我有一个接口的名称,我想调用由其具体实现的类定义的方法。所以我接受了Java Reflection的帮助。
界面:
package tsb.learning.reflection;
public interface IAnyThing {
void doSomething();
}
它实现了类:
package tsb.learning.reflection;
public class AnyThing implements IAnyThing {
public void doSomething() {
System.out.println("JYM");
}
}
InvocationHandler
的实施:
package tsb.learning.reflection;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class AnyInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(proxy, args);
}
}
和控制器:
package tsb.learning.reflection;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Controller {
/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
String interfaceName = "tsb.learning.reflection.IAnyThing";
ClassLoader classLoader = Class.forName(interfaceName).getClassLoader();
Class<?>[] interfaces = new Class<?>[] { Class.forName(interfaceName) };
InvocationHandler handler = new AnyInvocationHandler();
IAnyThing anyThing = (IAnyThing) Proxy.newProxyInstance(classLoader, interfaces, handler);
anyThing.doSomething();
}
}
但它没有用,我得到以下例外:
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at tsb.learning.reflection.AnyInvocationHandler.invoke(AnyInvocationHandler.java:10)
at $Proxy0.doSomething(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at tsb.learning.reflection.AnyInvocationHandler.invoke(AnyInvocationHandler.java:10)
at $Proxy0.doSomething(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at tsb.learning.reflection.AnyInvocationHandler.invoke(AnyInvocationHandler.java:10)
at $Proxy0.doSomething(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at tsb.learning.reflection.AnyInvocationHandler.invoke(AnyInvocationHandler.java:10)
例外是在循环控制台中打印,我需要停止程序。
任何信息都对我很有帮助。
答案 0 :(得分:3)
引起:java.lang.reflect.InvocationTargetException
这意味着您调用的方法引发了异常。你需要查看它后面出现的异常并导致这个异常。它与您调用方法的方式无关。
我怀疑你得到了StackOverflowError
// calls the same method on the same proxy which will recurse until you get an error.
return method.invoke(proxy, args);
而是尝试在真实对象上调用方法来做某事。
public class AnyInvocationHandler implements InvocationHandler {
final IAnyThing iat;
public AnyInvocationHandler(IAnyThing iat) {
this.iat = iat;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// call the same method on a real object.
return method.invoke(iat, args);
}
}
BTW你可以写
Class interfaceClass = tsb.learning.reflection.IAnyThing.class;
ClassLoader classLoader = interfaceClass.getClassLoader();
Class<?>[] interfaces = new Class<?>[] { interfaceClass };
答案 1 :(得分:1)
在AnyInvocationHandler
内,您可以将来电委托给AnyThing
的实例:
public class AnyInvocationHandler implements InvocationHandler {
private AnyThing delegate = new AnyThing();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// to something useful here
[...]
// finally, invoke the method on implementation class.
return method.invoke(delegate, args);
}
}
答案 2 :(得分:1)
IAnyThing
中唯一的方法是doSomething()
,所以我想在InvocationHandler
你知道方法是什么。把你的实现放在那里。另外,在doSomething()
旁边,您还应该处理从java.lang.Object
继承的三种方法:
public static class AnyInvocationHandler implements InvocationHandler {
private static final Method doSomething;
static {
try {
doSomething = IAnyThing.class.getMethod("doSomething");
} catch (NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class)
return handleObjectMethod(proxy, method, args);
if (doSomething.equals(method)) {
doSomethingImpl();
return null;
}
throw new AbstractMethodError(method.toString());
}
private Object handleObjectMethod(Object proxy, Method method, Object[] args) {
switch (method.getName()) {
case "equals":
return proxy == args[0];
case "hashCode":
return System.identityHashCode(proxy);
case "toString":
return proxy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(proxy));
default:
throw new AssertionError();
}
}
private void doSomethingImpl() {
// implement....
}
}