1.什么是静态工厂方法
类可以提供一个共有的静态工厂方法(static factory method),它只是一个放回类的实例的静态方法。
下面是一个来自Boolean(基本类型boolean的装箱类)的简单实例。
/** 将boolean基本类型转换成了一个Boolean对象引用*/
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
知识点:new 究竟做了什么?
简单来说:在JAVA里就是创建一个新的实例,或者说一个新的对象,一个普通类在没有实例化之前,就是new之前,它的属性,方法等等在内存中都是不存在的。只有使用new了以后,这个类的一些东西在内存中才会真的存在,也就是说只有new了之后,这个类才能用。
2.静态工厂方法的优势
2.1 静态工厂方法与构造器不同的第一优势在于,它们有名字。
如:BigInteger(int,int,Random)返回的BigInteger可能为素数,如果用名为
BigInteger.probablePrime的静态工厂方法来表示,显示更为清楚。
/** BigInteger(int,int,Random)*/
public BigInteger(int bitLength, int certainty, Random rnd) {
BigInteger prime;
if (bitLength < 2)
throw new ArithmeticException("bitLength < 2");
prime = (bitLength < SMALL_PRIME_THRESHOLD
? smallPrime(bitLength, certainty, rnd)
: largePrime(bitLength, certainty, rnd));
signum = 1;
mag = prime.mag;
}
/** BigInteger.probablePrime*/
public static BigInteger probablePrime(int bitLength, Random rnd) {
if (bitLength < 2)
throw new ArithmeticException("bitLength < 2");
return (bitLength < SMALL_PRIME_THRESHOLD ?
smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :
largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));
}
2.2 第二大优势在于,不必再每次调用他们的时候都创建一个新的对象。
这使得不可变类可以使用预先构建好的实例,或者将构建好的实例缓存起来,进行重复利用,从而避免创建不必要的重复对象。实例受控是的类可以确保他是一个单例或者是不可实例化的。
/** 不能通过构造器创建*/
private Sort(Direction direction, List<String> properties) {
if (properties == null || properties.isEmpty()) {
throw new IllegalArgumentException("You have to provide at least one property to sort by!");
}
this.orders = properties.stream() //
.map(it -> new Order(direction, it)) //
.collect(Collectors.toList());
}
/** 通过静态工厂方法创建*/
public static Sort by(Direction direction, String... properties) {
Assert.notNull(direction, "Direction must not be null!");
Assert.notNull(properties, "Properties must not be null!");
Assert.isTrue(properties.length > 0, "At least one property must be given!");
return Sort.by(Arrays.stream(properties)//
.map(it -> new Order(direction, it))//
.collect(Collectors.toList()));
}
2.3 第三大优势在于,它们可以放回原返回类型的任何子类型的对象。
2.4 第四大优势在于,返回的对象的类可以随着每次调用而发生变化,这取决与静态工厂的参数。
/** 通过泛型的床底改变放回值 */
public static <E extends Enum<E>> EnumSet<E> of(E e) {
EnumSet<E> result = noneOf(e.getDeclaringClass());
result.add(e);
return result;
}
2.5 第五大优势在于,方法返回的对象所属的类,在编写包含该静态工厂方法的类是可以不存在。
/** 返回Connection,该类为DriverManager.class */
@CallerSensitive
public static Connection getConnection(String url,
java.util.Properties info) throws SQLException {
return (getConnection(url, info, Reflection.getCallerClass()));
}
3.静态工厂方法的缺点
- 3.1 类如果不包含共有的或者受保护的构造器,就不能被子类化。
- 3.2 程序员很难发现静态工厂方法。
4.总结
简而言之,静态工厂方法和公有构造器都有用处,我们需要理解他们各自的长处。静态工厂经常更加合适,因此切忌第一反应就是提供公有的构造器,而不先考虑静态工厂。