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

Eli*_*luf 11 java

我是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是教程中的错误,还是我可能不理解某些内容?谢谢

Hov*_*els 7

在教程中这是一个错误,或者我可能不理解somwthing?

错误在于您的理解,并且教程正确的.嵌套的静态类中没有任何地方可以直接操作外部类的实例字段.我在谈论这些没有附加实例的字段 - 在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 );
}
Run Code Online (Sandbox Code Playgroud)

但你不能这样做:

static void doSomethingElse2() {
    x++;
    System.out.println("x is " + x );
}
Run Code Online (Sandbox Code Playgroud)

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


你问:

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

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


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


Boa*_*ann 4

\n

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

\n
\n\n

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

\n\n

这里有两个不同的概念:

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

  2. \n
  3. “静态”的含义。“内部”嵌套类的实例始终与封闭类的实例相关联(将对封闭类实例的引用存储在内部类的隐藏实例字段中)。“静态”嵌套类没有这个。

  4. \n
\n\n

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

\n\n
\n

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

\n
\n\n

是的。

\n\n
\n

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

\n
\n\n

没有。

\n\n

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

\n\n

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

\n\n
\n

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

\n
\n\n

这一段还是在讲static是什么意思。它并不是试图谈论任何有关访问控制的内容,尽管它可能会被误解。

\n\n
\n\n

以下是正确的访问控制规则,由JLS\xc2\xa76.6.1 \xe2\x80\x93 确定可访问性给出

\n\n
\n

[如果]声明了成员或构造函数private,当且仅当访问发生在包含成员或构造函数声明的顶级类 (\xc2\xa77.6) 的主体内时,才允许访问。

\n
\n\n

这个定义出人意料地简短,但它涵盖了这里相关的所有内容。

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n