外层阶级呼唤内层阶级的方式

时间:2018-11-13 10:25:49

标签: java constructor inner-classes

我知道要实例化成员内部类,您有两个不同的构造函数:

第一:

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();

    }
}

为什么要编译?

非常感谢!

4 个答案:

答案 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的实例。由于方法callInnerOuter的实例方法(未声明为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


比较:Java Tutorials - Inner Class Example

答案 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的范围。就像您要从给定目录中访问文件一样。如果您在此目录中,则只需按文件名访问文件即可。但是,当您不在目录中时,还必须输入目录名称才能查看要获取的文件。

相关问题