【问题标题】:Way to call inner class by outer class外部类调用内部类的方法
【发布时间】:2019-04-16 03:51:00
【问题描述】:

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

第一:

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

    }
}

为什么会编译?

非常感谢!

【问题讨论】:

    标签: java constructor inner-classes


    【解决方案1】:

    正如您的解释所示,您需要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 行,我们得到 aload_0loads in instance methods this


    比较:Java Tutorials - Inner Class Example

    【讨论】:

      【解决方案2】:

      当您调用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。就像您想从给定目录中访问文件一样。如果您在此目录中,则只需按文件名访问该文件。但是,当您在它之外时,您还必须写入目录的名称才能看到您想要获取的文件。

      【讨论】:

        【解决方案3】:

        将调用第一个 main 方法

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

        现在你已经创建了一个 Inner 对象并调用了 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 实例。

        【讨论】:

          【解决方案4】:

          当您在 Outer 范围内(在实例方法内)实例化 Inner 时,您不需要显式实例化引用 Outer 类,就像在您的示例中一样:

          Outer.Inner in = new Outer().new Inner();
          

          只引用Inner就可以实例化:

           Inner in = new Inner();
          

          这适用于类中的所有实例方法,只要它们不是静态的。

          【讨论】:

          • 基本上相当于Inner in = new this.Inner();
          • @biziclop 你的意思可能是Inner in = this.new Inner();
          猜你喜欢
          • 2023-03-23
          • 1970-01-01
          • 1970-01-01
          • 2013-05-31
          • 2014-08-28
          • 2012-02-21
          • 2011-07-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多