0

我遇到了以下问题。

我在包中有两个不同的包a我想在包中调用接口的实现方法,b但实现类具有包可见性。

所以一个简化的代码如下所示:

package b;

public final class Factory {
    public static B createB() {
        return new ImplB();
    }

    public interface B {
        void method();
    }

    static class ImplB implements B {
        public void method() {
            System.out.println("Called");
        }
    }
}

和调用者:

package a;

import java.lang.reflect.Method;
import b.Factory;
import b.Factory.B;

public final class Invoker {
    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[] {};
    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[] {};

    public static void main(String... args) throws Exception {
        final B b = Factory.createB();
        b.method();

        final Method method = b.getClass().getDeclaredMethod("method", EMPTY_CLASS_ARRAY);
        method.invoke(b, EMPTY_OBJECT_ARRAY);
    }
}

当我启动程序时,它按预期打印Called并抛出异常,因为包可见性禁止调用发现的方法。

所以我的问题是有什么办法可以解决这个问题?我是否遗漏了 Java 文档中的某些内容,或者这根本不可能,尽管无需反射就可以简单地调用已实现的方法。

4

3 回答 3

3

由于类具有包可见性,因此其方法的可见性实际上是包级别,而不是您想象的公共。因此,您必须method.setAccessible(true)在方法调用之前调用:

 final Method method = b.getClass().getDeclaredMethod("method", EMPTY_CLASS_ARRAY);
 method.setAccessible(true);
 method.invoke(b, EMPTY_OBJECT_ARRAY);
于 2012-10-04T15:36:22.607 回答
1

我发现了。我需要getDeclaredMethod在实现的接口上调用,而不是在类上。

例子:

final Method method = B.class.getDeclaredMethod("method", EMPTY_CLASS_ARRAY);
method.invoke(b, EMPTY_OBJECT_ARRAY);
于 2012-10-04T15:35:22.347 回答
0

请参阅setAccessible的文档。不过,SecurityPolicy 可能会阻止您访问它。

但不清楚你是否需要反思。多态性的好处之一是客户端可以调用B.method()而无需访问(甚至担心)实现接口的具体类。

于 2012-10-04T15:40:24.463 回答