Java内部类和静态嵌套类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/70324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:55:38  来源:igfitidea点击:

Java inner class and static nested class

javainner-classesstatic-classes

提问by Omnipotent

What is the main difference between an inner class and a static nested class in Java? Does design / implementation play a role in choosing one of these?

Java 中的内部类和静态嵌套类之间的主要区别是什么?设计/实现在选择其中之一时是否起作用?

采纳答案by Martin

From the Java Tutorial:

来自Java 教程

Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.

嵌套类分为两类:静态和非静态。声明为静态的嵌套类简称为静态嵌套类。非静态嵌套类称为内部类。

Static nested classes are accessed using the enclosing class name:

使用封闭类名访问静态嵌套类:

OuterClass.StaticNestedClass

For example, to create an object for the static nested class, use this syntax:

例如,要为静态嵌套类创建对象,请使用以下语法:

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

Objects that are instances of an inner class exist within an instance of the outer class. Consider the following classes:

作为内部类实例的对象存在于外部类的实例中。考虑以下类:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance.

InnerClass 的实例只能存在于 OuterClass 的实例中,并且可以直接访问其封闭实例的方法和字段。

To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:

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

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

see: Java Tutorial - Nested Classes

请参阅:Java 教程 - 嵌套类

For completeness note that there is also such a thing as an inner class withoutan enclosing instance:

为了完整起见,还有一个没有封闭实例内部类

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

Here, new A() { ... }is an inner class defined in a static contextand does not have an enclosing instance.

这里,new A() { ... }在静态上下文中定义内部类,没有封闭的实例。

回答by Mike Stone

Ummm... an inner class IS a nested class... do you mean anonymous class and inner class?

嗯...一个内部类是一个嵌套类...你的意思是匿名类和内部类?

Edit: If you actually meant inner vs anonymous... an inner class is just a class defined within a class such as:

编辑:如果您实际上是指内部与匿名……内部类只是在类中定义的类,例如:

public class A {
    public class B {
    }
}

Whereas an anonymous class is an extension of a class defined anonymously, so no actual "class is defined, as in:

而匿名类是匿名定义的类的扩展,因此没有定义实际的“类,如下所示:

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };

Further Edit:

进一步编辑:

Wikipedia claims there is a differencein Java, but I've been working with Java for 8 years, and it's the first I heard such a distinction... not to mention there are no references there to back up the claim... bottom line, an inner class is a class defined within a class (static or not), and nested is just another term to mean the same thing.

维基百科声称Java存在差异,但我使用 Java 已经 8 年了,这是我第一次听到这样的区别……更不用说那里没有参考资料来支持这一说法……底部行,内部类是在类中定义的类(静态或非静态),嵌套只是表示同一事物的另一个术语。

There is a subtle difference between static and non-static nested class... basically non-static inner classes have implicit access to instance fields and methods of the enclosing class (thus they cannot be constructed in a static context, it will be a compiler error). Static nested classes, on the other hand, don't have implicit access to instance fields and methods, and CAN be constructed in a static context.

静态和非静态嵌套类之间有细微的区别......基本上非静态内部类可以隐式访问封闭类的实例字段和方法(因此它们不能在静态上下文中构造,它将是一个编译器错误)。另一方面,静态嵌套类没有对实例字段和方法的隐式访问,并且可以在静态上下文中构造。

回答by Daniel Spiewak

The terms are used interchangeably. If you want to be really pedantic about it, then you coulddefine "nested class" to refer to a static inner class, one which has no enclosing instance. In code, you might have something like this:

这些术语可互换使用。如果你真的想学究,那么你可以定义“嵌套类”来引用一个没有封闭实例的静态内部类。在代码中,你可能有这样的事情:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

That's not really a widely accepted definition though.

不过,这并不是一个真正被广泛接受的定义。

回答by Wouter Coekaerts

Nested class is a very general term: every class which is not top level is a nested class. An inner class is a non-static nested class. Joseph Darcy wrote a very nice explanation about Nested, Inner, Member, and Top-Level Classes.

嵌套类是一个非常笼统的术语:每个不是顶级的类都是嵌套类。内部类是非静态嵌套类。Joseph Darcy 写了一篇关于Nested、Inner、Member 和 Top-Level Classes的非常好的解释。

回答by rmaruszewski

The instance of the inner class is created when instance of the outer class is created. Therefore the members and methods of the inner class have access to the members and methods of the instance (object) of the outer class. When the instance of the outer class goes out of scope, also the inner class instances cease to exist.

内部类的实例是在创建外部类的实例时创建的。因此内部类的成员和方法可以访问外部类的实例(对象)的成员和方法。当外部类的实例超出范围时,内部类的实例也不复存在。

The static nested class doesn't have a concrete instance. It's just loaded when it's used for the first time (just like the static methods). It's a completely independent entity, whose methods and variables doesn't have any access to the instances of the outer class.

静态嵌套类没有具体实例。它只是在第一次使用时加载(就像静态方法一样)。它是一个完全独立的实体,其方法和变量无法访问外部类的实例。

The static nested classes are not coupled with the outer object, they are faster, and they don't take heap/stack memory, because its not necessary to create instance of such class. Therefore the rule of thumb is to try to define static nested class, with as limited scope as possible (private >= class >= protected >= public), and then convert it to inner class (by removing "static" identifier) and loosen the scope, if it's really necessary.

静态嵌套类不与外部对象耦合,它们速度更快,并且它们不占用堆/堆栈内存,因为没有必要创建此类的实例。因此,经验法则是尝试定义静态嵌套类,范围尽可能有限(私有 >= 类 >= 受保护 >= 公共),然后将其转换为内部类(通过删除“静态”标识符)并放松范围,如果真的有必要的话。

回答by jrudolph

I don't think the real difference became clear in the above answers.

我不认为真正的区别在上述答案中变得清晰。

First to get the terms right:

首先要正确理解条款:

  • A nested class is a class which is contained in another class at the source code level.
  • It is static if you declare it with the staticmodifier.
  • A non-static nested class is called inner class. (I stay with non-static nested class.)
  • 嵌套类是包含在源代码级别的另一个类中的类。
  • 如果使用static修饰符声明它,则它是静态的。
  • 非静态嵌套类称为内部类。(我留在非静态嵌套类。)

Martin's answer is right so far. However, the actual question is: What is the purpose of declaring a nested class static or not?

到目前为止,马丁的回答是正确的。然而,实际的问题是:声明一个嵌套类是否为静态的目的是什么?

You use static nested classesif you just want to keep your classes together if they belong topically together or if the nested class is exclusively used in the enclosing class. There is no semantic difference between a static nested class and every other class.

如果您只想将您的类保持在一起,如果它们属于局部,或者嵌套类专门用于封闭类,则可以使用静态嵌套类。静态嵌套类和所有其他类之间没有语义差异。

Non-static nested classesare a different beast. Similar to anonymous inner classes, such nested classes are actually closures. That means they capture their surrounding scope and their enclosing instance and make that accessible. Perhaps an example will clarify that. See this stub of a Container:

非静态嵌套类是一个不同的野兽。类似于匿名内部类,这种嵌套类实际上是闭包。这意味着它们捕获了它们周围的范围和它们的封闭实例并使其可访问。也许一个例子会澄清这一点。看到这个容器的存根:

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

In this case you want to have a reference from a child item to the parent container. Using a non-static nested class, this works without some work. You can access the enclosing instance of Container with the syntax Container.this.

在这种情况下,您希望从子项引用到父容器。使用非静态嵌套类,这无需任何工作即可工作。您可以使用语法访问 Container 的封闭实例Container.this

More hardcore explanations following:

更多核心解释如下:

If you look at the Java bytecodes the compiler generates for an (non-static) nested class it might become even clearer:

如果您查看编译器为(非静态)嵌套类生成的 Java 字节码,它可能会变得更加清晰:

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
// access flags 1 public getContainer() : Container L0 LINENUMBER 7 L0 ALOAD 0: this GETFIELD Container$Item.this
new InnerClass(outerObject)
: Container ARETURN L1 LOCALVARIABLE this Container$Item L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 1 public <init>(Container,Object) : void L0 LINENUMBER 12 L0 ALOAD 0: this ALOAD 1 PUTFIELD Container$Item.this
package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}
: Container L1 LINENUMBER 10 L1 ALOAD 0: this INVOKESPECIAL Object.<init>() : void L2 LINENUMBER 11 L2 ALOAD 0: this ALOAD 2: data PUTFIELD Container$Item.data : Object RETURN L3 LOCALVARIABLE this Container$Item L0 L3 0 LOCALVARIABLE data Object L0 L3 2 MAXSTACK = 2 MAXLOCALS = 3 }

As you can see the compiler creates a hidden field Container this$0. This is set in the constructor which has an additional parameter of type Container to specify the enclosing instance. You can't see this parameter in the source but the compiler implicitly generates it for a nested class.

如您所见,编译器创建了一个隐藏字段Container this$0。这是在构造函数中设置的,该构造函数具有一个额外的 Container 类型参数来指定封闭实例。您无法在源代码中看到此参数,但编译器会为嵌套类隐式生成它。

Martin's example

马丁的例子

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

would so be compiled to a call of something like (in bytecodes)

所以会被编译成类似的调用(在字节码中)

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

For the sake of completeness:

为了完整起见:

An anonymous class isa perfect example of a non-static nested class which just has no name associated with it and can't be referenced later.

匿名类刚刚没有与之关联的名称,并且不能在以后引用非静态嵌套类的一个很好的例子。

回答by Jegschemesch

The Java tutorial says:

Java教程说

Terminology: Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.

术语:嵌套类分为两类:静态和非静态。声明为静态的嵌套类简称为静态嵌套类。非静态嵌套类称为内部类。

In common parlance, the terms "nested" and "inner" are used interchangeably by most programmers, but I'll use the correct term "nested class" which covers both inner and static.

通常,大多数程序员可以互换使用术语“嵌套”和“内部”,但我将使用正确的术语“嵌套类”,它涵盖内部和静态。

Classes can be nested ad infinitum, e.g. class A can contain class B which contains class C which contains class D, etc. However, more than one level of class nesting is rare, as it is generally bad design.

类可以无限嵌套,例如 A 类可以包含 B 类,B 类包含 C 类,C 类包含 D 类,等等。但是,多于一层的类嵌套很少见,因为它通常是糟糕的设计。

There are three reasons you might create a nested class:

您可能会创建嵌套类的三个原因:

  • organization: sometimes it seems most sensible to sort a class into the namespace of another class, especially when it won't be used in any other context
  • access: nested classes have special access to the variables/fields of their containing classes (precisely which variables/fields depends on the kind of nested class, whether inner or static).
  • convenience: having to create a new file for every new type is bothersome, again, especially when the type will only be used in one context
  • 组织:有时将一个类分类到另一个类的命名空间中似乎是最明智的,尤其是当它不会在任何其他上下文中使用时
  • 访问:嵌套类具有对其包含类的变量/字段的特殊访问权限(确切地说,哪些变量/字段取决于嵌套类的类型,无论是内部类还是静态类)。
  • 便利性:必须为每个新类型创建一个新文件同样很麻烦,尤其是当该类型仅在一个上下文中使用时

There are four kinds of nested class in Java. In brief, they are:

Java 中四种嵌套类。简而言之,它们是:

  • static class: declared as a static member of another class
  • inner class: declared as an instance member of another class
  • local inner class: declared inside an instance method of another class
  • anonymous inner class: like a local inner class, but written as an expression which returns a one-off object
  • 静态类:声明为另一个类的静态成员
  • 内部类:声明为另一个类的实例成员
  • 本地内部类:在另一个类的实例方法中声明
  • 匿名内部类:类似于本地内部类,但写为返回一次性对象的表达式

Let me elaborate in more details.

让我详细说明一下。



Static Classes

静态类

Static classes are the easiest kind to understand because they have nothing to do with instances of the containing class.

静态类是最容易理解的类型,因为它们与包含类的实例无关。

A static class is a class declared as a static member of another class. Just like other static members, such a class is really just a hanger on that uses the containing class as its namespace, e.g.the class Goatdeclared as a static member of class Rhinoin the package pizzais known by the name pizza.Rhino.Goat.

静态类是声明为另一个类的静态成员的类。就像其他静态成员一样,这样的类实际上只是一个使用包含类作为其命名空间的挂钩,例如,在包pizza 中声明为类Rhino的静态成员的类Goat被称为pizza.Rhino.Goat.

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

Frankly, static classes are a pretty worthless feature because classes are already divided into namespaces by packages. The only real conceivable reason to create a static class is that such a class has access to its containing class's private static members, but I find this to be a pretty lame justification for the static class feature to exist.

坦率地说,静态类是一个非常没有价值的特性,因为类已经被包划分为命名空间。创建静态类的唯一真正可能的原因是这样的类可以访问其包含类的私有静态成员,但我发现这是静态类功能存在的一个非常蹩脚的理由。



Inner Classes

内部类

An inner class is a class declared as a non-static member of another class:

内部类是声明为另一个类的非静态成员的类:

new *ParentClassName*(*constructorArgs*) {*members*}

Like with a static class, the inner class is known as qualified by its containing class name, pizza.Rhino.Goat, but inside the containing class, it can be known by its simple name. However, every instance of an inner class is tied to a particular instance of its containing class: above, the Goatcreated in jerry, is implicitly tied to the Rhinoinstance thisin jerry. Otherwise, we make the associated Rhinoinstance explicit when we instantiate Goat:

与静态类一样,内部类通过其包含的类名pizza.Rhino.Goat被称为限定,但在包含类中,可以通过其简单的名称来识别。然而,一个内部类的每一个实例被绑定到其包含类的特定实例:如上所述,山羊中创建杰里,被隐式地绑定到犀牛实例杰里。否则,我们在实例化Goat时使关联的Rhino实例显式:

new *InterfaceName*() {*members*}

(Notice you refer to the inner type as just Goatin the weird newsyntax: Java infers the containing type from the rhinopart. And, yes new rhino.Goat()would have made more sense to me too.)

(请注意,您在奇怪的语法中将内部类型称为Goat:Java 从犀牛部分推断包含类型。而且,是的new rhino.Goat()对我来说也更有意义。)

So what does this gain us? Well, the inner class instance has access to the instance members of the containing class instance. These enclosing instance members are referred to inside the inner class viajust their simple names, not viathis(thisin the inner class refers to the inner class instance, not the associated containing class instance):

那么这对我们有什么好处呢?好吧,内部类实例可以访问包含类实例的实例成员。这些封闭实例成员在内部类中仅通过它们的简单名称来引用,而不是通过this(内部类中的this指的是内部类实例,而不是关联的包含类实例):

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");
    }
}

In the inner class, you can refer to thisof the containing class as Rhino.this, and you can use thisto refer to its members, e.g. Rhino.this.barry.

在内部类,你可以参考这个包含类作为Rhino.this,您可以使用指其成员,如Rhino.this.barry



Local Inner Classes

本地内部类

A local inner class is a class declared in the body of a method. Such a class is only known within its containing method, so it can only be instantiated and have its members accessed within its containing method. The gain is that a local inner class instance is tied to and can access the final local variables of its containing method. When the instance uses a final local of its containing method, the variable retains the value it held at the time of the instance's creation, even if the variable has gone out of scope (this is effectively Java's crude, limited version of closures).

局部内部类是在方法体中声明的类。这样的类只在它的包含方法中是已知的,所以它只能被实例化并在它的包含方法中访问它的成员。好处是局部内部类实例绑定并可以访问其包含方法的最终局部变量。当实例使用其包含方法的最终局部变量时,该变量会保留实例创建时它所持有的值,即使该变量已超出范围(这实际上是 Java 的原始、有限版本的闭包)。

Because a local inner class is neither the member of a class or package, it is not declared with an access level. (Be clear, however, that its own members have access levels like in a normal class.)

因为局部内部类既不是类的成员,也不是包的成员,所以它没有声明访问级别。(但是,请注意,它自己的成员具有与普通类一样的访问级别。)

If a local inner class is declared in an instance method, an instantiation of the inner class is tied to the instance held by the containing method's thisat the time of the instance's creation, and so the containing class's instance members are accessible like in an instance inner class. A local inner class is instantiated simply viaits name, e.g.local inner class Catis instantiated as new Cat(), not new this.Cat() as you might expect.

如果在实例方法中声明了本地内部类,则在创建实例时,内部类的实例化与包含方法的this持有的实例相关联,因此可以像在实例中一样访问包含类的实例成员内部类。本地内部类仅通过其名称进行实例化,例如本地内部类Cat实例化为new Cat(),而不是您可能期望的 new this.Cat() 。



Anonymous Inner Classes

匿名内部类

An anonymous inner class is a syntactically convenient way of writing a local inner class. Most commonly, a local inner class is instantiated at most just once each time its containing method is run. It would be nice, then, if we could combine the local inner class definition and its single instantiation into one convenient syntax form, and it would also be nice if we didn't have to think up a name for the class (the fewer unhelpful names your code contains, the better). An anonymous inner class allows both these things:

匿名内部类是一种在语法上方便的编写本地内部类的方法。最常见的是,每次运行其包含的方法时,本地内部类最多只实例化一次。那么,如果我们可以将本地内部类定义和它的单个实例化成一种方便的语法形式,那就太好了,如果我们不必为类想一个名字(越少无用的您的代码包含的名称越好)。匿名内部类允许以下两种情况:

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

This is an expression returning a new instance of an unnamed class which extends ParentClassName. You cannot supply your own constructor; rather, one is implicitly supplied which simply calls the super constructor, so the arguments supplied must fit the super constructor. (If the parent contains multiple constructors, the “simplest” one is called, “simplest” as determined by a rather complex set of rules not worth bothering to learn in detail--just pay attention to what NetBeans or Eclipse tell you.)

这是一个表达式,返回一个未命名类的新实例,它扩展了ParentClassName。您不能提供自己的构造函数;相反,一个是隐式提供的,它只是调用超级构造函数,因此提供的参数必须适合超级构造函数。(如果父级包含多个构造函数,则称为“最简单”的构造函数,“最简单”由一组相当复杂的规则确定,不值得费心去详细学习——只需注意 NetBeans 或 Eclipse 告诉您的内容。)

Alternatively, you can specify an interface to implement:

或者,您可以指定要实现的接口:

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

Such a declaration creates a new instance of an unnamed class which extends Object and implements InterfaceName. Again, you cannot supply your own constructor; in this case, Java implicitly supplies a no-arg, do-nothing constructor (so there will never be constructor arguments in this case).

这样的声明创建了一个未命名类的新实例,它扩展了 Object 并实现了InterfaceName。同样,您不能提供自己的构造函数;在这种情况下,Java 隐式地提供了一个无参数、什么都不做的构造函数(因此在这种情况下永远不会有构造函数参数)。

Even though you can't give an anonymous inner class a constructor, you can still do any setup you want using an initializer block (a {} block placed outside any method).

即使您不能为匿名内部类提供构造函数,您仍然可以使用初始化程序块(放置在任何方法之外的 {} 块)进行您想要的任何设置。

Be clear that an anonymous inner class is simply a less flexible way of creating a local inner class with one instance. If you want a local inner class which implements multiple interfaces or which implements interfaces while extending some class other than Objector which specifies its own constructor, you're stuck creating a regular named local inner class.

需要明确的是,匿名内部类只是一种创建具有一个实例的本地内部类的不太灵活的方式。如果您想要一个实现多个接口的本地内部类,或者在扩展某个类而不是Object 的同时实现接口,或者指定自己的构造函数,那么您将不得不创建一个常规命名的本地内部类。

回答by HippoMan

There is a subtlety about the use of nested static classes that might be useful in certain situations.

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

Whereas static attributes get instantiated before the class gets instantiated via its constructor, static attributes inside of nested static classes don't seem to get instantiated until after the class's constructor gets invoked, or at least not until after the attributes are first referenced, even if they are marked as 'final'.

虽然静态属性在类通过其构造函数实例化之前被实例化,但嵌套静态类中的静态属性似乎直到类的构造函数被调用之后才会被实例化,或者至少在第一次引用属性之后才被实例化,即使它们被标记为“最终”。

Consider this example:

考虑这个例子:

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);

Even though 'nested' and 'innerItem' are both declared as 'static final'. the setting of nested.innerItem doesn't take place until after the class is instantiated (or at least not until after the nested static item is first referenced), as you can see for yourself by commenting and uncommenting the lines that I refer to, above. The same does not hold true for 'outerItem'.

即使 'nested' 和 'innerItem' 都被声明为 'static final'。Nested.innerItem 的设置在类被实例化之后(或者至少在嵌套的静态项目被第一次引用之后)才会发生,正如您可以通过注释和取消注释我所引用的行来亲眼看到的,以上。'outerItem' 也是如此。

At least this is what I'm seeing in Java 6.0.

至少这是我在 Java 6.0 中看到的。

回答by tejas

Nested class: class inside class

嵌套类:类内类

Types:

类型:

  1. Static nested class
  2. Non-static nested class [Inner class]
  1. 静态嵌套类
  2. 非静态嵌套类【内部类】

Difference:

区别:

Non-static nested class [Inner class]

非静态嵌套类【内部类】

In non-static nested class object of inner class exist within object of outer class. So that data member of outer class is accessible to inner class. So to create object of inner class we must create object of outer class first.

内部类的非静态嵌套类对象存在于外部类的对象中。这样内部类就可以访问外部类的数据成员。所以要创建内部类的对象,我们必须先创建外部类的对象。

##代码##

Static nested class

静态嵌套类

In static nested class object of inner class don't need object of outer class, because the word "static" indicate no need to create object.

在静态嵌套类中,内部类的对象不需要外部类的对象,因为“静态”一词表示不需要创建对象。

##代码##

If you want to access x, then write the following inside method

如果要访问x,那么在方法里面写如下

##代码##

回答by sactiw

I think, the convention that is generally followed is this:

我认为,通常遵循的约定是:

  • static classwithin a top level class is a nested class
  • non static classwithin a top level class is a inner class, which further has two more form:
    • local class- named classes declared inside of a block like a method or constructor body
    • anonymous class- unnamed classes whose instances are created in expressions and statements
  • 顶级类中的静态类嵌套类
  • 顶级中的非静态类内部类,它还有两种形式:
    • 本地类- 在块内声明的命名类,如方法或构造函数体
    • 匿名类- 在表达式和语句中创建实例的未命名类

However, few other points to remembersare:

但是,要记住的其他几点是:

  • Top level classes and static nested class are semantically same except that in case of static nested class it can make static reference to private static fields/methods of its Outer [parent] class and vice versa.

  • Inner classes have access to instance variables of the enclosing instance of the Outer [parent] class. However, not all inner classes have enclosing instances, for example inner classes in static contexts, like an anonymous class used in a static initializer block, do not.

  • Anonymous class by default extends the parent class or implements the parent interface and there is no further clause to extend any other class or implement any more interfaces. So,

    • new YourClass(){};means class [Anonymous] extends YourClass {}
    • new YourInterface(){};means class [Anonymous] implements YourInterface {}
  • 顶级类和静态嵌套类在语义上是相同的,除了在静态嵌套类的情况下,它可以静态引用其外部 [父] 类的私有静态字段/方法,反之亦然。

  • 内部类可以访问外部 [父] 类的封闭实例的实例变量。然而,并非所有内部类都有封闭实例,例如静态上下文中的内部类,如静态初始化块中使用的匿名类,则没有。

  • 默认情况下,匿名类扩展父类或实现父接口,并且没有进一步的子句来扩展任何其他类或实现更多接口。所以,

    • new YourClass(){};方法 class [Anonymous] extends YourClass {}
    • new YourInterface(){};方法 class [Anonymous] implements YourInterface {}


I feel that the bigger question that remains open which one to use and when? Well that mostly depends on what scenario you are dealing with but reading the reply given by @jrudolph may help you making some decision.

我觉得更大的问题仍然是使用哪个以及何时使用?嗯,这主要取决于您正在处理的情况,但阅读@jrudolph 给出的回复可能会帮助您做出一些决定。