如何通过 获取所有声明的方法MethodHandles.lookup()
?如何获取所有声明的字段?
和MethodHandle.invoke()
之间有什么区别MethodHandle.invokeExact()
MethodHandle.invokeWithArguments()
此外,我将不胜感激有关使用 MethodHandle API for Java devloper的教程。我强调,我是在静态类型语言纯旧 Java 上编程,我不是 JVM 开发人员,特别是我对整个字节码废话(invokedynamic)不感兴趣。我想弄清楚如何使用这个新 API 而不是 Java Core API。
编辑-2:
@Glen Best 下面提供了一些参考我只想提供一个http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&search_term=methodhandle&doc_id=-1#pg50这正是我想要的。我发现实际上有一些新词汇。例如,目标实际上是指 MethodHandle(而不是要进行调度的对象),而调用站点实际上是“调用”“函数指针”又名 MethodHandle 的代码。此外,必须了解 MethodHandle API不是核心反射 API的替代品,而不是补充它。例如,您无法使用 MethodHandle “发现”所有方法,而您需要 Core Reflection API。但是当你“找到”你想要的方法时,你可以切换到 MethodHandle,例如,绑定它的一些参数或“改变”(适应)它的签名,例如可变参数。
编辑:
我仍在试图找出答案。我写了一些测试,想和大家分享。
package alexander.berkovich;
import static org.junit.Assert.assertSame;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.BeforeClass;
import org.junit.Test;
public class MethodHandlerCleanTest {
public static MethodHandles.Lookup lookup;
@BeforeClass
public static void asetUp(){
lookup = MethodHandles.lookup();
}
public static class Check {
public void primitive(final int i){
}
public void wrapper(final Integer i){
}
}
@Test
public void testPrimitive() throws Throwable {
Check check = new Check();
MethodType type = MethodType.methodType(void.class, int.class);
MethodHandle mh = lookup.findVirtual(Check.class, "primitive", type);
mh.invokeWithArguments(check, 1);
mh.invoke(check, (short)2);
mh.invoke(check, Integer.valueOf(3));
Method method = Check.class.getMethod("primitive", int.class);
method.invoke(check, (short)20);
method.invoke(check, Integer.valueOf(21));
}
@Test
public void testWrapper() throws Throwable {
Check check = new Check();
MethodType type = MethodType.methodType(void.class, Integer.class);
MethodHandle mh = lookup.findVirtual(Check.class, "wrapper", type);
mh.invoke(check, 2);
Method method = Check.class.getMethod("wrapper", Integer.class);
method.invoke(check, 20);
}
@SuppressWarnings("unused")
public static class StaticInnerClass {
public static String staticName;
public String name;
public void foo(){}
public static void staticFoo(){}
}
@Test
public void testStaticInnerClassStaticField() throws Throwable {
MethodHandle mhSet = lookup.findStaticSetter(StaticInnerClass.class, "staticName", String.class);
String expected = "mama";
mhSet.invoke(expected);
MethodHandle mhGet = lookup.findStaticGetter(StaticInnerClass.class, "staticName", String.class);
Object obj = mhGet.invoke();
String value = (String)obj;
assertSame(expected, value);
}
@Test
public void testStaticInnerClassField() throws Throwable {
StaticInnerClass sut = new StaticInnerClass();
Field f = StaticInnerClass.class.getDeclaredField("name");
MethodHandle mhSetUnreflect = lookup.unreflectSetter(f);
String expectedUnreflect = "unreflect";
mhSetUnreflect.invoke(sut, expectedUnreflect);
MethodHandle mhSet = lookup.findSetter(StaticInnerClass.class, "name", String.class);
String expected = "mama";
mhSet.invoke(sut, expected);
MethodHandle mhGet = lookup.findGetter(StaticInnerClass.class, "name", String.class);
Object obj = mhGet.invoke(sut);
String value = (String)obj;
assertSame(expected, value);
}
@Test
public void testStaticInnerClassConstructor() throws Throwable {
StaticInnerClass sut = new StaticInnerClass();
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findConstructor(StaticInnerClass.class, type);
mh.invoke();
}
@Test
public void testStaticInnerClassMethod() throws Throwable {
StaticInnerClass sut = new StaticInnerClass();
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findVirtual(StaticInnerClass.class, "foo", type);
mh.invoke(sut);
}
@Test
public void testStaticInnerClassStaticMethod() throws Throwable {
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findStatic(StaticInnerClass.class, "staticFoo", type);
mh.invoke();
}
@SuppressWarnings("unused")
private class InnerClass {
public String name;
public void foo(){}
}
@Test
public void testInnerClassField() throws Throwable {
InnerClass sut = new InnerClass();
MethodHandle mhSet = lookup.findSetter(InnerClass.class, "name", String.class);
String expected = "mama";
mhSet.invoke(sut, expected);
MethodHandle mhGet = lookup.findGetter(InnerClass.class, "name", String.class);
Object obj = mhGet.invoke(sut);
String value = (String)obj;
assertSame(expected, value);
}
@Test
public void testInnerClassConstructor() throws Throwable {
MethodType type = MethodType.methodType(void.class, MethodHandlerCleanTest.class);
//default constructor is private
Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
MethodHandles.Lookup trustedLookup = (MethodHandles.Lookup)
field
.get(null);
MethodHandle mh = trustedLookup.findConstructor(InnerClass.class, type);
mh.invoke(this);
}
@Test
public void testInnerClassMethod() throws Throwable {
InnerClass sut = new InnerClass();
MethodType type = MethodType.methodType(void.class);
MethodHandle mh = lookup.findVirtual(InnerClass.class, "foo", type);
mh.invoke(sut);
}
}