samedi 18 mars 2017

getGenericSuperclass() in Java. How does it work?

Let's consider the following piece of code:

package index;

public class Main {
    public static void main(String[] args) {
        Inner inner = new Inner();
        Type t = inner.getClass().getGenericSuperclass();
        ParameterizedType p = (ParameterizedType) t;
        Type[] a = p.getActualTypeArguments();
        try {
            Custom c = (Custom) ((Class) a[0]).newInstance();
            c.f();
        } catch (Exception e){}
    }

    private static abstract class AbstractClass<T> {
        public abstract void doSth();
    }
    private static class Inner extends AbstractClass<Custom>{
        public void doSth() {
        }
    }
    private static class Custom{
        public Custom(){

        }
        public void f(){
            System.out.println("Custom");
        }
    }
}

And generated bytecode:

public class index/Main {

  static synthetic INNERCLASS index/Main$1 null null
  private static INNERCLASS index/Main$Custom index/Main Custom
  private static INNERCLASS index/Main$Inner index/Main Inner
  private static abstract INNERCLASS index/Main$AbstractClass index/Main AbstractClass

  public <init>()V
   L0
    LINENUMBER 6 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lindex/Main; L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  public static main([Ljava/lang/String;)V
    TRYCATCHBLOCK L0 L1 L2 java/lang/Exception
   L3
    LINENUMBER 8 L3
    NEW index/Main$Inner
    DUP
    ACONST_NULL
    INVOKESPECIAL index/Main$Inner.<init> (Lindex/Main$1;)V
    ASTORE 1
   L4
    LINENUMBER 9 L4
    ALOAD 1
    INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
    INVOKEVIRTUAL java/lang/Class.getGenericSuperclass ()Ljava/lang/reflect/Type;
    ASTORE 2
   L5
    LINENUMBER 10 L5
    ALOAD 2
    CHECKCAST java/lang/reflect/ParameterizedType
    ASTORE 3
   L6
    LINENUMBER 11 L6
    ALOAD 3
    INVOKEINTERFACE java/lang/reflect/ParameterizedType.getActualTypeArguments ()[Ljava/lang/reflect/Type;
    ASTORE 4
   L0
    LINENUMBER 13 L0
    ALOAD 4
    ICONST_0
    AALOAD
    CHECKCAST java/lang/Class
    INVOKEVIRTUAL java/lang/Class.newInstance ()Ljava/lang/Object;
    CHECKCAST index/Main$Custom
    ASTORE 5
   L7
    LINENUMBER 14 L7
    ALOAD 5
    INVOKEVIRTUAL index/Main$Custom.f ()V
   L1
    LINENUMBER 15 L1
    GOTO L8
   L2
    ASTORE 5
   L8
    LINENUMBER 25 L8
    RETURN
   L9
    LOCALVARIABLE c Lindex/Main$Custom; L7 L1 5
    LOCALVARIABLE args [Ljava/lang/String; L3 L9 0
    LOCALVARIABLE inner Lindex/Main$Inner; L4 L9 1
    LOCALVARIABLE t Ljava/lang/reflect/Type; L5 L9 2
    LOCALVARIABLE p Ljava/lang/reflect/ParameterizedType; L6 L9 3
    LOCALVARIABLE a [Ljava/lang/reflect/Type; L0 L9 4
    MAXSTACK = 3
    MAXLOCALS = 6
}

  1. It works and I cannot understand how does it works. It shows that it is possible to get information about superclasses parameters. I don't know how it is possible to get a such information because I looked at bytecode and there is no such information:

  2. Is it ok to do it?





Aucun commentaire:

Enregistrer un commentaire