每个静态工厂方法在内部使用新的关键字来创建对象吗?
我有以下常用的静态工厂方法检查,他们中的每一个在内部使用new关键字来创建对象每个静态工厂方法在内部使用新的关键字来创建对象吗?
-
valueOf()
public static String More ...valueOf(char c) { char data[] = {c}; return new String(data, true); } public static String More ...valueOf(int i) { return Integer.toString(i); }
-
toString()
回报return new String(buf, true);
来源:
java.lang.String.java
两个相关源的部分:getInstance()
public static Calendar More ...getInstance()
{
Calendar cal = createCalendar(TimeZone.getDefaultRef(),
Locale.getDefault(Locale.Category.FORMAT));
cal.sharedZone = true;
return cal;
}
createCalendar
方法在内部创建使用new
关键字Calendar
对象。
来源:java.util.Calendar.java
是否有任何静态工厂方法,其内部不使用new
关键字创建对象?
简短的回答是(在Java中)创建对象的唯一方法是new
。
某处下游的工厂方法必须返回使用new
构建的对象。
有一些全局对象,如System.out
可以(原则上)通过运行时环境以其他方式实例化。
这并不意味着工厂方法通过一对一调用new
来调用它们。 例如,需要Integer.valueof(int v)
来缓存至少在[-128,127]范围内的值。 因此在第一次拨打Integer.valueof(0)
之前或期间new
应被调用(或实际调用),但随后的调用将返回缓存的对象。
参见https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#valueOf(int)
你有3种方式:
1)工厂,其类型的实例在编译时已知使用new
操作。
这是最好的方式,因为它是直接的,编译器还强制执行对象创建的有效性。
2)在某些特定情况下,实例化的类型在编译时可能不知道。
在这种情况下,反射是不可避免的。
它依靠Class.forName()
来检索类和Class.newInstance()
方法来实例化类。
查看例如java.net.InetAddress
类。
它有一个loadImpl()
工厂方法,以这种方式工作。
您可以看到Class.forName()
和Class.newInstance()
是可能抛出“技术”异常的方法,这些方法仅在运行时才会被发现。
static InetAddressImpl loadImpl(String implName) {
Object impl = null;
/*
* Property "impl.prefix" will be prepended to the classname
* of the implementation object we instantiate, to which we
* delegate the real work (like native methods). This
* property can vary across implementations of the java.
* classes. The default is an empty String "".
*/
String prefix = AccessController.doPrivileged(
new GetPropertyAction("impl.prefix", ""));
try {
impl = Class.forName("java.net." + prefix + implName).newInstance();
} catch (ClassNotFoundException e) {
System.err.println("Class not found: java.net." + prefix +
implName + ":\ncheck impl.prefix property " +
"in your properties file.");
} catch (InstantiationException e) {
System.err.println("Could not instantiate: java.net." + prefix +
implName + ":\ncheck impl.prefix property " +
"in your properties file.");
} catch (IllegalAccessException e) {
System.err.println("Cannot access class: java.net." + prefix +
implName + ":\ncheck impl.prefix property " +
"in your properties file.");
}
if (impl == null) {
try {
impl = Class.forName(implName).newInstance();
} catch (Exception e) {
throw new Error("System property impl.prefix incorrect");
}
}
return (InetAddressImpl) impl;
}
3)有时,new
或newInstance()
所创建的对象可以被高速缓存以避免创建多次相同的对象。
这对不可变对象有意义。
'Long.valueOf'有时使用预先创建的对象从池 –
创建一个新对象的唯一方法是使用'new'(或反射)。但是,工厂可能不会自己创建对象,而是使用缓存或预先创建的对象。 –
静态和新功能无关,所以很可能它们确实存在,或者您可以自己创建它们 –