簡體   English   中英

java泛型運行時類型

[英]java generics runtime type

我在Ian Robertson找到的帖子中有一個很好的實用方法,用於確定Java類類型參數的運行時類。 它比快速版本快了幾步:

ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
Class<?> c = (Class<?>) pt.getActualTypeArguments()[0]

這兩種方法的作用類似於從抽象參數化父class Foo<T> extends Bar<T>繼承的參數化子class Foo<T> extends Bar<T>class Foo<T> extends Bar<T> ),或者參數化抽象類的匿名實例( new Foo<Bar>() {} ),以及用具體類型實例化。


我失敗的地方是嘗試對通過類型參數實例化的其他對象執行相同的操作。 相關的類對象是:

public class Foo {/* code omitted for brevity */}

public class MyFoo extends Foo {/* code omitted for brevity */}

public abstract class AbstractLoader<T extends Foo> {/* code omitted for brevity */}

public abstract class AbstractReader<T extends Foo> {/* code omitted for brevity */}

public class MyReader<T extends Foo> extends AbstractReader<T> {/* code omitted for brevity */}

public class Loader<T extends Foo> extends AbstractLoader<T> {
    /* code omitted for brevity */

    public MyReader<T> getReader() {
        // Parameterized type "T" doesn't seem to carry through here
        return new MyReader<T>();
    }
}

示例代碼:

static void main(String... s) {
    Loader<MyFoo> loader = new Loader<>(); // new Loader<MyFoo>() for Java < 1.7
    MyReader<MyFoo> = loader.getReader();

    ParameterizedType pt = (ParameterizedType)loader.getClass().getGenericSuperclass();
    System.out.println("LoaderType = " + pt.getActualTypeArguments()[0]);
    // Prints: LoaderType = MyFoo

    pt = (ParameterizedType)reader.getClass().getGenericSuperclass();
    System.out.println("ReaderType = " + pt.getActualTypeArguments()[0]);
    // Prints: ReaderType = T
}

直覺告訴我這種“應該”是可能的,但我似乎無法找到正確的答案。 OTOH,這可能是由於類型擦除而“無法做到”的另一個例子。

你完全誤解了什么。 new Loader();之間沒有差異 new Loader(); new Loader<Integer>(); ,和new Loader<Object>(); 等等。在運行時。 不可能區分它們。 現在就把這個想法從頭腦中解脫出來。

如果我們創建一個類,那么關於該類的聲明中的類型(包括泛型),包括超類,方法類型,字段類型等,都存儲在類文件中。 可以在運行時檢索此信息。

因此,當您有new Foo<Bar>() {}時,會創建某個類(匿名類)的實例,該類擴展具有特定類型參數的泛型類型。 它類似於:

class SomeAnonymousClass extends Foo<Bar> {
}
new SomeAnonymousClass()

事實上, Foo<Bar>在編譯時被硬編碼為此類的類,這在運行時是可檢索的。

但是你的代碼沒有做這種事。 你沒有創建Loader任何子類。

您找不到對象的類型參數 - 它在運行時被刪除。

如果可以,那么Loader loader0Loader<MyFoo> loader1Loader<MyBar> loader2會給出不同的結果。 這種差異必須以某種方式在運行時表示:直接在對象中,或通過引用不同的類。 第一個變體需要為每個實例添加額外的內存,並被認為是不合適的。 第二個需要在運行時創建類,因為類Loader本身不能包含參數化類Loader的所有可能變體 - 它們在編譯時是未知的。

暫無
暫無

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

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