我有两节课。
班级A
有受保护的方法m()
,a
是A
的一个实例。
类B
与类A
位于同一个包中。
我正在尝试访问a.m()
,但我收到IllegalAccessError
...
怎么了?
答案 0 :(得分:19)
编译器应该捕获这样的错误。正如你在运行时显然得到的那样,发生了一些奇怪的事情。您可能已更改源代码但已完全重新编译。
另一个潜在但又模糊的问题是通过不同的类加载器加载类。从不同的类加载器加载的类将在不同的包中,即使包名相同(与不同类加载器加载的具有相同名称的类的方式相同)。
答案 1 :(得分:17)
如果类A和B由不同的类加载器加载,则会发生这种情况。然后,jvm将这些类视为不同的“运行时包”。引自the jvm specification,第5.3节:
在运行时,类或接口不仅由其名称决定,而是由一对确定:它的完全限定名称及其定义的类加载器。每个这样的类或接口都属于单个运行时包。类或接口的运行时包由包名称和类或接口的类加载器确定。
在第5.4.4节中:
当且仅当满足以下任一条件时,才能访问类或接口D的字段或方法R:
...
R是受保护的或包私有的(即既不公开也不受保护也不是私有),并且由与D相同的运行时包中的类声明。
答案 2 :(得分:-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 modifier指定了 会员只能在其中访问 它自己的包(如同 包 - 私人),另外,由 另一个类的子类 包“。
答案 3 :(得分:-2)
编译器应该捕获这样的错误。当你在运行时得到它时,发生了一些错误。很可能你已经改变了完全重新编译的源代码。
必须有效。这是一个运行的例子 -
**
**
package com.test;
public class A {
protected void m(){
System.out.println("Hi Stackoverflow");
}
}
**
**
package com.test;
public class B{
public static void main(String[] args) {
A a = new A();
a.m();
}
}
打印预期的字符串
您好Stackoverflow