我知道要实例化成员内部类,您有两个不同的构造函数:
第一:
Outer out = new Outer();
Outer.Inner in = out.new Inner();
第二:
Outer.Inner in = new Outer().new Inner();
现在,我不知道为什么编译此代码:
public class Outer {
private String greeting="Hi";
protected class Inner {
public int repeat=3;
public void go() {
for (int i =0; i<repeat; i++) {
System.out.println(greeting);
}
}
}
public void callInner() {
Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
in.go();
}
public static void main(String[] args) {
Outer out = new Outer();
out.callInner();
}
}
为什么要编译?
非常感谢!
答案 0 :(得分:6)
在Inner
范围内实例化Outer
时(在实例方法内部),您无需像在示例中那样显式实例化引用Outer
clas,< / p>
Outer.Inner in = new Outer().new Inner();
仅引用Inner
即可实例化:
Inner in = new Inner();
这适用于类中的所有实例方法,只要它们不是静态的。
答案 1 :(得分:2)
第一个主要方法将被调用
public static void main(String[] args){
Outer out = new Outer();
out.callInner();
}
在这里,您已经创建了一个Outer类的对象,并调用了如下的callInner方法
public void callInner() {
Inner in = new Inner(); //in my opinion the correct constructor is Outer.Inner in = new Inner()
in.go();
}
现在您已经创建了一个内部对象,并称为go方法。
protected class Inner {
public int repeat=3;
public void go() {
for (int i =0; i<repeat; i++) {
System.out.println(greeting);
}
}
}
所以这是一个简单的调用,所有调用都在同一范围内。因此需要调用external.Inner概念。
重要的是要了解外部和内部之间的关系。更具体地说,您需要一个Outer实例才能创建一个Inner实例。
答案 2 :(得分:2)
如您的解释所示,您需要一个Outer
的实例才能创建一个Inner
的实例。由于方法callInner
是Outer
的实例方法(未声明为static
),因此已经存在Outer
的实例:this
代码也可以这样写:
public void callInner() {
Outer out = this;
Inner in = out.new Inner();
in.go();
}
现在代码看起来与您的第一个示例类似。
但是让我们保留如下所示的代码:
public void callInner() {
Inner in = new Inner();
in.go();
}
现在,如果我们在幕后看,基本上是一样的:
public void callInner();
Code:
0: new #21 // class playground/Outer$Inner
3: dup
4: aload_0
5: invokespecial #23 // Method playground/Outer$Inner."<init>":(Lplayground/Outer;)V
8: astore_1
9: aload_1
10: invokevirtual #26 // Method playground/Outer$Inner.go:()V
13: return
在第4行,我们得到loads in instance methods this
中的aload_0
。
答案 3 :(得分:1)
当您调用callInner
方法时,您实际上在Outer
类的范围之内。而且,编译器接受调用new Inner()
的原因是完全相同的,为什么不必显式地编写您想象中的静态变量来自哪个类(当它是您调用的同一类的一部分时) 。请参见下面的示例:
public class Outer {
private static int x = 1;
private void innerCall() {
x++;
}
}
在上述情况下,您使用示例而不是使用变量而不是与示例中的示例完全相同(在此处实际上无关紧要)。如果要从类(范围)的外部访问类/变量,则必须使用语法。然后看起来像下面的东西:
public class Outer {
public static int x = 1;
}
Outer.x++;
上面,您必须明确指定要从哪个范围访问变量x
的范围。就像您要从给定目录中访问文件一样。如果您在此目录中,则只需按文件名访问文件即可。但是,当您不在目录中时,还必须输入目录名称才能查看要获取的文件。