我知道以前曾问过这个问题,但是大多数关于某个库都非常具体。给出的答案并没有真正向我解释发生了什么。
这就是为什么我在这里设置一个非常简单的测试方案并尝试摆弄它的原因,但是仍然存在一些问号!Online Java Example
简单的代码由两个文件组成:
Main.java
public class Main
{
public static void main(String[] args) {
// this works, and inner1 and inner2 seem to be new instances
Outer.Inner inner1 = new Outer.Inner();
Outer.Inner inner2 = new Outer.Inner();
inner1.setName("Mario");
inner1.say();
inner2.setName("Luigi");
inner2.say();
// if Inner is not a public static class this gives this error:
// error: an enclosing instance that contains Outer.InnerNoStatic is required
Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();
}
}
Outer.java
public class Outer {
public static class Inner {
private String name;
public void say() {
System.out.println("Hi " + name);
}
public void setName(String name) {
this.name = name;
}
}
public class InnerNoStatic {
public void say() {
System.out.println("Hi from InnerNoStatic");
}
}
}
因此,即使Inner
类是用静态声明的,我们仍然创建了两个新实例,分别称为inner1和inner2。为什么叫静态呢?
反过来,如果我删除了静态变量,如InnerNoStatic
所示,我将如何获取该类的实例?
[static
在此处指示相对于Inner
如何使用InnerNoStatic
和Outer
。
因为Inner
在Outer
中是静态的,所以它没有绑定到Outer
的任何特定实例(一如既往,静态成员属于该类,而不属于该类的任何特定实例)。这就解释了如何编译:
Outer.Inner inner1 = new Outer.Inner();
InnerNoStatic
,但是,是一个实例成员(也就是说:如果它不是静态的,它将绑定到给定的成员)。这就解释了为什么编译器会在这里引发错误:
Outer.InnerNoStatic inner3 = new Outer.InnerNoStatic();
因为InnerNoStatic
必须绑定到Outer
的实例,所以需要使用这样的实例来创建inner3
:
Outer.InnerNoStatic inner3 = new Outer().new InnerNoStatic(); //note the calls
您也可以使用现有实例。
Outer outer = new Outer();
Outer.InnerNoStatic inner3 = outer.new InnerNoStatic();
在这两种情况下,都使用Outer
实例来构建InnerNoStatic
实例(没有变量指向使用Outer
创建的new Outer().new InnerNoStatic()
对象)
注意:很容易将new Outer.Inner();
与new Outer().new Inner();
混淆。它们没有做相同的事情(前者中的“外部”基本上起着命名空间的作用,而后者中的new Outer()
创建了Outer
对象)。也就是说,前者有一个构造函数调用(Inner()
),而后者有两个构造函数调用(Outer()
和Inner()
)。
因此,即使Inner类是用静态声明的,我们仍然创建了两个新实例,分别称为inner1和inner2。为什么叫静态呢?
static
表示嵌套类具有更多的独立性。它主要是为了提高封装性,可读性,可维护性而设计的,这是对类进行逻辑分组的好方法。
反过来,如果我删除静态对象,如InnerNoStatic,我将如何获取该类的实例?
语法有点不同,因为您需要Outer
的实例。
Outer.InnerNoStatic inner3 = new Outer(). new InnerNoStatic();
因此,即使Inner类是用静态声明的,我们仍然创建了两个新实例,分别称为inner1和inner2。为什么叫静态呢?
“静态”内部类的对象不与其封闭类的对象绑定,与非“静态”内部类相反。拥有一个“静态”内部类而不是将其移到“顶级”是一种向用户发出信号的便捷方式,可向用户发出该内部类的对象与外部类没有太多用处的信息,类似于e。 G。 Map.Entry
。
反过来,如果我删除静态对象,如InnerNoStatic,我将如何获取该类的实例?
例如
public class Outer {
private InnerNoStatic innerNoStatic = new InnerNoStatic();
public InnerNoStatic getInnerNoStatic () {
return innerNoStatic;
}
// ...
和
Outer.InnerNoStatic innerNoStatic = new Outer().getInnerNoStatic();
非静态内部类始终具有对相应外部类的引用。结果,此类只能由外部类实例化。
相反,如果可见性允许,则静态内部类不引用外部类,并且可以由任何其他对象创建。这与静态方法的行为非常相似,后者不需要调用对象实例。