Effective Java 学习-类和接口

Effective Java 学习-类和接口

左岸 236 2022-12-16

类和接口

类和接口是Java编程语言的核心,也是Java语言的基本抽象单元,Java语言提供了许多强大的基本元素,供程序员用来设计类和接口.

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

区分一个组件设计得好不好,唯一重要的因素在于,它对于外部的其他组件而言,是否隐藏了其内部数据和其他实现细节。设计良好的组件会隐藏所有实现细节,把API与实现清晰的隔离开来。组件之间通过API进行通信,一个模块不需要知道其他模块的内部工作情况.这个概念是称为信息隐藏或封装.是软件设计的基本原则之一。

  • 尽可能地使每个类或者成员不被外界访问

总而言之.应该始终尽可能合理地降低程序元素的可访问性,在仔细地设计了一个最小的公有API之后,应该防止把任何散乱的类,接口或者成员变成API的一部分,除了公有静态final域的特殊情形之外。公有类不应该包含公有域,并且要确保公有静态final域所有引用对象都是不可变的

16. 要在公有类而非公有域中使用方法

  • 对于公有类(类可以在它所在的包之外进行访问),必须通过get、set方法来访问成员变量
  • 对于包级私有、私有嵌套类,直接暴露它的数据域并没有本质错误。

17. 使可变性最小化

为了使类成为不可变,要遵循下面五条规则:

  • 不要提供任何会修改对象状态的方法(也称为设值方法)
  • 保证类不会被扩展
  • 声明所有的域都是final的
  • 声明所有的域都是私有的
  • 确保对于任何可变的组件的互斥访问

不可变类的优点

  • 不可变对象比较简单
  • 不可变对象本质上是线程安全的,它们不要求同步
  • 不可变对象可以被自由地共享
  • 不可变对象无偿提供了失败的原子性

不可变的缺点

  • 不可变对象真正唯一的缺点是,对每个不同的值都需要一个单独的对象,创建对象的代价可能很高

总之,除非有很好的理由要让类成为可变类,否则它就应该是不可变的,如果对于某些类不可变是不切实际的,仍应尽可能地限制它的可变形,降低对象可以存在的状态数,

  • 除非令人信服的理由要是域变成非final得,否则要使每个域都是 private final 的

  • 构造器应该创建完全初始化的对象,并建立起所有的约束关系

  • 不要在构造器或者静态工厂之外在提供公有的初始化方法

18. 组合优于继承

继承是实现代码重用的有力手段,但它并非永远是完成这项工作的最佳工具,使用不当会导致软件变得很脆弱。

在包的内部使用继承是非常安全的,在哪里子类和超类的实现都处在同一个程序员的控制之下.对于专门为了继承而设计并且具有很好的文档说明的类来说,使用继承也是非常安全的,对普通的具体类,进行跨越包边界的继承则是非常危险的

继承的缺点

  • 与方法调用不同的是,继承打破了封装性

简而言之,继承的功能非常强大,但是也存在诸多问题,因为它违背了封装原则有当子类和超类之间确实存在子类型关系时,使用继承才是恰当的 即使如此,如果子类和超类处在不同的包中,并且超类并不是为了继承 计的,那么继承将会导致脆弱性, 为了避免这种脆弱性,可以用组合和转发机制来代替继承,尤其是当存在适当的接口可以实现包装类的时候 包装类不仅比子类更加健壮,而且功能也更加强大