Java中内部类和静态嵌套类的主要区别是什么?设计/实现是否在选择其中一个方面发挥作用?


当前回答

嵌套静态类的使用有一个微妙之处,这在某些情况下可能很有用。

尽管静态属性在类通过其构造函数实例化之前被实例化,嵌套静态类内部的静态属性似乎在类的构造函数被调用,或者至少直到属性被首次引用之后,即使它们被标记为“最终”。

考虑以下示例:

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

即使“nested”和“innerItem”都声明为“static final”。设置nested.innerItem的值在类实例化后才会发生(或至少直到第一次引用嵌套的静态项之后),正如您自己所看到的通过注释和取消注释上面提到的行。这一点不成立对于“outerItem”为true。

至少这是我在Java6.0中看到的。

其他回答

不同之处在于,同样是静态的嵌套类声明可以在封闭类之外实例化。

当您有一个非静态的嵌套类声明(也称为内部类)时,Java不允许您实例化它,除非通过封闭类。从内部类创建的对象链接到从外部类创建的目标,因此内部类可以引用外部类的字段。

但是如果它是静态的,那么链接就不存在,外部字段就不能被访问(除非像其他对象一样通过普通引用),因此您可以自己实例化嵌套类。

我认为,通常遵循的惯例是:

顶级类中的静态类是嵌套类顶级类中的非静态类是内部类还有两种形式:本地类-在块(如方法或构造函数体)内部声明的类匿名类-在表达式和语句中创建实例的未命名类

然而,需要记住的其他几点是:

顶级类和静态嵌套类在语义上是相同的,只是在静态嵌套类的情况下,它可以对其外部〔父〕类的私有静态字段/方法进行静态引用,反之亦然。内部类可以访问外部[父]类的封闭实例的实例变量。然而,并不是所有的内部类都有封闭实例,例如静态上下文中的内部类,比如静态初始值设定项块中使用的匿名类。默认情况下,匿名类扩展父类或实现父接口,并且没有进一步的子句来扩展任何其他类或实现任何其他接口。所以新建YourClass(){};意味着类〔Anonymous〕扩展了YourClass{}新建YourInterface(){};表示类〔Anonymous〕实现YourInterface{}


我觉得还有一个更大的问题,那就是什么时候使用?这主要取决于你正在处理的场景,但阅读@jrudolph给出的回复可能会帮助你做出一些决定。

这里是Java内部类和静态嵌套类之间的关键区别和相似之处。

希望它有帮助!

内部类

可以访问实例和静态方法以及字段的外部类与封闭类的实例关联,因此要实例化它,首先需要一个外部类的实例(注意new关键字place):Outerclass.InnerClass innerObject=outerObject.new InnerClass();无法定义任何静态成员本身不能有类或接口声明

静态嵌套类

无法访问外部类实例方法或字段不与封闭类的任何实例关联,因此要实例化它:OuterClass.StaticNestedClass嵌套对象=新OuterClass.staticNestClass();

相似之处

两个内部类甚至可以访问外部类的私有字段和方法外部类也可以访问内部类的私有字段和方法两个类都可以具有私有、受保护或公共访问修饰符

为什么使用嵌套类?

根据Oracle文档,有几个原因(完整文档):

这是一种对仅在一个地方使用的类进行逻辑分组的方法:如果一个类只对另一个类有用,那么将其嵌入该类并将两者保持在一起是合乎逻辑的。嵌套这样的“助手类”使它们的包更加精简。它增加了封装:考虑两个顶级类A和B,其中B需要访问A的成员,否则这些成员将被声明为私有。通过将类B隐藏在类A中,可以将A的成员声明为私有,B可以访问它们。此外,B本身可以对外界隐藏。它可以产生更可读和可维护的代码:将小类嵌套在顶级类中,使代码更接近使用它的地方。

A图表

静态嵌套类和非静态嵌套类之间的主要区别在于,静态嵌套类不能访问非静态外部类成员

Java编程语言允许您在另一个类中定义一个类。这样的类称为嵌套类,如下所示:

class OuterClass {
...
class NestedClass {
    ...
    }
}

嵌套类分为两类:静态类和非静态类。声明为静态的嵌套类称为静态嵌套类。非静态嵌套类称为内部类。我们应该记住的一点是,非静态嵌套类(内部类)可以访问封闭类的其他成员,即使它们被声明为私有。静态嵌套类只能访问封闭类的其他成员(如果这些成员是静态的)。它无法访问外部类的非静态成员。与类方法和变量一样,静态嵌套类与其外部类相关联。例如,要为静态嵌套类创建对象,请使用以下语法:

OuterClass.StaticNestedClass nestedObject =
 new OuterClass.StaticNestedClass(); 

要实例化内部类,必须首先实例化外部类。然后,使用以下语法在外部对象中创建内部对象:

OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();

为什么我们使用嵌套类

这是一种对仅在一个地方使用的类进行逻辑分组的方法。它增加了封装性。它可以产生更可读和可维护的代码。

来源:Java™ 教程-嵌套类