2017-08-18 51 views
-3

我有以下常用的靜態工廠方法檢查,他們中的每一個在內部使用new關鍵字來創建對象每個靜態工廠方法在內部使用新的關鍵字來創建對象嗎?

  1. 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); 
    } 
    
  2. 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關鍵字創建對象?

+3

'Long.valueOf'有時使用預先創建的對象從池 –

+1

創建一個新對象的唯一方法是使用'new'(或反射)。但是,工廠可能不會自己創建對象,而是使用緩存或預先創建的對象。 –

+0

靜態和新功能無關,所以很可能它們確實存在,或者您可以自己創建它們 –

回答

1

簡短的回答是(在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)

1

你有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)有時,newnewInstance()所創建的對象可以被高速緩存以避免創建多次相同的對象。
這對不可變對象有意義。