反思性地创建一个匿名类

时间:2018-12-12 15:14:43

标签: java reflection

我打算使用自定义的ClassLoader导入库(jar),事实证明要求在其中一个类上设置侦听器,例如

Class<?> clazz = getInitializerClass();
Object initializer = clazz.newInstance();

// I would like the below listener to be set on this initializer reflectively
// setOnInitListener() is mathod to be called on initializer
setOnInitListener(new OnInitCompleteListener(){
    @Override
    public void onInit(){
    }
}

问题是我没有将侦听器用作导入文件,而我只能通过动态加载类来动态获取OnInitCompleteListener.class

如何实现以上目标?

注意:我愿意为达到相同的目标而竭尽全力,但简单的方法将不胜感激。

2 个答案:

答案 0 :(得分:2)

匿名类是编译时工件。它们甚至具有Java编译器可以识别它们的名称,尽管程序员无法访问。

但是,有一种解决方法:由于OnInitCompleteListener是一个接口,因此您可以生成一个动态代理来实现您的接口:

InvocationHandler handler = new InvocationHandler() {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("onInit")) {
            ... // Listener's code goes here
        }
    }
};
Class<T> onInitCompleteListenerClass = ... // You get this one dynamically
Object listener = Proxy.newProxyInstance(
    classLoader,
    new Class[] { onInitCompleteListenerClass },
    handler);
// Use listener in the reflective call to a method taking OnInitCompleteListener

MyInvocationHandler实现InvocationHandler接口。其invoke方法可以检测到它是在onInit位置被调用的,并根据需要执行工作。

答案 1 :(得分:0)

假设您的OnInitCompleteListener类在同一类加载器中可用,而您在...中运行此代码的其余部分...

您可以对类实例进行反思来了解setOnInitListener方法:

Method setter = clazz.getDeclaredMethod("setOnInitListener", OnInitCompleteListener.class);
setter.invoke(initializer, new OnInitCompleteListener() {
    @Override
    public void onInit()  {
        // implementation
    }
});