关于 class 嵌套在 java 中的查询
A query about class nesting in java
public class Outer{
public class Inner{
}
}
public class Main {
public static void main(String[] args) {
Outer objOut = new Outer();
//Outer.Inner object1= objOut.new Inner(); // runes without a problem
//objOut.Inner object2= objOut.new Inner(); //gives error
}
}
这听起来有点业余,但是,Outer.Inner
和 objOut.Inner
之间有什么区别。
两者都不编译。
要使前者编译,应声明一个变量,并给出该变量的名称。
Outer.Inner obj = objOut.new Inner();
即使您执行了这一步,后者也不会编译,因为 objOut.Inner
既不是类型(因为主表达式 objOut
不是类型)也不是有效名称(因为 [= an identifier (jls-3.8) 中不允许使用 14=])。
针对您的情况的简化 rule (jls-14.4) 是
LocalVariableType VariableDeclaratorId [= VariableInitializer];
这个:
Outer.Inner = objOut.new Inner();
将无法编译,但如果将其更改为:
Outer.Inner object = objOut.new Inner();
将意味着创建一个 inner class 的实例,它引用了 Outer
class - objOut
将是 Outer
[=48= 的实例].
还有这个:
objOut.Inner = objOut.new Inner();
将无法编译,因为 objOut
Outer
class 的实例没有属性 Inner
。
而且 Outer
class 知道 Inner
class 的实例 - 它是 Inner
class 知道的实例创建它的 Outer
class 实例。
编辑
行:
objOut.Inner object2= objOut.new Inner();
不会编译,因为 Inner
类型标识符属于 Outer
class 而不是此 class 的实例。
您不能将一个变量名用作另一个变量的 类型 ,这正是您要对 objOut.Inner
所做的。变量的类型是Inner
(或者可选的Outer.Inner
)。
因为 Inner
是一个 inner class,它与其外部 class 的 实例 相关联(它的 包含实例)。当您创建它的实例时,您可以选择¹指定它关联的对象实例,这就是您在 objOut.new Inner
.
中所做的
这个例子可能有助于使它更清楚一点:
public class Example {
private String str;
public class Inner {
void show() {
// Show the string for the Example this Inner is part of
System.out.println(Example.this.str);
}
}
public Example(String s) {
this.str = s;
}
public static void main(String[] args) {
Example e1 = new Example("e1");
Example e2 = new Example("e2");
Inner i1 = e1.new Inner();
i1.show(); // "e1"
Inner i2 = e2.new Inner();
i2.show(); // "e2"
}
}
注意 i1
Inner
实例如何将 e1
作为其封闭的 Example
实例,因此可以看到 e1
的 str
, 但是 i2
得到 e2
作为它的封闭实例所以它看到 e2
的 str
.
我建议 this Java tutorial 了解更多信息。
¹ 有时它不是可选的,例如在我上面的 Example
class 中,因为在使用 new Inner
的地方,没有它可以使用的默认实例。它在 Example
的 instance 方法中是可选的,但在 static
方法中不是。
public class Outer{
public class Inner{
}
}
public class Main {
public static void main(String[] args) {
Outer objOut = new Outer();
//Outer.Inner object1= objOut.new Inner(); // runes without a problem
//objOut.Inner object2= objOut.new Inner(); //gives error
}
}
这听起来有点业余,但是,Outer.Inner
和 objOut.Inner
之间有什么区别。
两者都不编译。
要使前者编译,应声明一个变量,并给出该变量的名称。
Outer.Inner obj = objOut.new Inner();
即使您执行了这一步,后者也不会编译,因为 objOut.Inner
既不是类型(因为主表达式 objOut
不是类型)也不是有效名称(因为 [= an identifier (jls-3.8) 中不允许使用 14=])。
针对您的情况的简化 rule (jls-14.4) 是
LocalVariableType VariableDeclaratorId [= VariableInitializer];
这个:
Outer.Inner = objOut.new Inner();
将无法编译,但如果将其更改为:
Outer.Inner object = objOut.new Inner();
将意味着创建一个 inner class 的实例,它引用了 Outer
class - objOut
将是 Outer
[=48= 的实例].
还有这个:
objOut.Inner = objOut.new Inner();
将无法编译,因为 objOut
Outer
class 的实例没有属性 Inner
。
而且 Outer
class 知道 Inner
class 的实例 - 它是 Inner
class 知道的实例创建它的 Outer
class 实例。
编辑
行:
objOut.Inner object2= objOut.new Inner();
不会编译,因为 Inner
类型标识符属于 Outer
class 而不是此 class 的实例。
您不能将一个变量名用作另一个变量的 类型 ,这正是您要对 objOut.Inner
所做的。变量的类型是Inner
(或者可选的Outer.Inner
)。
因为 Inner
是一个 inner class,它与其外部 class 的 实例 相关联(它的 包含实例)。当您创建它的实例时,您可以选择¹指定它关联的对象实例,这就是您在 objOut.new Inner
.
这个例子可能有助于使它更清楚一点:
public class Example {
private String str;
public class Inner {
void show() {
// Show the string for the Example this Inner is part of
System.out.println(Example.this.str);
}
}
public Example(String s) {
this.str = s;
}
public static void main(String[] args) {
Example e1 = new Example("e1");
Example e2 = new Example("e2");
Inner i1 = e1.new Inner();
i1.show(); // "e1"
Inner i2 = e2.new Inner();
i2.show(); // "e2"
}
}
注意 i1
Inner
实例如何将 e1
作为其封闭的 Example
实例,因此可以看到 e1
的 str
, 但是 i2
得到 e2
作为它的封闭实例所以它看到 e2
的 str
.
我建议 this Java tutorial 了解更多信息。
¹ 有时它不是可选的,例如在我上面的 Example
class 中,因为在使用 new Inner
的地方,没有它可以使用的默认实例。它在 Example
的 instance 方法中是可选的,但在 static
方法中不是。