2016-04-20 7 views
1

Я создал 2 простых классов для Java попробовать MethodHandle -API:Почему checkcast-инструкция отсутствует для (int) MethodHandle.invokeExact?

public class Foo { 
    private static int staticField; 

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

другой класс для метода Invoke Foo.getStaticField() двумя способами - прямым и использованием 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(); 
} 
.... 

Я декомпилированный класс и видел, что directGetStaticField способ содержит литье инструкцияa, но способ methodHandleGetStaticField не, хотя java.lang.invoke.MethodHandle.invokeExact() возвращение 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 

Может ли кто-нибудь объяснить это мне?

ответ

3

Вы можете заметить, что invokeExact действительно возвращает int из дескриптора ()I:

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

В результате, не требуется отливка.

Причина, почему она возвращает int, не Object, является то, что метод invokeExact (а также invoke) в MethodHandle рассматриваются специально, см invokeExact API

Возвращает:

в подпись-полиморфный результат, статически представленный с использованием объекта

и от signature polymorphism:

... Необычная частью является то, что символический дескриптор типа является производной от фактического аргумента и возвращают типы, а не из декларации методы.