Jak zobaczyć zdekompilowany kod w IntelliJ?

1

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

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
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1