在使用entityClass.newInstance()创建的实例上调用Exact是否会导致java.lang.invoke.ErrorMethodTypeException?
我在向invokeExact方法传递使用newInstance方法创建的实例时遇到问题 我的方法是这样的在使用entityClass.newInstance()创建的实例上调用Exact是否会导致java.lang.invoke.ErrorMethodTypeException?,java,reflection,Java,Reflection,我在向invokeExact方法传递使用newInstance方法创建的实例时遇到问题 我的方法是这样的 public <T extends BaseEntity> T getEntity(Class<T> entityClass) { T entity; try { entity = entityClass.newInstance(); } catch (InstantiationException | IllegalAcce
public <T extends BaseEntity> T getEntity(Class<T> entityClass) {
T entity;
try {
entity = entityClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
for (Field field : map.get(entityClass).keySet()) {
if (get(field.getName()) != null) {
try {
MethodHandle methodHandle = map.get(entityClass).get(field);
methodHandle.invokeExact(entity, (String) get(field.getName()));
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
return entity;
}
resource.getEntity(DemoEntity.class);
结果是
Caused by: java.lang.invoke.WrongMethodTypeException: **expected (DemoEntity,String)void but found (BaseEntity,String)void**
at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:349) ~[na:1.7.0_45]
at java.lang.invoke.Invokers.checkExactType(Invokers.java:360) ~[na:1.7.0_45]
at com.me.api.entity.request.DemoEntityRequest.getEntity(DemoEntityRequest.java:49) ~[classes/:na]
... 27 common frames omitted
如果我使用invoke而不是invokeExact,代码可以正常工作,但我很想知道是什么导致了这个问题,即为什么invokeExact方法将T实体视为其超类类型而不是DemoEntity
编辑:
下面是一个完整的工作示例
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
public class InvokeExactTest {
public static void main(String[] args) {
new InvokeExactTest().test(Demo.class);
}
public <T extends Base> void test(Class<T> clazz) {
Field field = clazz.getDeclaredFields()[0];
field.setAccessible(true);
MethodHandle setter = null;
try {
setter = MethodHandles.lookup().unreflectSetter(field);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
Demo demo1 = new Demo();
setter.invokeExact(demo1, "Demo 1");
} catch (Throwable e) {
e.printStackTrace();
}
try {
T demo2 = clazz.newInstance();
setter.invokeExact(demo2, "Demo 2");
} catch (Throwable e) {
e.printStackTrace();
}
}
public static class Base {
}
public static class Demo extends Base {
private String name;
}
}
为了回答我的问题,invokeExact要求在编译时知道类型,没有办法绕过它。您可以添加一个完整的(但最小的)示例来重现这个问题吗?大概
MethodHandle
是通过引用类BaseEntity
获得的。这会将其方法类型设置为类似于(BaseEntity,String)void
。使用DemoEntity
@SotiriosDelimanolis,您将无法invokeExact
。我已经添加了一个完整的工作示例来演示我的问题。如果我将demo2更改为demo2=(demo)clazz.newInstance(),代码将工作,那么invokeExact似乎需要确切的类型,但需要编译时间?
java.lang.invoke.WrongMethodTypeException: expected (Demo,String)void but found (Base,String)void
at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:294)
at java.lang.invoke.Invokers.checkExactType(Invokers.java:305)
at InvokeExactTest.test(InvokeExactTest.java:30)
at InvokeExactTest.main(InvokeExactTest.java:8)