如何在 Java 中实例化内部 class 真的有效吗?
How instantiating an inner class in Java really works?
我正在从 innerclass 创建一个实例,但我不明白这个语法是什么意思。
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
我知道如果不从外部 OuterClass outerObject = new OuterClass();
获取对象就无法从内部 class 获取对象,然后我们使用外部 class 的对象outerObject从内部classouterObject.new InnerClass();
获取一个实例,那么OuterClass.InnerClass实际上意味着什么Java 文档中没有解释,因为它指出:
要实例化内部 class,您必须首先实例化外部 class。然后,使用以下语法在外部对象中创建内部对象 OuterClass.InnerClass innerObject = outerObject.new InnerClass();
如果我没记错的话,句法含义如下:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
InnerClass The class InnerClass
. which is an inner class of
OuterClass OuterClass
innerObject has an instance named innerObject
= which is assigned the value
new InnerClass() of a new InnerClass instance
. such that when you use
OuterClass.this from within
InnerClass methods invoked on
innerObject, it refers to
outerObject outerObject.
这里的关键是内部classes是通过引用外部class创建的。如果你的 InnerClass 是静态的(一个 InnerClass 代表整个 OuterClass class),你会看到对外部 class 的引用是静态的:
static class InnerClass { ... }
...
//Initialization will become:
OuterClass.InnerClass innerObject = new OuterClass.InnerClass();
^ this part is a static OuterClass reference
另一方面,在您当前的情况下(InnerClass 不是静态的),内部 class 必须以对象的形式引用 OuterClass 创建 - outerObject
。此外,您实际上可以通过引用 OuterClass.this
:
从 InnerClass 访问 outerObject
OuterClass.java
public class OuterClass
{
class InnerClass
{
public OuterClass getOuterClassReference()
{
return OuterClass.this;
}
}
}
Main.java
class Main
{
public static void main(String[] args)
{
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
System.out.println(outerObject);
System.out.println(innerObject.getOuterClassReference());
System.out.println(outerObject == innerObject.getOuterClassReference());
}
}
输出:
OuterClass@36baf30c
OuterClass@36baf30c
true
这里,输出中的36baf30c
是任意内存地址。这两条输出线将始终相同。您可以清楚地看到,从 InnerClass 实例中引用 OuterClass.this
将 return 初始化时提供的 OuterClass 实例。这是您不能只调用 new InnerClass()
的部分原因 - 引用 OuterClass.this
在没有提供实例的情况下无法正确初始化。
这是 class 的名称,这样命名很可能是为了让编译器更容易找到定义。
如果您将变量声明为 InnerClass
类型,它将查找文件 InnerClass.java
,但没有这样的文件。
圆点符号表示它实际上是 OuterClass
的成员,因此它将在文件 OuterClass.java
.
中查找定义
这与使用图书馆中的 class 相同,
com.example.MyLibrary.ExternalClass myExternalObject;
JVM 对 OuterClass
和 InnerClass
没有区别:类 都是 POJO 并且单独 类。但是 InnerClass
不是 static
因此它有内部 this
引用 OuterClass
的实例(因此它应该只用现有的 OuterClass
实例创建)
public class OuterClass {
public class InnerClass {
public OuterClass getOuterClassReference() {
return OuterClass.this;
}
}
}
OuterClass outerObject = new OuterClass();
OuterClass.InnterClass innerObject = outerObject.new InnerClass(); // innerObject has this reference to outerObject
public class OuterClass {
public static class InnerClass {}
}
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = new OuterClass.InnerClass(); // innerObject does not have this reference to outerObject
换句话说,你可以像这样自己模拟InnterClass
:
public class OuterClass {
}
public class InnerClass {
private final OuterClass outer;
public InnerClass(OuterClass outer) {
this.outer = outer;
}
}
Outerclass.Innerclass
只是内部类完整路径的一部分。
完整路径类似于 packagename.Outerclass.Innerclass
.
因此,
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
真的和类似的东西没有什么不同:
java.util.ArrayList<T> varName = new java.util.ArrayList<T>();
您可以将内部 class 定义为 OuterClass
的静态成员
public class OuterClass {
public static class StaticInnerClass {
int i = 0;
public String call() {
i++;
return this.getClass().getName() + " i=" + i;
}
}
}
所以定义静态内部class编译知道成员是一个class,内存区域在编译时实例化(它可以静态方式访问)并且你可以应用新的运算符和新运算符在另一个内存区域中实例化 class。
例如在主class
public class Main {
public static void main(String[] args) {
/**
*
*
* @@@ New instance of Inner class
*/
OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass();
System.out.println(staticInnerClass.call());
System.out.println(staticInnerClass.call());
staticInnerClass = new OuterClass.StaticInnerClass();
System.out.println("\n" + staticInnerClass.call());
System.out.println(staticInnerClass.call());
}
}
有输出
// new of inner class and i = 0
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2
// new of inner class and i = 0
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2
参考文献:https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html.
我正在从 innerclass 创建一个实例,但我不明白这个语法是什么意思。
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
我知道如果不从外部 OuterClass outerObject = new OuterClass();
获取对象就无法从内部 class 获取对象,然后我们使用外部 class 的对象outerObject从内部classouterObject.new InnerClass();
获取一个实例,那么OuterClass.InnerClass实际上意味着什么Java 文档中没有解释,因为它指出:
要实例化内部 class,您必须首先实例化外部 class。然后,使用以下语法在外部对象中创建内部对象 OuterClass.InnerClass innerObject = outerObject.new InnerClass();
如果我没记错的话,句法含义如下:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
InnerClass The class InnerClass
. which is an inner class of
OuterClass OuterClass
innerObject has an instance named innerObject
= which is assigned the value
new InnerClass() of a new InnerClass instance
. such that when you use
OuterClass.this from within
InnerClass methods invoked on
innerObject, it refers to
outerObject outerObject.
这里的关键是内部classes是通过引用外部class创建的。如果你的 InnerClass 是静态的(一个 InnerClass 代表整个 OuterClass class),你会看到对外部 class 的引用是静态的:
static class InnerClass { ... }
...
//Initialization will become:
OuterClass.InnerClass innerObject = new OuterClass.InnerClass();
^ this part is a static OuterClass reference
另一方面,在您当前的情况下(InnerClass 不是静态的),内部 class 必须以对象的形式引用 OuterClass 创建 - outerObject
。此外,您实际上可以通过引用 OuterClass.this
:
outerObject
OuterClass.java
public class OuterClass
{
class InnerClass
{
public OuterClass getOuterClassReference()
{
return OuterClass.this;
}
}
}
Main.java
class Main
{
public static void main(String[] args)
{
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
System.out.println(outerObject);
System.out.println(innerObject.getOuterClassReference());
System.out.println(outerObject == innerObject.getOuterClassReference());
}
}
输出:
OuterClass@36baf30c
OuterClass@36baf30c
true
这里,输出中的36baf30c
是任意内存地址。这两条输出线将始终相同。您可以清楚地看到,从 InnerClass 实例中引用 OuterClass.this
将 return 初始化时提供的 OuterClass 实例。这是您不能只调用 new InnerClass()
的部分原因 - 引用 OuterClass.this
在没有提供实例的情况下无法正确初始化。
这是 class 的名称,这样命名很可能是为了让编译器更容易找到定义。
如果您将变量声明为 InnerClass
类型,它将查找文件 InnerClass.java
,但没有这样的文件。
圆点符号表示它实际上是 OuterClass
的成员,因此它将在文件 OuterClass.java
.
这与使用图书馆中的 class 相同,
com.example.MyLibrary.ExternalClass myExternalObject;
JVM 对 OuterClass
和 InnerClass
没有区别:类 都是 POJO 并且单独 类。但是 InnerClass
不是 static
因此它有内部 this
引用 OuterClass
的实例(因此它应该只用现有的 OuterClass
实例创建)
public class OuterClass {
public class InnerClass {
public OuterClass getOuterClassReference() {
return OuterClass.this;
}
}
}
OuterClass outerObject = new OuterClass();
OuterClass.InnterClass innerObject = outerObject.new InnerClass(); // innerObject has this reference to outerObject
public class OuterClass {
public static class InnerClass {}
}
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = new OuterClass.InnerClass(); // innerObject does not have this reference to outerObject
换句话说,你可以像这样自己模拟InnterClass
:
public class OuterClass {
}
public class InnerClass {
private final OuterClass outer;
public InnerClass(OuterClass outer) {
this.outer = outer;
}
}
Outerclass.Innerclass
只是内部类完整路径的一部分。
完整路径类似于 packagename.Outerclass.Innerclass
.
因此,
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
真的和类似的东西没有什么不同:
java.util.ArrayList<T> varName = new java.util.ArrayList<T>();
您可以将内部 class 定义为 OuterClass
的静态成员public class OuterClass {
public static class StaticInnerClass {
int i = 0;
public String call() {
i++;
return this.getClass().getName() + " i=" + i;
}
}
}
所以定义静态内部class编译知道成员是一个class,内存区域在编译时实例化(它可以静态方式访问)并且你可以应用新的运算符和新运算符在另一个内存区域中实例化 class。
例如在主class
public class Main {
public static void main(String[] args) {
/**
*
*
* @@@ New instance of Inner class
*/
OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass();
System.out.println(staticInnerClass.call());
System.out.println(staticInnerClass.call());
staticInnerClass = new OuterClass.StaticInnerClass();
System.out.println("\n" + staticInnerClass.call());
System.out.println(staticInnerClass.call());
}
}
有输出
// new of inner class and i = 0
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2
// new of inner class and i = 0
innerclass.OuterClass$StaticInnerClass i=1
innerclass.OuterClass$StaticInnerClass i=2
参考文献:https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html.