【发布时间】:2010-08-02 09:56:53
【问题描述】:
我有两节课。
类A 具有受保护的方法m(),a 是A 的一个实例。
B 类与A 类在同一个包中。
我正在尝试访问a.m(),但我收到了IllegalAccessError...
怎么了?
【问题讨论】:
-
请制作一个简短但完整的程序来演示该问题。这听起来很奇怪。您是否涉及任何混淆等?
标签: java
我有两节课。
类A 具有受保护的方法m(),a 是A 的一个实例。
B 类与A 类在同一个包中。
我正在尝试访问a.m(),但我收到了IllegalAccessError...
怎么了?
【问题讨论】:
标签: java
编译器应该捕获这样的错误。当您显然在运行时得到这个时,发生了一些奇怪的事情。可能您已经更改了源代码但完全重新编译。
另一个潜在但模糊的问题是通过不同的类加载器加载类。即使包名相同,从不同类加载器加载的类也会在不同的包中(就像不同类加载器加载的同名类会是不同的类一样)。
【讨论】:
如果类 A 和 B 由不同的类加载器加载,就会发生这种情况。 jvm 然后认为这些类位于不同的“运行时包”中。引自the jvm specification,第 5.3 节:
在运行时,类或接口不仅仅由其名称决定,而是由一对:它的完全限定名称和它的定义类加载器决定。每个这样的类或接口都属于一个运行时包。类或接口的运行时包由包名和定义类或接口的类加载器决定。
在第 5.4.4 节中:
当且仅当满足以下任一条件时,类或接口 D 才能访问字段或方法 R:
...
R 要么是受保护的,要么是包私有的(即既不是公共的,也不是受保护的,也不是私有的),并且由与 D 相同的运行时包中的类声明。
【讨论】:
它必须工作,请看下面的例子,它工作得很好:
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()”
"受保护的修饰符指定 该成员只能在内部访问 它自己的包(与 包私有),此外,通过 另一个类的子类 包。”
【讨论】:
编译器应该捕获这样的错误。当您在运行时得到这个时,发生了一些错误。很可能您已经更改了完全重新编译的源代码。
它必须有效。这是一个运行示例 -
**
**
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
【讨论】: