Witam, jak zobaczyć zdekompilowany kod w IntelliJ? Mam jakąś klasę generyczną, jak wchodzę do katalogu target
i patrzę na zdekompilowany plik .class, to widzę dokładnie ten sam kod, jakby type erasure w ogóle nie zachodziło.
1
1
Fernflower jest sprytny i odzyskuje sygnatury także dla generyków.
1
@nobody01: jeśli nie wierzysz ze erasure is real to patrz:
import java.util.ArrayList;
import java.util.List;
public class Erasure {
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("test");
List whatever = strings;
List<Integer> ints = whatever;
ints.add(1);
for (Object x : whatever) {
System.out.println(x);
}
}
}
;)
1
Przecież w bajtkodzie są obecne generyki wpisane wprost w kodzie (czyli statycznie zdefiniowane konkretne typy np String, ale nie T). Możesz się do nich dobrać metodami typu:
- Class.getGenericInterfaces
- Class.getGenericSuperclass
- ParametrizedType.getActualTypeArguments
- itd
Innymi słowy dla np List<String>
typ generyczny zostanie zapisany w bajtkodzie, ale dla List<T>
już nie bo na etapie kompilacji nie wiadomo co T oznacza (a może oznaczać przecież wiele rzeczy jednocześnie, jak np T w Arrays.asList, gdzie możemy sobie podstawiać różne T dla różnych wywołań).
1
Wygląda na to, że się wszystko zamienia w Object
. Tak jak się pisało drzewiej, w erze przedgenerycznej.
import java.util.*;
public class TypeErasure
{
public static class A<T> {
public A(T x) {
for(int i = 0; i < 2; i++)
System.out.println("new " + x);
}
}
public static void main(String args[])
{
new A("napis");
new A(3);
}
}
javap -p -c TypeErasure$A.class
Compiled from "TypeErasure.java"
public class TypeErasure$A<T> {
public TypeErasure$A(T);
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: iconst_0
5: istore_2
6: iload_2
7: iconst_2
8: if_icmpge 42
11: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
14: new #3 // class java/lang/StringBuilder
17: dup
18: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
21: ldc #5 // String new
23: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: aload_1
27: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
30: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
33: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
36: iinc 2, 1
39: goto 6
42: return
}