2016-04-20 9 views
1

J'ai créé 2 classes simples pour essayer Java MethodHandle -API:Pourquoi checkcast-instruction est absent pour (int) MethodHandle.invokeExact?

public class Foo { 
    private static int staticField; 

    public static Object getStaticField() { 
     return staticField; 
    } 
} 

une autre classe pour Invoke méthode Foo.getStaticField() de deux façons - directs et en utilisant MethodHandle -API:

.... 
public static void methodHandleGetStaticField() throws Throwable { 
    MethodHandle methodHandle = lookup.findStatic(Foo.class, "getStaticField", MethodType.methodType(int.class)); 
    int i = (int)methodHandle.invokeExact(); 
} 

public static void directGetStaticField() { 
    int i = (int)Foo.getStaticField(); 
} 
.... 

Je classe décompilé et vu que la méthode directGetStaticField contient cast instructiona, mais la méthode methodHandleGetStaticField ne fonctionne pas, bien que java.lang.invoke.MethodHandle.invokeExact() renvoie java.lang.Object.

public static void directGetStaticField(); 
descriptor:()V 
Code: 
    0: invokestatic #70 // Method ru/fj/methodhandle/Foo.getStaticField:()Ljava/lang/Object; 
    3: checkcast  #33 // class java/lang/Integer 
    6: invokevirtual #74 // Method java/lang/Integer.intValue:()I 
    9: istore_0 
    10: return 

public static void methodHandleGetStaticField() throws java.lang.Throwable; 
descriptor:()V 
Code: 
    0: getstatic  #15 // Field lookup:Ljava/lang/invoke/MethodHandles$Lookup; 
    3: ldc   #29 // class ru/fj/methodhandle/Foo 
    5: ldc   #90 // String getStaticField 
    7: getstatic  #32 // Field java/lang/Integer.TYPE:Ljava/lang/Class; 
    10: invokestatic #38 // Method java/lang/invoke/MethodType.methodType:(Ljava/lang/Class;)Ljava/lang/invoke/MethodType; 
    13: invokevirtual #46 // Method java/lang/invoke/MethodHandles$Lookup.findStatic:(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/MethodHandle; 
    16: astore_0 
    17: aload_0 
    18: invokevirtual #52 // Method java/lang/invoke/MethodHandle.invokeExact:()I 
    21: istore_1 
    22: return 

Quelqu'un peut-il m'expliquer pour moi?

Répondre

3

Vous pouvez remarquer que invokeExact retourne en effet un int de son descripteur ()I:

18: invokevirtual #52 // Method java/lang/invoke/MethodHandle.invokeExact:()I 

En conséquence, aucune coulée est nécessaire.

La raison pour laquelle elle renvoie une int, pas un Object, est cette méthode invokeExact (ainsi que invoke) dans MethodHandle sont traités spécialement, voir les invokeExact API

Retours:

la résultat polymorphique de la signature, représenté statiquement à l'aide de l'objet

et du signature polymorphism:

... La partie inhabituelle est que le descripteur de type symbolique est dérivé de l'argument réel et les types de retour, pas de la déclaration de méthode.