2015-05-11 41 views
1

我有這樣的代碼:如何初始化實例在Java泛型方法

public <V> V getPropertiesByObject(V sample) throws TimeoutException { 
//settings fields using reflaction 
     return sample; 
    } 

我稱之爲是這樣的:

MyClass a = getPropertiesByObject(new MyClass()); 

只是因爲我不知道如何構建一個實例除此以外。

我寧願:

public <V> V getPropertiesByObject(Class<V> sample) throws TimeoutException { 
//how to create a new V instance? 
    return result; 
} 

有沒有辦法來修改我的原代碼?

+0

我真的沒有看到'getPropertiesByObject(new MyClass());'的問題。 – Radiodef

回答

1

如果V具有無參數構造函數,則可以使用Class<V>::newInstance()

public <V> V getPropertiesByObject(Class<V> sample) throws TimeoutException { 
    V result = sample.newInstance(); 
    // stuff on V 
    return result; 
} 

當然,你會使用這樣的:MyClass a = getPropertiesByObject(MyClass.class)

如果你必須指定一些參數,你可以這樣做:

public <V> V getPropertiesByObject(Class<V> sample, Object... params) throws TimeoutException { 
    V result = sample.newInstance(); 
    result.param0 = params[0]; 
    result.param1 = params[1]; 
    // etc 
    return result; 
} 

但在這兩種情況下,MyClass必須有一個無參數的構造函數。如果你不能編輯MyClass,你應該使用波希米亞人的回答,使用Constructor

+0

如果沒有無參數ctor? –

+0

@ user1065869那麼,您可以添加一個參數,並在我編輯的答案中指定參數,或者使用Bohemian的答案中指定的'Class :: getConstrutor(Class ... parameterTypes)': – NiziL

2

你可以使用反射 - 這裏有一個基本的實現,其展示的一種方法:

public <V> V getPropertiesByObject(Class<V> clazz, Object... params) throws TimeoutException { 
    Class<?>[] paramClasses = new Class<?>[params.length]; 
    for (int i =0; i < params.length; i++) 
     paramClasses[i] = params[i].getClass(); 
    V result = clazz.getConstructor(paramClasses).newInstance((Object[])params); 
    return result; 
} 

參數params,這可能是空的,是通過對應於這些參數的構造函數的參數。此代碼不會處理null值。這裏是你會如何稱呼它:

String str = getPropertiesByObject(String.class); // blank String 
Integer i = getPropertiesByObject(Integer.class, "1"); // 1 
+0

您正在失去泛型的好處與該實施。例如,「String string = getPropertiesByObject(String.class,new Object())」在編譯時不會報錯,但會在運行時崩潰。泛型的要點是在編譯時保證調用的正確性並防止運行時錯誤。 – vap78

+0

@ vap78當然 - 反射繞過不僅泛型,但所有靜態類型檢查。你可以通過編寫運行反射代碼的單元測試來保護自己免受運行時錯誤的影響 - 雖然不是嚴格的編譯時間檢查,編譯時間檢查足夠接近(因爲你在編譯代碼時運行所有的單元測試)。主要的缺點是你沒有從IDE獲得任何幫助,這種代碼很難閱讀。 – Bohemian

+0

我的意思是,對於建議的更改,泛型的使用沒有多大意義。方法簽名可以是「Object getPropertiesByObject(Class clazz,Object ... params)」,並且幾乎沒有什麼區別 - 調用者無論如何都必須注意傳遞與給定類的構造函數相匹配的參數。 – vap78

0

所以,你要創建一個可以創造任何可能的類的實例,並設置任何可能的領域,以實例的方法?

這很難。像GSON這樣的框架有相同的問題,它們要麼在所使用的bean中有無參數的構造函數,要麼提供一種爲特定類創建實例的方法(請參閱Is default no-args constructor mandatory for Gson?)。

否則爲你的具體情況 - 如果你知道你要實例化的類的集合,那麼你可以實現一個工廠類,它創建基於類對象的if-else-if-else類型的實例。 .. 結構體。