当前位置: 首页 > 知识库问答 >
问题:

OracleJava教程-静态类-教程中可能的错误

章侯林
2023-03-14

我是Java新手,从OracleJava教程学习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个答案

缪修德
2023-03-14

这是教程中的错误,还是我可能没有很好地理解什么?

你理解得很好。教程页面充其量是误导性的。

这里有两个不同的概念:

>

  • 您是否有权限访问Java权限改造规则内的东西(例如,私有、包私有、受保护、公共)。

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

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

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

    没错。

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

    不。

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

    该段使用“访问”和“私人”一词,强烈表明它是在Java语言规范中给出的定义范围内谈论权限改造。但它不是。它只是试图解释概念#2,关于封闭类的实例如何与嵌套类相关联。即使这样,它仍然是错误的,因为静态嵌套类当然可以访问封闭类的静态成员,而段落说它们不能。写那一页的人很草率。

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

    这一段仍在讨论静态的含义。虽然它有可能被误解,但它并没有试图说任何关于访问控制的话。

    下面是JLS§6.6.1-确定可访问性给出的正确权限改造规则:

    [如果]成员或构造函数被声明为私有,[...]访问被允许当且仅当它发生在包含成员或构造函数声明的顶级类(§7.6)的主体中时。

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

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

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

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

    我引用的JLS的句子是指私有访问。但是如果成员或构造函数不是私有的,那么它的访问级别只能是更允许的,至少是包访问,并且包含在同一个顶级类型中的类也不可避免地在同一个包中,所以它们对每个都可以访问其他甚至没有特殊待遇。

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

  • 苏硕
    2023-03-14

    这是教程中的一个错误,还是我没有很好地理解某些东西?

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

    所以你可以这样做:

    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)方法参数中。

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

     类似资料:
    • 我是新来的Java,正在阅读Oracle教程。每一节后面都有问题和答案,一个答案里面有一句我听不懂(见下面粗线)。 来源是https://docs.oracle.com/javase/tutorial/java/javaOO/QandE/objects-answers.html 我指的是问题2,见粗体字。据我所知,如果没有对数组的引用,那么数组有资格进行垃圾收集。是否存在对此数组持有的对象的引用并

    • 1、打开代码配置文件config.php 开启伪静态(false改为true) 2、后台开启pathinfo模式 3、环境配置 Nginx配置 找到nginx的配置文件Nginx.conf添加伪静态配置代码(以下代码) location / { if \(!-e $request\_filename\) { rewrite ^\(.\*\)$ /index.php?s=$1 las

    • 本文向大家介绍Tomcat中对静态资源的处理教程,包括了Tomcat中对静态资源的处理教程的使用技巧和注意事项,需要的朋友参考一下 前言 Tomcat 中的请求都是由 Servlet 处理,静态资源也不例外。在默认的 web.xml 中,配置了一个 DefaultServlet 用于处理静态资源,它支持缓存和断点续传。 DefaultServlet 的基本处理过程如下: 查找资源是否存在缓存 检查

    • 原文:Pyplot tutorial matplotlib.pyplot是一个命令风格函数的集合,使matplotlib的机制更像 MATLAB。 每个绘图函数对图形进行一些更改:例如,创建图形,在图形中创建绘图区域,在绘图区域绘制一些线条,使用标签装饰绘图等。在matplotlib.pyplot中,各种状态跨函数调用保存,以便跟踪诸如当前图形和绘图区域之类的东西,并且绘图函数始终指向当前轴域(请

    • 本文向大家介绍iOS制作framework静态库图文教程,包括了iOS制作framework静态库图文教程的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了iOS制作framework静态库教程 ,供大家参考,具体内容如下 环境: 硬件:macbook air 系统:OSX EI Capitan 版本:10.11.3 xcode :Version 7.2.1 (7C1002) 最近在做

    • 原文:Path Tutorial 位于所有matplotlib.patch对象底层的对象是Path,它支持moveto,lineto,curveto命令的标准几个,来绘制由线段和样条组成的简单和复合轮廓。 路径由(x,y)顶点的(N,2)数组,以及路径代码的长度为 N 的数组实例化。 例如,为了绘制(0,0)到(1,1)的单位矩形,我们可以使用这个代码: import matplotlib.pyp