Java 是否每个静态工厂方法在内部都使用new关键字来创建对象?

Java 是否每个静态工厂方法在内部都使用new关键字来创建对象?,java,methods,static,Java,Methods,Static,我检查了以下常用的静态工厂方法,它们中的每一个都在内部使用new关键字来创建对象 价值 toString返回新的Stringbuf,true 来源:java.lang.String.java 相关资料来源第二部分:getInstance createCalendar方法使用new关键字在内部创建日历对象 来源:java.util.Calendar.java 是否有任何静态工厂方法,在内部不使用new关键字创建对象?您有3种方法: 1要实例化的类型在编译时已知的工厂使用新运算符。 这是最好的方法,

我检查了以下常用的静态工厂方法,它们中的每一个都在内部使用new关键字来创建对象

价值

toString返回新的Stringbuf,true

来源:java.lang.String.java

相关资料来源第二部分:getInstance

createCalendar方法使用new关键字在内部创建日历对象

来源:java.util.Calendar.java

是否有任何静态工厂方法,在内部不使用new关键字创建对象?

您有3种方法:

1要实例化的类型在编译时已知的工厂使用新运算符。 这是最好的方法,因为它是直截了当的,而且编译器还强制执行对象创建的有效性

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创建的对象,以避免多次创建同一对象。
这对于不可变的对象可能有意义。

简单的回答是,在Java中,创建对象的唯一方法是新的

工厂方法必须返回使用新方法构造的对象

有些全局对象,如System.out,原则上可以通过运行时环境以其他方式实例化

这并不意味着工厂方法通过调用一对一地调用新方法。 例如,Integer.valueofint v需要缓存至少在[-128127]范围内的值。 因此,在第一次调用Integer.valueof0之前或期间,应调用或实际上调用new,但后续调用将返回缓存对象


请参见

Long.valueOf有时使用池中预先创建的对象创建新对象的唯一方法是使用new或reflection。但是,工厂本身可能不会创建对象,而是使用缓存或预创建的对象。静态对象和新对象在功能上不相关,因此很可能它们确实存在,或者您可以自己创建它们
public static Calendar More ...getInstance()
{
    Calendar cal = createCalendar(TimeZone.getDefaultRef(), 
    Locale.getDefault(Locale.Category.FORMAT));
    cal.sharedZone = true;
    return cal;
}
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;
}