外基类的访问字段

时间:2014-08-12 18:05:54

标签: java

在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

中具有私有访问权限

1 个答案:

答案 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变为可访问。