在静态工厂方法中使用覆盖方法创建实例时,如何访问封闭类中的私有字段?



我不确定这里发生了什么。导致错误的行位于 Printer 类型的对象的实现中,该对象具有一个名为"string"的字段。整个内容都包含在名为"打印机"的抽象类中。如何在保持"字符串"字段私密性的同时实现我想要的东西?

public abstract class Printer {
static Printer blahPrinter(){
Printer blahPrinter =  new Printer("blah") {
@Override
void printString() {
System.out.println(this.string); //Here is the error: "string has private access in Printer"
}
};
System.out.println(blahPrinter.string); //No error on this line
return blahPrinter;
}
private final String string;  //Compiles and works as expected if I use a more visible access modifier
public Printer(String string) {
this.string = "I say " + string;
}
abstract void printString();
public static void main(String[] args) {
final Printer blahPrinter = Printer.blahPrinter();
blahPrinter.printString();
}
}

你可以通过说来修复它:

System.out.println(super.string);

问题是私有成员不由子类继承,尽管它们可以在声明私有成员的顶级类的整个主体中访问。因此,来自编译器的错误消息令人困惑(并且可能说"错误"(。

参见JLS 6.6.1关于可访问性:

否则,如果成员或构造函数被声明为私有,则 当且仅当访问发生在 包含成员声明的顶级类 (§7.6(或 构造 函数。

这里就是这种情况,因为您是从包含声明的Printer正文中访问私有成员的

。但是JLS第8.2节"类成员"有关于继承的规则:

声明为 private 的类的成员不由 该类的子类。

所以你不能说this.string,因为字段string不存在于你的printString方法所在的Printer的匿名子类上。

通过明确引用super(或在 Hero 的答案中使用类型转换(,您可以清楚地表明您不想访问子类中的字段,而是从超类访问字段。

在您的匿名子类中,您可以将this.string替换为((Printer) this).stringsuper.string

最新更新