title: Effective Java 3rd 读书笔记(一)
date: 2019-02-19 18:05:09
tags: java
categories: 读书笔记
才发现 Effective Java 已经出到第三版了,重新看一遍并且记录下,这一篇先更静态工厂方法
静态工厂方法
使用静态方法向外界提供自身实例的方法
Fragment fragment = MyFragment.newIntance();
// or
Calendar calendar = Calendar.getInstance();
使用静态工厂代替构造方法
在原生java中,有很多使用静态工厂方法代替构造方法的例子,比如Boolean
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
使用静态工厂有几个优点:
可以使用名字去提示这个方法的返回
不使用new
去创建实例,通过静态方法名字去代表不同创建实例的行为,例如valueOf
,newInstance
等,这样代码的编写和阅读都能够更清晰。
允许在每次调用时,不创建新的对象
例如Boolean
: Boolean.valueOf(boolean),永远不会返回新的对象。因此可以省去频繁创建相同对象所造成的性能损耗,减少内存占用;同时做到“控制实例”。可以参考享元模式的思路。此外java中的单例模式也是使用静态工厂方法,具体写法参考单例模式的八种写法
可以返回该类型的任何子类
作为输入参数的函数,返回对象的类可以随调用的不同而变化。
例如EnumSet
类没有公共构造函数,只有静态工厂。
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum<?>[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
//根据不同长度,返回不同的子类实例
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
当编写包含方法的类时,返回对象的类不需要存在
考虑服务提供者框架(service provider frameworks),其包含提供者注册API(提供者用来注册实现),服务接口,以及服务准入API(客户端用来获取服务实例),此外还有可选的第四个组件:服务提供接口,用于描述生成服务接口实例的工厂对象。在没有服务提供者接口的情况下,必须以反射的方式实例化实现
通过服务准入API,客户端可以通过定制标准来选择不同的实现。参考JDBC
:Connection
=服务接口;DriverManager.registerDriver
=提供者注册API;DriverManager.getConnection
=服务准入API
//TODO JDBC源码分析
静态工厂常用名称
- from: 一种型转换方法,该方法接受单个参数并返回该类型的相应实例
- of: 一个聚合方法,它接受多个参数并返回一个包含这些参数的此类实例
- valueOf: 一种替代 from 和 of 但更冗长的方法
例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
- getInstance: 返回一个实例,该实例由其参数(如果有的话)描述,但不具有相同的值
- newInstance: 只是该方法保证每个调用都返回一个新实例
- get{Type}: 与
getInstance
类似,但如果工厂方法位于不同的类中,则使用此方法。类型是工厂方法返回的对象类型 - newType: 与
newInstance
类似,但是如果工厂方法在不同的类中使用。类型是工厂方法返回的对象类型