Вопрос

I ran into the following problem.

I have two different packages in package a I would like to call the implemented method of an interface in a package b but the implementing class has package visibility.

So a simplifed code looks like this:

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");
        }
    }
}

and the Invoker:

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);
    }
}

When I start the program it prints out Called as expected and throws an Exception because the package visibility prohibits the calling of the discovered method.

So my question is any way to solve this problem? Am I missing something in Java documentation or this is simply not possible although simply calling an implemented method is possible without reflection.

Это было полезно?

Решение 2

I've found out. I need to call the getDeclaredMethod on the implemented interface, not on the class.

Example:

final Method method = B.class.getDeclaredMethod("method", EMPTY_CLASS_ARRAY);
method.invoke(b, EMPTY_OBJECT_ARRAY);

Другие советы

Since class has a package visibility its method's visibilty is in fact package level instead of public as you think. So, you have to call method.setAccessible(true) before method invocation:

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

See the documentation for setAccessible. SecurityPolicy may prevent you from making it accessible though.

But it is not clear that you need reflection at all. One of the benefits of polymorphism is that clients can call B.method() without having access to (or even worrying about) the concrete class that implements the interface.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top