class A<T> extends B<T> {}
class B<T> implements ParameterizedType {
@Override
public Type[] getActualTypeArguments() {
Type superclass = this.getClass().getGenericSuperclass();
System.out.println("A superClass:" superclass);
return superclass.getClass().getTypeParameters();
}
@Override
public Type getRawType() {
return null;
}
@Override
public Type getOwnerType() {
return null;
}
}
public static void main(String[] args) {
Action<String> action = new Action<>();
action.getActualTypeArguments();
B<String> b = new B<>();
b.getActualTypeArguments();
}
結果是:
superClass:class java.lang.Object
superClass:Main$Action<T>
我想得到正確的結果(java.lang.String),我該怎么辦。我嘗試this.getClass().getSuperClass().getGenericSuperclass();在 B 類中進行更改,但結果也是 java.lang.Object...
uj5u.com熱心網友回復:
B<String> b = new B<>();
不可能出去,這String就是擦除的意思。沒有多少麻煩.getActualTypeArguments()或getGenericType()讓您對此進行最后的處理。如果可能的話,您不認為會有相當簡單的 API 來解決這個問題嗎?
new B<String>()一點一點,在記憶中,和之間沒有任何區別new B<Integer>。這些泛型幾乎是編譯器用來將事物鏈接在一起的所有東西。當你把事情搞砸時,編譯器會抱怨,java.exe不知道泛型是什么。
簽名中的泛型仍然存在 - 它們必須這樣做,因為編譯器需要它們來完成它的作業,并且編譯器通常只有編譯后的代碼可以使用(例如,要編譯一個 hello world 程式,你需要java.lang.String類,但你不需要' t 需要它的來源)。就java.exe目前而言,這些是注釋——它們的存在僅供 javac 查看。
但是,您可以通過反思來解決這些問題,這就是getGenericSuperclass()爵士樂的全部內容。B<String> b = new B<>()因此,雖然您無法將字串從B<String> b = new B<>() {}. 那是一個匿名的內部類文字。如果你不知道它們是什么,那就是語法糖:
// You can declare a class inside a method just fine
class $RandomName extends B<String> {
}
new $RandomName();
而且,至關重要的是extends B<String>,那是簽名的東西,并且可以用泛型讀取簽名。
這個原理被稱為超型別令牌。這意味著傳遞泛型,您必須使用這個new Foo<TheActualGenericsYouWantToPass>() {}以大括號結尾的構造,以確保創建一個新的本地匿名類,因為它帶有泛型型別。然后轉移您放入其中的確切內容,即如果您有:
public class Foo<T> {
public void example() {
new SuperTypeToken<T>() {};
}
}
您正在創建一個字面上只是T的,而不是 T 實際上是什么,換句話說,如果您這樣做:new Foo<String>.example(),該型別標記仍然是字面上T的 ,它不能用于派生String(再次,擦除,這實際上是不可能的,那資訊只是在運行時不存在,因此不可能匯出)。
您可以在網上搜索有關如何制作這些的教程,并且各種庫(例如 JSON 決議庫)具有 TypeToken(以及有關如何使用它們的檔案),這些都是此想法的實作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/506766.html
上一篇:無法分配給通用結構欄位
下一篇:在介面中使用泛型
