- 第二章:创建和销毁对象
- 用静态方法代替构造器:
- 好处:
- 有名称,代码更易读
- 对于对象可以复用的情况,不用每次都创建新的对象·
- 为重复的调用返回相同的对象,控制对象的数量,称为实例受控的类
- 可以返回原类型任何子类型的对象,选择返回的对象的时候有了更大的灵活性
- 适用于“基于接口的框架”
- 可以根据静态工厂的参数值,返回不同类的对象
- 方法返回对象所属的类,在编写该静态工厂方法的时候可以不存在
- 应用是“服务提供者框架”
- 服务提供者框架:
- 定义:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把它们从多个实现中解耦出来
- 组件:
- 服务接口
- 提供者注册API
- 服务访问API
- 服务提供者接口(可选)
- 坏处:
- 有可能不能被子类化:类不含邮public或者protected的构造器
- 即使提供了,但是不能以一种比较直观的方式告诉调用者,很难发现!
- 静态工厂的惯用名称:
- from:类型转换方法
- of:聚合方法,多个参数,把多个参数合并起来并返回该类的一个实例
- valveOf:
- instance or getInstance 返回的实例是通过参数描述的,有点像单例,但不完全一样
- create or newInstance 类似于getInstance 但是每次都返回一个新的实例
- 总结:优先考虑静态工厂,而不是构造器
- 好处:
- 遇到多个构造器参数的时候考虑使用构建器(Builder)
- 比如Android中Dialog的创建方式
- 当Builder模式应用于类层次结构
- 坏处:为了创建一个对象还要额外再创建一个对象
- 用私有构造器或者枚举类型强化Singleton属性
- 实现单例模式的两种常见方法:
- 方法:
- 持有一个静态final的公有域
- 静态工厂方法
- 缺点:
- 可以用哪个反射的方式生成新的实例
- 要注意序列化反序列化可能会生成新的实例
- 方法:
- 第三种方法:
- 声明一个包含单个元素的枚举类型:
- 优点:
- 不用管序列化反序列化问题
- 缺点:
- 不适用于必须扩展一个超类而不是emun的情况
- 优点:
- 声明一个包含单个元素的枚举类型:
- 实现单例模式的两种常见方法:
- 通过私有构造器强化不可实例化的能力
- 比如系统的一些工具类:Math,Arrays等等实例化没有什么意义
- 抽象类避免被实例化行不通的,因为他的子类可以被实例化
- 优先考虑依赖注入来引用资源
- 依赖注入:当创建一个新的实例时,就将资源传到构造器中
- 依赖注入的资源具有不可变性,一个资源可以被多个地方依赖注入
- 依赖注入也同样适用于构造器、静态工厂和构建器
- java8中增加的接口Supplier
表示工厂 - 优缺点:
- ✔️提升了灵活性和可测试性
- ❌会导致项目凌乱不堪,可以用dagger来解决
- 避免创建不必要的对象:
- 如果对象是不可变的,那么他就始终可以被复用
- 尽量重用一个对象,而不是创建对象
- 比如String:
- String s = new String(“hello”) 这种语句会创建一个对象
- String s =“hello” 而这个语句在jvm中会保证同一台虚拟机中运行的代码只要他们包含相同的字符串常量,就可以被重用
- 优先使用静态工厂方法而不是构造器来避免创建不必要的对象 比如Boolean.valueof
- 对于创建成本高的类,如果重复的使用这些类,建议缓存下来重用
- 优先使用基本类型而不是装箱类型,要当心无意识的自动装箱
- 维护对象池来避免创建对象并不是一种好的做法:
- 除非是比较特殊的场景,比如数据库的连接池
- 一般情况下,维护对象池代码会乱,而且现代jvm高度优化的垃圾回收机制很容易超过轻量级对象池的性能
- 消除过期的对象引用:
- 如果一个对象引用被无意识地保留起来了,垃圾回收机制不仅不会处理这个对象,而且也不会处理被这个对象所引用的其他对象
- 不用的对象要及时清除(将对象的所有引用置为null)还有一个好处是,如果错误的应用对象会立即抛出空指针异常
- 缓存可能会导致内存泄漏:
- 使用WeakHashMap:只要缓存者外不存在对某个项的引用,他就会被删除
- LinkedHashMap的removeEldestEntry可以移除掉最早的引用
- 避免使用终结方法(finalizer)和清除方法
- 优先使用try-with-resources而不是try-finally
- 用try-finally存在多个需要关闭的引用不仅会让代码一团糟关闭方法本身也会存在异常,而且第二个异常有可能会抹除第一个异常,看不到异常堆栈
- try-with-resource
- 必须实现AutoCloseable代表是可被关闭的资源
- 用静态方法代替构造器:
- 第三章:对于所有对象都通用的方法
- 覆盖equals时请遵守约定
- 覆盖equals时总要覆盖hashcode
- 始终要覆盖toString
- 谨慎的覆盖clone
- 考虑实现Comparable接口
- 第四章:类和接口
- 使类和成员的可访问性最小化
- 隐藏实现细节,把API与实现细节区隔离开来,封装—软件设计的基本原则之一
- 好处:
- 解除各组件的耦合关系,独立开发和测试,加快了开发速度,减轻了维护负担
- 降低了构建大型系统的风险
- 怎么做?
- java的访问控制机制
- 尽可能使每个类或者成员不被外界访问
- 尽量把顶级类做成包级别私有的而不是公有的,如果做成公有的,就有责任永远支持它 ->降低不必要的公有类的可访问性
- 如果一个顶级类只是在某一个类的内部使用,那么就应该把它做成哪个类的私有嵌套类
- 包含公有可变域的类决不能是公有的
- 让类具有公有的静态final数组域或者返回这种域的方法是错误的
- 使类和成员的可访问性最小化
[读书笔记]Effective Java
2019-08-16