目前,我有一種情況,我試圖實體化一個類的物件,將類作為引數給出,并使用默認值(例如 null)初始化物件的屬性。問題是,我的班級沒有任何建構式,由于各種原因我無法添加一個。可能的類也沒有通過超類連接,它們都是 Object 的直接子類。我試圖實體化的類如下所示:
public class MyClass {
public String prop1;
public int prop2;
public int prop3;
}
這意味著類只包含屬性而沒有方法,因此沒有顯式建構式。如果我事先知道課程,我當然可以這樣做:
public MyClass create() {
return new MyClass();
}
在上述情況下,編譯器為 MyClass 生成一個默認建構式,并使用它們的默認值啟動所有屬性。正如評論中指出的那樣,這意味著我在技術上有一個建構式,但我只能使用“new”關鍵字并事先了解該類來訪問該建構式。現在,我想要做的(基本上)如下:
public someClass create(Class<?> someClass) {
return new someClass();
}
當然,'new' 關鍵字在這種情況下不起作用,所以我嘗試了很多替代方案,但到目前為止都沒有奏效:
- 使用
someClass.getConstructor().newInstance()或someClass.getDeclaredConstructor().newInstance()。代碼已編譯,但我得到了預期的“NoSuchMethodException”,因為它找不到 someClass 的 <init> 方法或建構式 - 從像
Object newObject = someClass.cast(new Object()). 正如預期的那樣,這也會崩潰,因為您無法從超類轉換為子類
我現在唯一真正的替代方法是,由于可能的類的范圍不是太大,因此對每個類使用“instanceof”,然后在每個分支中只使用“new”關鍵字來想象一個巨大的 switch-case。但正如你想象的那樣,我不太喜歡那樣。
那么我是在嘗試做不可能的事情還是有辦法做到這一點?
解決方案:原來第一種方法是完全有效的,它只是不起作用,因為我的一些類是陣列,我沒有意識到。如果我采用陣列中物件的實際類,它就可以作業。抱歉造成混亂,這一直是我的錯誤!
uj5u.com熱心網友回復:
方法Class::getConstructor回傳公共建構式,因此它可能不會檢測到非公共無引數建構式:
回傳一個 Constructor 物件,該物件反映了此 Class 物件表示的類的指定公共建構式。parameterTypes 引數是一個 Class 物件陣列,這些物件按照宣告的順序標識建構式的形參型別。如果此 Class 物件表示在非靜態背景關系中宣告的內部類,則形參型別包括顯式封閉實體作為第一個引數。
要反映的建構式是此 Class 物件表示的類的公共建構式,其形參型別與 parameterTypes 指定的型別相匹配。
因此,方法create(Class<?> someClass)應該被定義和實作來呼叫Class::newInstance,然而,因為它從Java 9 開始被棄用,它應該被替換為someClass.getDeclaredConstructor().newInstance().
此外,檢查例外可能會被捕獲并包裝到一個 RuntimeException
public static <T> T create(Class<T> someClass) {
try {
return someClass.getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
throw new RuntimeException("Failed to create instance of class " someClass.getName(), ex);
}
}
測驗:
MyClass mc = create(MyClass.class);
System.out.println(mc); // overridden toString
輸出
MyClass :: prop1 = null; prop2 = 0; prop3 = 0
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/311161.html
