Java反射:从接口名调用方法
我有一个接口的名称,我想调用一个由其具体实现的类定义的方法。所以我借助Java反射 界面:Java反射:从接口名调用方法,java,class,reflection,methods,interface,Java,Class,Reflection,Methods,Interface,我有一个接口的名称,我想调用一个由其具体实现的类定义的方法。所以我借助Java反射 界面: package tsb.learning.reflection; public interface IAnyThing { void doSomething(); } 它是在类中实现的: package tsb.learning.reflection; public class AnyThing implements IAnyThing { public void doSomet
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();
}
}
异常是在控制台中循环打印,我需要停止程序
任何信息都会对我很有帮助
原因:java.lang.reflect.InvocationTargetException
这意味着您调用的方法引发了异常。您需要查看它后面出现的异常,并导致此异常。这与您如何调用该方法无关
我怀疑你有一个堆栈溢出错误
// 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);
}
}
顺便说一句,你可以写
Class interfaceClass = tsb.learning.reflection.IAnyThing.class;
ClassLoader classLoader = interfaceClass.getClassLoader();
Class<?>[] interfaces = new Class<?>[] { interfaceClass };
Class interfaceClass=tsb.learning.reflection.IAnyThing.Class;
ClassLoader ClassLoader=interfaceClass.getClassLoader();
类[]接口=新类[]{interfaceClass};
在AnyInvocationHandler
中,您可以将调用委托给任何东西的实例:
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);
}
}
IAnyThing
中唯一的方法是doSomething()
,因此我猜在调用处理程序中,您知道该方法是什么。把你的实现放在那里。此外,除了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....
}
}
谢谢所以方法AnyInvocationHandler#invoke
的实现是可以的吗?@TapasBose我重新编写的方式是可以的感谢您提供的代码片段正在运行。但是如果我不知道实现类,那么我怎么做呢?实际上,它是一个演示应用程序。在RealOne中,我不知道是哪个类实现了它。你不需要知道是什么实现了接口,但你必须有一个真实的实例。否则你不能期望它做任何事情。我已经更改了它,这样你就可以看到它如何调用接口的实现,而不需要知道它将是什么。谢谢,你的例子很有用,但它不是真实的情况。在实际情况中,我只有接口名,我是从RMI获得的,我需要调用该接口的一个方法。你是在告诉我你想要实现一个接口,而不知道它是什么,甚至没有一个具体的实现类?问问自己,如果从RMI收到java.util.Collection
,会发生什么。您是要模拟ArrayList
还是HashSet
或LinkedBlockingQueue
还是。。。。?现在有成千上万个这样的接口。
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....
}
}