非法访问错误:访问受保护的方法

14

我有两个类。

A 有一个受保护的方法 m()aA 类的一个实例。

B 与类 A 在同一个包中。

我试图访问 a.m(),但是出现了 IllegalAccessError ...

问题出在哪里?


4
请提供一个简短而完整的程序来演示问题。这听起来非常奇怪。你有任何混淆等操作吗? - Jon Skeet
4个回答

23
编译器应该捕获这样的错误。由于您似乎在运行时得到了这个错误,因此可能发生了一些奇怪的事情。可能您已更改了源代码但没有完全重新编译。
另一个潜在但晦涩的问题是通过不同的类装入器加载类。即使包名称相同,从不同类装入器加载的类也会在不同的包中(就像由不同类装入器加载的名称相同的类将是不同的类一样)。

你可能需要重新启动你的应用程序。我在修改一个正在运行的应用程序时也遇到了同样的经历(即热代码替换中可能存在错误)。 - Maximilian Böhm

19
如果类A和类B由不同的类加载器加载,则可能会发生这种情况。此时,JVM认为这些类属于不同的“运行时包”。引用自JVM规范第5.3节:

在运行时,类或接口的确定不仅仅取决于其名称,还取决于一对:其完全限定名和定义该类的类加载器。每个这样的类或接口都属于单个运行时包。类或接口的运行时包是由该类或接口的包名称和定义该类或接口的类加载器确定的。

并且在第5.4.4节中提到:

如果以下任何条件成立,则字段或方法R对类或接口D可访问:

...

R既可以是受保护的,也可以是程序包私有的(即既不是公共的、受保护的,也不是私有的),并且是由与D相同的运行时包中的类声明的。


我怀疑这可能是导致我的问题的原因,但不确定第二个类加载器在堆栈中的哪个位置被引入或如何进行调试。但我会四处寻找... - Mark Bennett
在搜索另一个问题时,我找到了这个答案,其中我的类位于同名包中,但运行时包不同。这使得事情变得更加清晰!+1 - vergenzt

-1

它必须正常工作,看下面的例子就可以了:

package com.stackoverflow;

public class TEST
{
  static class A {
    protected void m()
    {
      System.out.println("hello from A.m()");
    }
  }

  static class B {

    public B()
    {
      a.m();
    }

    private A a = new A();
  }

  /**
   * @param args
   */
  public static void main(String[] args)
  {
    B b = new B();
  }
}

这段代码会输出以下信息: "hello from A.m()"

"protected修饰符指定该成员只能在其自己的包内访问(与包私有相同),并且可以被另一个包中其类的子类访问。"

请参见控制类成员的访问权限


2
"protected修饰符指定该成员只能在其自身的包内访问(与包私有性相同),并且可以被另一个包中其类的子类访问。" http://download.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html - Mike Tunnicliffe
或者将其保留为默认访问(即没有访问修饰符),以允许包访问。 - Scott
我修改了答案的内容,之前的内容有错误,对此很抱歉,感谢@fd;你确定你的B类确实和A类在同一个包中吗? - Gregory Pakosz
1
内容现在是正确的、有帮助的,但并没有直接回答问题(可能需要更多来自问题的信息)。 - Mike Tunnicliffe
它应该可以工作;如果不能,那是因为其他原因,比如类加载器问题或其他。 - Gregory Pakosz

-2

编译器应该能捕获到这种错误。如果你在运行时遇到了这个问题,说明出现了一些错误。很可能是你改变了完全重新编译的源代码。

它必须能正常工作。这里有一个运行的示例 -

**

  • 类A

**

package com.test;

public class A {

  protected void m(){
  System.out.println("Hi Stackoverflow");
 }

}

**

  • 类别 B

**

package com.test;

public class B{

public static void main(String[] args) {
  A a = new A();
  a.m();
 }

}

打印出期望的字符串

你好 Stackoverflow


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接