【问题标题】:Inconsistent behaviour with Java reflection 'invoke' methodJava 反射“调用”方法的行为不一致
【发布时间】:2019-09-24 14:39:31
【问题描述】:

请查看这些示例类。

A.java:

// A is not public
class A
{
    public static void foo()
    {

    }
}

B.java:

package p;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class B
{
    public void invoke() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException
    {
        Class clazz = Class.forName("A");
        Method method = clazz.getDeclaredMethod("foo", new Class[0]);
        method.invoke(null, new Object[0]);
    }
}

C.java:

import java.lang.reflect.InvocationTargetException;

public class C extends p.B
{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException
    {
        C c = new C();
        c.invoke();
    }

//  @Override
//  public void invoke() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException
//  {
//      Class clazz = Class.forName("A");
//      Method method = clazz.getDeclaredMethod("foo", new Class[0]);
//      method.invoke(null, new Object[0]);
//  }
}

C 中 main 中的“调用”方法失败:

IllegalAccessException:类 p.B 不能使用修饰符“public static”访问 A 类的成员

如果 C 中的 'invoke' 方法与 p.B. 中的覆盖方法完全相同。但是,如果未注释,则不会抛出异常。

为什么不一样?

【问题讨论】:

  • A 类在什么包中? C类在什么包里?

标签: java reflection


【解决方案1】:

A 类是包私有的。因为AC 在同一个(默认)包中,所以从类C 中的任何代码调用A.foo() 是合法的访问,但不能在类B 中调用,因为它在不同的包中。

如果您覆盖该方法,则会从同一包中调用A.foo()。如果不覆盖该方法,则从不同包中的代码调用A.foo(),这是非法访问。

您可以通过在各自的invoke() 方法中添加语句A.foo() 来复制类似的行为。但是,在这种情况下,您将收到编译错误而不是运行时错误。

【讨论】:

  • 感谢您的回复。您通过调用 A.foo() 来复制它是正确的,因此这种行为是一致的。我不喜欢的是,invoke() 是在 C 类的对象上调用的,而不是 B 类的对象,它只继承 B 类。所以它应该表现得像一个,允许调用封装私有 A。其他意见?
  • 这就是多态性的工作原理,方法在 B 类中,所以它到底是什么类型的对象并不重要。如果只是扩展某个类就可以访问其包中的所有内容......那么整个可见性就有点没用了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-21
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
相关资源
最近更新 更多