Java 静态嵌套类和常规类之间的区别

Java 静态嵌套类和常规类之间的区别,java,class,Java,Class,我知道这是一个有点重复的问题,但为了澄清一个非常重要的问题,我想以一种非常具体的方式提出这个问题。主要的问题是:当一个是静态嵌套类,而另一个是常规的顶级类,而不是访问包含类中的私有静态字段时,在其他方面相同的类之间是否有任何区别 // ContainingClass.java public class ContainingClass { private static String privateStaticField = ""; static class ContainedSt

我知道这是一个有点重复的问题,但为了澄清一个非常重要的问题,我想以一种非常具体的方式提出这个问题。主要的问题是:当一个是静态嵌套类,而另一个是常规的顶级类,而不是访问包含类中的私有静态字段时,在其他方面相同的类之间是否有任何区别

// ContainingClass.java
public class ContainingClass {
    private static String privateStaticField = "";

    static class ContainedStaticClass {
        public static void main(String[] args) {
            ContainingClass.privateStaticField = "new value";
        }
    }
}

// OutsideClass.java
public class OutsideClass {
    public static void main(String[] args) {
        ContainingClass.privateStaticField = "new value";  // DOES NOT COMPILE!!
    }
}

换句话说:
ContainedStaticClass
可以访问或执行的内容与
OutsideClass
可以访问或执行的内容之间唯一的区别是
OutsideClass
不能直接访问
ContainingClass.privateStaticField
?或者还有其他不常讨论或遇到的细微差别吗?

您的说法是正确的:静态类和外部类之间的唯一区别是对类和封闭类成员的访问。
static
关键字声明该类不是内部类:它实际上是封闭类范围内的外部类


请参见

一个细微的区别是嵌套类能够创建封闭类型的成员:

class ContainingClass {
    public static String privateStaticField = "a";

    static class ContainedStaticClass {
        public static String privateStaticField = "b";
        public static void main(String[] args) {
            System.out.println(privateStaticField);  // prints b
        }
    }
}

但这也与类的范围有关。

ContainedStaticClass具有包私有(即默认)可见性,OutsideClass具有公共可见性


您可以选择将ContainedStaticClass设置为protected或private,这不是OutsideClass的选项。

另一个细微的区别出现在反射用例中。您需要使用
class.forName
加载类的类名有点古怪

Class.forName("com.acme.OuterClass.Innerclass");  // not found
Class.forName("com.acme.OuterClass$Innerclass");  // correct
另见:
有几个细微的差别

可能最重要的一点是嵌套的静态类可以设置为
私有的
受保护的
。顶级类只能是包私有类或
公共类

我能想到的其他差异是技术细节,在这些细节重要的地方,您可能不应该编写代码:

  • 嵌套的静态类可以包含其他同名的类。当嵌套的静态类与外部类具有相同的名称,并且两者都在范围内时,嵌套的静态类将隐藏外部类

  • 嵌套的静态类是由其外部类的子类定义的,因此它在这些子类的作用域中,可以在没有完全限定名或静态导入的情况下引用

  • 同一个包中的两个外部级别类不能共享相同的名称,但一个类可以继承多个相同名称的嵌套静态类(例如,来自两个接口)。这不会导致编译错误,除非嵌套类的名称不正确

  • 嵌套的静态类可能由于继承而具有多个不同的属性,例如在
    类A中{static class B extensed A{}
    A.B
    可以称为
    A.B.B
    A.B.B
    ,等等。外部类只能有一个完全限定名

  • 外部类的名称等于其名称,但嵌套静态类的规范名称不等于其二进制名称。嵌套静态类的二进制名称使用符号
    $
    将外部类的二进制名称与嵌套静态类的简单名称分开


我不能完全证实,但就我所知,你的问题的答案是:不,没有其他区别。我可能错了,但我记得在某个地方读到过,非静态内部类有对外部类的隐式引用,但静态内部类没有。@Naveed,我还需要做更多的研究。但是,我很确定您认为非静态方法具有对调用它们的对象的隐式引用,而静态方法没有这样的引用,因为它们属于类而不是任何单个实例。换句话说,您可以在非静态方法中使用“this”关键字,但不能在静态方法中使用。谢谢。这是我要找的好东西。这肯定会让初学者绊倒。说得好。在这种情况下,问题是谁可以访问这些类,而不是这些类可以访问什么。我必须记住从两个方向思考。我选择这个答案是正确的,因为静态嵌套类所具有的所有附加“品质”,超过了其他顶级类,都是授予的,因为它在封闭类的范围内,即使不是所述封闭类的成员,嵌套的静态类实际上是外部类的成员:“类主体可以包含类成员的声明,即字段(§8.3)、方法(§8.4)、类(§8.5)和接口(§8.5)。”“成员类是其声明直接包含在另一类或接口声明正文中的类(§8.1.6,§9.1.4)。”