gpt4 book ai didi

java - 来自匿名静态实例的私有(private)实例成员访问

转载 作者:太空狗 更新时间:2023-10-29 22:41:16 24 4
gpt4 key购买 nike

考虑以下代码:

enum E {
A { public int get() { return i; } },
B { public int get() { return this.i; } },
C { public int get() { return super.i; } },
D { public int get() { return D.i; } };

private int i = 0;
E() { this.i = 1; }
public abstract int get();
}

我在前 2 个枚举常量声明(A 和 B)上遇到编译时错误,但在后 2 个枚举常量声明(C 和 D)上没有问题。错误是:

Error 1 on line A: non-static variable i cannot be referenced from a static context
Error 2 on line B: i has private access in E

因为 get 是一个实例方法,我不明白为什么我不能按我想要的方式访问实例变量 i

注意:从 i 的声明中删除 private 关键字也使代码可编译,我也不明白。

使用 Oracle JDK 7u9。

编辑

正如评论中所指出的,这并非特定于枚举,下面的代码会产生相同的行为:

class E {
static E a = new E() { public int get() { return i; } };
static E b = new E() { public int get() { return this.i; } };
static E c = new E() { public int get() { return super.i; } };
static E d = new E() { public int get() { return d.i; } };

private int i = 0;
}

最佳答案

观察到的行为是 Java 语言规范规定的,特别是对封闭类型字段的隐式访问,以及不继承私有(private)成员的规则。

不合格的现场访问

A { public int get() { return i; } }

规范 mandates :

The optional class body of an enum constant implicitly defines an anonymous class declaration (§15.9.5) that extends the immediately enclosing enum type. The class body is governed by the usual rules of anonymous classes; in particular it cannot contain any constructors.

这使得表达式 i 有点模棱两可:我们指的是封闭实例的字段还是内部实例?唉,内部实例doesn't inherit the field :

Members of a class that are declared private are not inherited by subclasses of that class.

因此,编译器得出结论,我们打算访问封闭实例的字段 - 但在静态 block 中, 没有封闭实例,因此出现错误。

通过this访问字段

B { public int get() { return this.i; } },

规范 mandates :

When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method was invoked (§15.12), or to the object being constructed.

因此,很明显我们想要内部类的字段,而不是外部类。

编译器拒绝字段访问表达式this.i的原因is :

Members of a class that are declared private are not inherited by subclasses of that class.

也就是说,私有(private)字段只能通过声明该字段的类型的引用访问,而不能通过其子类型访问。确实,

B { public int get() { return ((E)this).i; } },

编译得很好。

通过super访问

像这样,超refers调用方法的对象(或正在构造的对象)。因此很明显,我们指的是内部实例。

此外,super 是 E 类型,因此声明可见。

通过其他字段访问

D { public int get() { return D.i; } };

这里,D 是对E 中声明的静态字段D 的非限定访问。由于它是静态字段,因此使用哪个实例的问题没有实际意义,访问有效。

然而,它非常脆弱,因为只有在枚举对象完全构建后才会分配该字段。如果有人在构造期间调用 get(),则会抛出 NullPointerException

推荐

正如我们所见,访问其他类型的私有(private)字段受到一些复杂的限制。由于很少需要,开发人员可能没有意识到这些微妙之处。

虽然使字段 protected 会削弱访问控制(即允许包中的其他类访问该字段),但它会避免这些问题。

关于java - 来自匿名静态实例的私有(private)实例成员访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14138645/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com