Ich untersuche, wie Bibliotheken, die Proxy-Objekte erstellen, insbesondere ich möchte verstehen, wie sie Typen von deklarierten Methoden abrufen. Zum Beispiel beliebte Bibliothek für Android - Retrofit:Wie Typ Löschen funktioniert
interface MyService {
@GET("path")
Call<MyData> getData();
}
Ich war verwirrt - wie es möglich ist, von dieser Schnittstelle genau MyData Klasse nicht roh Objekt zu bekommen? Aufgrund meines Verständnisses löscht Type Erase alle Informationen, die in generische Klammern gesetzt wurden.
Ich schrieb einigen Test-Code und überraschend für mich ist es einfach Art von solchen Code zu erhalten:
@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();
}
Es sieht ein bisschen schmutzig, aber es funktioniert und Druck Integer
. Das bedeutet, dass wir Typen in Runtime haben. Auch ich habe über einen anderen schmutzigen Trick mit anonymen Klassen lesen:
System.out.println(new ArrayList<Integer>().getClass().getGenericSuperclass());
druckt roh AbstractList<E>
während dieser Code
System.out.println(new ArrayList<Integer>() { }.getClass().getGenericSuperclass());
druckt ArrayList<Integer>
.
Und es ist nicht das letzte, was mich verwirrt. In Kotlin sind dort verdinglichten Generika, aus denen wie ein Hack in der Kompilierung aussieht, aber wir können einfach Klasse von Generika erhalten:
inline fun <reified T> test() {
print(T::class)
}
Und jetzt bin ich völlig mit Typ-Löschmechanismus verwirrt.
- Kann jemand erklären, warum manchmal Informationen hält und manchmal nicht?
- Warum Generika in Java nicht normal implementiert ist? Ja, ich habe gelesen, dass es die Kompatibilität mit früheren Versionen brechen könnte, aber ich möchte verstehen, wie. Warum bricht generischer Rückgabetyp nichts außer
new ArrayList<Integer>
? - Warum haben anonyme Klassen einen generischen Typ und werden nicht vom Typ gelöscht?
Aktualisiert: 4. Wie Generika in Kotlin arbeitet sie verdinglicht und warum so coole Sache nicht in Java implementiert werden können?
Here erklärt ziemlich klar darüber, wie vergiftete Generika arbeiten. @Mibac
Sie können nur in Kombination mit einer Inline-Funktion verdinglichten verwenden. Solch eine eine Funktion macht den Compiler den Bytecode der Funktion zu jedem Ort kopieren, wo die Funktion verwendet wird (die Funktion ist "inline"). Wenn Sie eine Inline-Funktion mit verdichtetem Typ aufrufen, kennt der Compiler den tatsächlichen Typ, der als Typargument verwendet wird, und ändert den generierten Bytecode, um die entsprechende Klasse direkt zu verwenden. Deshalb Aufrufe wie myVar ist T myVar ist String, wenn der Typ Argument String, im Bytecode und zur Laufzeit waren.
[Wie 'vereidigt' funktioniert] (https://Stackoverflow.com/a/45952201/3533380) – Mibac