在Java中,内部类通常可以访问外部类'私人会员。 在编写Android应用程序时,我有一个静态内部类,它扩展了它的外部类。 事实证明,无法访问外部类的私有字段:
class Outer {
private int m_field = 1;
static class Inner extends Outer {
Inner() {
m_field = 2;
}
}
}
它给出了一个令人困惑的错误消息:
错误:无法从静态上下文引用非静态变量m_field
即使除了班级本身以外什么都不是静态的。
当字段m_field受到保护时,它编译没有问题。 但是,这样做的时候:
class Outer {
private int m_field = 1;
static class Inner extends Outer {
Inner() {
((Outer)this).m_field = 2;
}
}
}
它没有问题。 这是编译器中的错误吗?为什么你需要转换为外部类,你已经是一个实例?
编辑:
对于一个真实的用例,请考虑这样的类:
public abstract class MyItem {
private int m_counter = 0;
public abstract int updateSomething();
public static class CountItem extends MyItem {
public int updateSomething() { m_counter++; }
}
public static class DoubleCountItem extends MyItem {
public int updateSomething() { m_counter += 2; }
}
}
非常抽象的例子,但它可以用来为抽象类提供基本的实现,而这些抽象类本身并不需要很多代码。
EDIT2:
正如@Nathan建议的那样,似乎这个问题可以通过2个类重新创建而不需要嵌套:
class Base {
private int x = 0;
void a(Extended b) {
((Base)b).x = 1; //<-- with cast: compiles, without: error
}
}
class Extended extends Base {
}
这提供了更好的错误消息:
错误:x在Base
中具有私有访问权限
答案 0 :(得分:5)
你在这里看到的是,只要你在Outer的类定义中,就可以访问具有类Outer的任何东西的私有成员,包括强制转换为Outer的东西。它们必须具有相同的类(而不是作为类的实例,具有不同的具体子类)。
内部类是一个复杂的问题,这是一个较小的例子:
public class A {
private int foo = 0;
public String toString() {
return "A: foo=" + foo;
}
public static void main(String[] args) {
B b = new B();
System.out.println(b);
((A)b).foo = 1;
System.out.println(b);
}
}
class B extends A {
}
这个编译,只是因为它在A的类定义中。将main方法移动到其他地方(例如在B中),你不能再引用foo。
这是您在编码等于方法时看到的内容,您可以在其中访问同一类的另一个实例的私有字段,因为您正在编写一个属于类定义的方法。
Java language specification, in 6.6.1 Determining Accessibility:
否则,如果成员或构造函数被声明为private,则当且仅当它发生在包含成员或构造函数声明的顶级类(第7.6节)的主体内时才允许访问。
不允许强制转换为外部访问是不允许的,因为a)m_field是Outer的私有成员,因此它对子类是不可见的,并且b)它不是被声明的类的成员。添加强制转换意味着编译器将其视为外部,并且m_field变为可访问。