Effective Java之类和接口

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Effective Java之类和接口脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

使类和成员的可访问性最小化

封装的好处

封装的规则

  • 尽量的使每一个类或成员不被外界访问@H_404_25@
  • 如果1个包级私有的顶层类只在某1类的内部被用到,应当斟酌使它成为唯1使用它的那个类的私有嵌套类@H_404_25@
  • 成员变量不能是公然的,常量是例外。

    @H_404_25@
  • 长度为非0的数组总是可变的,因此用public static final修饰的数组容易带来潜伏的安全漏洞

    @H_404_25@

有两种解决方式,1是将数组变成私有,并添加1个公有的不可变列表

PRivate static final Thing[] PRIVATE_VALUES = {}; public static final List<Thing> VALUES= Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

2是使数组变成私有的,并添加1个公有方法,返回数组的备份。

private static final Thing[] PRIVATE_VALUES = {}; public static final Thing[] values() { return PRIVATE_VALUES.clone(); }

使用方法访问类成员变量

使用setter和getter方法访问类成员变量,有以下好处
* 可以添加束缚条件
* 可以灵活的修改该类的内部表示方式

如何设计不可变类

不可变类遵守的规则

  • 不要提供任何会修改对象属性方法@H_404_25@
  • 保证类不会扩大@H_404_25@
  • 使所有域都是final的@H_404_25@
  • 所有的域都成为私有的@H_404_25@
  • 确保对任何可变组件的互斥访问
    @H_404_25@

不可变类的设计

  • 不可变对象本质上是线程安全的,它们不要求同步。

    @H_404_25@
  • 不要用为不可变对象提供clone方法或拷贝构造器

    @H_404_25@
  • 不可变类的缺点是对不同的值都需要1个单独的对象。

    @H_404_25@
  • 声明构造器为private可以避免该类被继承。

    @H_404_25@
  • 许多不可变类具有多个非final域,当它们第1次被要求计算时,把1些开消昂贵的结果缓存到这些域中,以便下次再次要求一样的计算,就直接返回这些缓存的值。@H_404_25@
  • 如果需要让不可变类实现Serializable接口,就必须显示的提供1个readObjectreadResolve方法,或使用ObjectOutputStream.wrITeUnsharedObjectInputStream.readUnshared方法。@H_404_25@
  • 如果1个类不能被设计成不可变的,应当尽可能限制其可变性。@H_404_25@

组合优于继承

4.1 继承的缺点

  • 继承打破了封装性,子类依赖超类中特定功能的实现细节,但超类的实现有可能随着发行版本的不同而有所变化。@H_404_25@
  • 如果超类在后续版本中添加了1个新的方法,该方法与子类中的某1方法签名相同但返回值不同,将致使编译毛病。@H_404_25@

取代继承的方式

  • 使用转发的方式代替继承(装潢器模式)@H_404_25@
  • 采取组合方式代替继承@H_404_25@

甚么时候需要继承

  • 只有当二者之间确切存在“is-a”关系的时候@H_404_25@
  • 当超类的API设计有缺点时,采取继承机制会传播缺点,复合则允许新的API隐藏这类缺点@H_404_25@

要末为继承而设计,并提供文档说明,要末制止继承

  • 该类必须有文档说明它可覆盖的方法的自用性
    @H_404_25@
  • 构造器不能调用可被覆盖的方法
    超类构造器将在子类构造器之前被调用,所以子类中覆盖的版本方法将在子类构造器之前被调用,如果该方法依赖构造器所履行的初始化方法,那末将有可能致使程序失败。@H_404_25@
  • 对为继承而设计的类中实现CloneableSerializable接口,不管clone还是readObject都不可以调用可覆盖的方法,不管是间接还是直接。@H_404_25@
  • 对为继承而设计的类中实现Serializable,并且该来有readResolvewriteReplace方法,就必须使其成为protected,避免子类疏忽这两个方法。@H_404_25@
  • 对不专门为继承而设计的类,最好要制止子类化@H_404_25@

接口优于抽象

  • 现有类可以很容易被更新,以实现新的接口@H_404_25@
  • 接口是定义mixin的理想选择
    @H_404_25@
  • 接口允许我们构造非层次结构的类型框架@H_404_25@
  • 接口可以安全的增强类的功能@H_404_25@
  • 可以将接口和抽象类结合起来,提供1个抽象的骨架实现。例如AbstractCollection类@H_404_25@

接口只用于定义类型

接口应当只被用来定义类型,不应当用于声明常量

优先斟酌静态成员类

  • 嵌套类(nested class)是指定义在另外一个类的内部的类,包括静态成员类、非静态成员类、匿名类、局部类。@H_404_25@
  • 嵌套类存在的目的应当只是为它的外围类提供服务。@H_404_25@
  • 如果1个嵌套类在单个方法以外依然可见,或它太长了,不合适放在方法内部,就应当使用成员类。@H_404_25@
  • 如果成员类的每个实例都需要1个指向外围实例的援用,就要把成员类声明为非静态的。否则就要声明为静态的。@H_404_25@
  • 如果这个嵌套类属于1个方法的内部,并且你只需要在1个地方创建实例,而且已有1个预置的类型可以说明这个类的特点,就要把它做成匿名类。@H_404_25@

静态成员类

  • 静态成员类是外围类的1个静态成员,与其他静态成员1样,遵照一样的可访问性规则。@H_404_25@
  • 静态成员类的常见用法是作为公有的辅助类,仅当与它的外部类1起使用时才成心义。@H_404_25@
  • 私有静态成员类的另外一个常见用法是作为外围类所代表对象的1个组件。@H_404_25@

非静态成员类

  • 非静态成员类的1个常见用法是定义1个Adapter,它允许外部类的实例被看做另外一个不相干的类的实例。例如Map接口中的集合视图。@H_404_25@
  • 非静态成员类的每一个实例都将包括1个额外的指向外围对象的援用,这需要消耗额外的空间和时间,并且会致使外围实例在符合垃圾回收时仍然得以保存,因此除非必须访问外围实例,否则要始终把成员类声明为static。@H_404_25@

匿名类

  • 匿名类要尽可能简短,否则会影响程序的可读性。10行或更少。@H_404_25@
  • 匿名类的1个常见用法是动态的创建函数对象,例如匿名Comparator实例。@H_404_25@
  • 匿名类的另外一个常见用法是创建进程对象,例如RunnableThread。@H_404_25@

脚本宝典总结

以上是脚本宝典为你收集整理的Effective Java之类和接口全部内容,希望文章能够帮你解决Effective Java之类和接口所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: