为什么 (int)MethodHandle.invokeExact 缺少 checkcast-instruction?
Why checkcast-instruction is absent for (int)MethodHandle.invokeExact?
我已经为 try Java 创建了 2 个简单的 classes MethodHandle
-API:
public class Foo {
private static int staticField;
public static Object getStaticField() {
return staticField;
}
}
另一个 class 以两种方式调用方法 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();
}
....
我已经反编译了 class 并看到 directGetStaticField
方法包含转换指令 a,但是方法 methodHandleGetStaticField
没有,尽管 java.lang.invoke.MethodHandle.invokeExact()
returns 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
谁能帮我解释一下?
您可以从其描述符 ()I
:
中注意到 invokeExact
确实是 returns 一个 int
18: invokevirtual #52 // Method java/lang/invoke/MethodHandle.invokeExact:()I
因此,不需要转换。
之所以 returns 是 int
,而不是 Object
,是因为 invokeExact
(以及 invoke
)在 MethodHandle
被特殊对待,见invokeExact API
Returns:
the signature-polymorphic result, statically represented using Object
并且来自 signature polymorphism:
... The unusual part is that the symbolic type descriptor is derived from the actual argument and return types, not from the method declaration.
我已经为 try Java 创建了 2 个简单的 classes MethodHandle
-API:
public class Foo {
private static int staticField;
public static Object getStaticField() {
return staticField;
}
}
另一个 class 以两种方式调用方法 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();
}
....
我已经反编译了 class 并看到 directGetStaticField
方法包含转换指令 a,但是方法 methodHandleGetStaticField
没有,尽管 java.lang.invoke.MethodHandle.invokeExact()
returns 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
谁能帮我解释一下?
您可以从其描述符 ()I
:
invokeExact
确实是 returns 一个 int
18: invokevirtual #52 // Method java/lang/invoke/MethodHandle.invokeExact:()I
因此,不需要转换。
之所以 returns 是 int
,而不是 Object
,是因为 invokeExact
(以及 invoke
)在 MethodHandle
被特殊对待,见invokeExact API
Returns:
the signature-polymorphic result, statically represented using Object
并且来自 signature polymorphism:
... The unusual part is that the symbolic type descriptor is derived from the actual argument and return types, not from the method declaration.