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

我有一个接口的名称,我想调用一个由其具体实现的类定义的方法。所以我借助Java反射

界面:

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....
    }

}