我正在研究創建代理對象的庫如何工作,特別是我想了解它們如何從聲明的方法中獲取類型。例如流行的Android庫 - 改造:類型擦除如何工作
interface MyService {
@GET("path")
Call<MyData> getData();
}
我被搞糊塗了 - 它是如何可能從這個接口正是MyData的類不生對象得到什麼?從我的理解類型刪除的原因將刪除放置在通用括號內的任何信息。
我寫了一些測試代碼和令人驚訝的對我來說是很容易從這樣的代碼獲取類型:
@org.junit.Test
public void run() {
Method[] methods = Test.class.getDeclaredMethods();
Method testMethod = methods[0];
System.out.println(testMethod.getReturnType());
ParameterizedType genericType = ((ParameterizedType) testMethod.getGenericReturnType());
Class<Integer> clazz = (Class<Integer>) genericType.getActualTypeArguments()[0];
System.out.println(clazz);
}
interface Test {
List<Integer> test();
}
它看起來有點髒,但它的工作原理,並打印Integer
。這意味着我們在運行時有類型。此外,我讀過有關另一使壞無名類:
System.out.println(new ArrayList<Integer>().getClass().getGenericSuperclass());
打印原料AbstractList<E>
而這段代碼
System.out.println(new ArrayList<Integer>() { }.getClass().getGenericSuperclass());
打印ArrayList<Integer>
。
這並不是最後一件讓我困惑的事情。在科特林有物化仿製藥從它看起來像在編譯時的一些技巧,但我們可以很容易地從通用獲取類:
inline fun <reified T> test() {
print(T::class)
}
而且現在我有類型擦除機制完全糊塗了。
- 有人可以解釋一下,爲什麼有時候它持有信息,有時不會?
- 爲什麼泛型沒有在Java中以正常的方式實現?是的,我讀過它可能會破壞以前的版本compabillity,但我想了解如何。爲什麼泛型返回類型不會破壞任何東西,但
new ArrayList<Integer>
呢? - 爲什麼匿名類持有泛型類型,而不是類型擦除?
更新時間: 4.如何具體化的泛型工作在科特林以及爲什麼這樣酷的事情不能用Java實現?
Here解釋了物化泛化的工作原理。 @Mibac
您只能使用reified與內聯函數的組合。這樣的函數使得編譯器將函數的字節碼複製到每個使用該函數的地方(該函數正在被 「內聯」)的每個 位置。當您使用具體化類型調用內聯函數時, 編譯器知道用作類型參數的實際類型,並將生成的字節碼修改爲直接使用相應的類。 因此,像myVar這樣的調用是T成爲myVar是字符串,如果類型 參數是字符串,在字節碼和運行時。
[工作原理](https://stackoverflow.com/a/45952201/3533380) – Mibac