簡體   English   中英

如何使用泛型實例化Java中的類實例?

[英]How can I instantiate a class instance in java with generics?

如何使用泛型實例化Java中的類實例?

我試圖從XML文件讀取數據,然后實例化對象,以便可以將對象的其他屬性(從XML文件讀取)添加到對象中。 我認為最簡單的方法(這樣我就不必讀取類方法的名稱並查找設置方法)將是使用構造函數中的所有值實例化該對象。

我試圖做這樣的事情,所以我需要有這樣的事情: T obj = new Object()但要獲取對象類

    private static final boolean string_field = true;

    private static <T> T getObject(Element e, String[] fieldNames, boolean[] fieldTypes) {
        Object[] values = new Object[fieldNames.length];
        for (int i=0; i<fieldNames.length; i++) {
            values[i] = (fieldTypes[i]==string_field)? getStringValue(e, fieldNames[i])
                    : getIntegerValue(e, fieldNames[i]);
        }
        return new T(values);
    }

謝謝你的建議。

編輯:

這是我更新的代碼(未經測試):

    public static <T> List<T> populateObjectList(Document xmlDoc, String tagName,
            Class clazz, String[] fieldNames, Class[] fieldTypes) {
        List<T> objList = new ArrayList<T>();
        NodeList nl = xmlDoc.getElementsByTagName(tagName);
        if (nl!=null && nl.getLength()>0) {
            for (int i=0; i<nl.getLength(); i++) {
                Element e = (Element) nl.item(i);
                T t;
                try {
                    t = getObject(e, clazz, fieldNames, fieldTypes);
                    objList.add(t);
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (IllegalArgumentException ex) {
                } catch (InvocationTargetException ex) {
                } catch (NoSuchMethodException ex) {
                }
            }
        }
        return objList;
    }

    private static <T> T getObject(Element e, Class clazz, String[] fieldNames, Class[] fieldTypes)
            throws InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException {
        Object[] initargs = new Object[fieldNames.length];
        for (int i=0; i<fieldNames.length; i++) {
            initargs[i] = (fieldTypes[i].getName().equals("int"))?
                getIntegerValue(e, fieldNames[i])
                : getStringValue(e, fieldNames[i]);
        }
        return (T) clazz.getConstructor(fieldTypes).newInstance(initargs);
    }

我發布了這個信息,以便你們中的一些人了解我正在嘗試做的事情。

再次感謝大家的建議。

您不能實例化泛型類型。 Java泛型具有一個令人討厭的特性,稱為類型擦除 ,它基本上意味着JVM在運行時不知道泛型類或方法使用了哪種類型。 這是為了向后兼容通用類的通用版本,例如集合。

您可以做的是將Class<T> clazz添加到參數列表,然后用以下方法替換方法的結尾:

Class<?>[] paramTypes = new Class[values.length];
for (int i = 0; i < paramTypes.length; i++) {
    paramTypes[i] = values[i].getClass();
}
return clazz.getConstructor(paramTypes).newInstance(values);

如果該類沒有構造器以正確的順序采用正確的類型和數量的參數,則將引發異常。

CAVEAT:僅當構造函數的參數類型與對象類型完全相同時 ,此方法才有效。 例如,如果values包含{ "Hello", new Integer(2) } ,那么它將僅找到帶有簽名SomeClass(String, Integer)的構造函數,而不是帶有簽名SomeClass(Object, Object)的構造函數。

您甚至怎么知道T包含一個采用單個Object[]參數的構造函數? 解決此問題的方法是傳入一個抽象工廠。

interface ThingFactory { // Choose an appropriate name.
    T create(Object[] values);
}

private static <T> T getObject(
    ThingFactory<T> factory, Element e, String[] fieldNames, boolean[] fieldTypes
) { 
    ...
    return factory.create(values);
}

現在, T甚至可能沒有一個很奇怪的Object[]構造函數。 T可能是抽象類型。 工廠可能會根據參數返回不同的類型。 也許有時這些產品是可以緩存的不可變對象。

您不能執行new T()因為在運行時, T實際上只是Object 編譯器使用泛型進行類型檢查(例如,您不能將Integer放入List<String> ),但隨后會將泛型信息丟棄。 該方法針對所有類型的參數都有一個已編譯的副本,因此它無法知道您希望實例化哪種類型。

閱讀有關類型擦除的更多信息。

我真的看不到您的問題,無法使用obj.getClass嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM