为了账号安全,请及时绑定邮箱和手机立即绑定

Oracle Java 教程 - 静态类 - 教程中可能出现的错误

Oracle Java 教程 - 静态类 - 教程中可能出现的错误

潇潇雨雨 2021-08-25 17:19:31
我是 Java 新手,从 Oracle Java 教程学习 Java。我现在正在学习嵌套类、静态类和内部类。我发现以下解释似乎很奇怪,我认为这是错误的。来自:https : //docs.oracle.com/javase/tutorial/java/javaOO/nested.html嵌套类是其封闭类的成员。非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有。静态嵌套类无权访问封闭类的其他成员最后一句“静态嵌套类无法访问封闭类的其他成员”很奇怪,但可能指的是实例成员,说静态类就像一个静态方法,无法访问实例变量。但下一个注释更奇怪:注意:静态嵌套类与其 外部类(和其他类)的实例成员交互,就像任何其他顶级类一样。实际上,静态嵌套类在行为上是一个顶层类,为了方便打包,它嵌套在另一个顶层类中。这看起来很奇怪,因为它意味着静态类不能访问外部类的私有实例成员。我编写了以下编译和运行的代码,并演示了静态类可以访问外部实例私有变量。public class A {    private int x;    static private int y;    static public class B{        static void doSomething(){            y++;            System.out.println("y is now " + y );        }        static void doSomethingElse(A a)        {            a.x++;            System.out.println("a.x is " + a.x );        }    }}// ------public class Main {    public static void main(String[] args){        A a = new A();        A.B b = new A.B();        b.doSomething();        b.doSomethingElse(a);    }}这是教程中的错误,还是我可能不太理解?谢谢
查看完整描述

2 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

这是教程中的错误,还是我可能不太理解?

你完全理解。教程页面充其量是误导性的。

这里有两个不同的概念:

  1. 您是否有权访问 Java访问控制规则(例如,私有、包私有、受保护、公共)内的事物。

  2. “静态”的含义。“内部”嵌套类的实例总是与封闭类的实例相关联(在内部类的隐藏实例字段中存储对封闭类实例的引用)。“静态”嵌套类没有。

教程页面混淆了这两个概念。

嵌套类是其封闭类的成员。

是的。

非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有。静态嵌套类无权访问封闭类的其他成员。

不。

通过自己提供实例,您会看到静态类确实可以访问封闭类的成员,包括私有实例字段,因此为什么a.x++;在您的示例中进行编译。这就是访问。

通过使用“访问”和“私有”这两个词,该段落强烈暗示它是在 Java 语言规范中给出的定义中讨论访问控制但事实并非如此。它只是试图解释概念#2,关于封闭类的实例如何与嵌套类相关联。即便如此,它仍然是错误的,因为静态嵌套类当然可以访问封闭类的静态成员,而段落说他们没有。写那个页面的人很草率。

注意:静态嵌套类与其外部类(和其他类)的实例成员交互,就像任何其他顶级类一样。实际上,静态嵌套类在行为上是一个顶层类,为了方便打包,它嵌套在另一个顶层类中。

这一段还在讲静态是什么意思。虽然它有可能被误解,但它并不试图说明访问控制。


这是正确的访问控制规则,由JLS§6.6.1 – Determining Accessibility 给出:

[如果] 声明了成员或构造函数private,当且仅当它出现在包含成员或构造函数声明的顶级类(第 7.6 节)的主体内时,才允许访问 [..]。

该定义出奇地短,但它涵盖了此处相关的所有内容。

这意味着所有嵌套类(因为它们“在顶级类的主体内”)都可以访问封闭类的所有成员和构造函数,无论嵌套类是静态类还是实例类,也不管嵌套类是静态类还是实例类访问的东西是静态的或实例。

此外,所有嵌套类还可以访问同一顶级类中所有其他嵌套类的所有成员和构造函数。

顶级类可以访问嵌套在其中的所有类的所有成员和构造函数。

我引用的JLS那句话是指private访问。但是如果成员或构造函数不是private,那么它的访问级别只能更宽松,至少包访问,并且包含在同一顶级类型中的类也不可避免地在同一个包中,因此它们可以相互访问即使没有特殊处理。

基本上,顶级(非封闭)类及其中的所有内容都构成了一个nest。原则上,该巢中的所有内容都可以访问其中的其他所有内容。如果它是一个实例成员,您还需要先以某种方式获取一个实例,但这总是正确的。


查看完整回答
反对 回复 2021-08-25
?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

这是教程中的错误,还是我不太了解某些内容?


错误在于您的理解,而教程是正确的。在嵌套的静态类中没有任何地方可以直接操作外部类的实例字段。我说的是没有附加实例的这些字段——如果没有x附加到A实例,你就无法直接操作。


所以你可以这样做:


static void doSomethingElse(A a) {

    a.x++;  // x is part of the A instance passed into a parameter

    System.out.println("a.x is " + a.x );

}

但你不能这样做:


static void doSomethingElse2() {

    x++;

    System.out.println("x is " + x );

}

如果B是静态嵌套或独立的非嵌套类,则此代码将相同。


你问:


“静态嵌套类与其外部类的实例成员交互,就像任何其他顶级类一样”?


完全如上所示——非静态嵌套类可以直接与a字段交互(如图doSomethingElse2()所示),而无需支持A实例,而静态嵌套类和独立类都不能。它们都需要单独的 A 实例,此处将其传递到您的doSomethingElse(A a)方法参数中。


静态嵌套和独立的主要区别在于前者,嵌套类,可以访问外部类的私有成员,而独立则没有。也许这就是你困惑的根源。


查看完整回答
反对 回复 2021-08-25
  • 2 回答
  • 0 关注
  • 157 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信