繁体   English   中英

从其子类调用内部类的构造函数

[英]Invoking constructor of a Inner class from its subclass

我正在学习内部课程。 出于好奇,我扩展了具有参数化构造函数的内部类。 但是当我编写super(int i)来调用它时,代码无法编译。

class Outer{
  class Inner{
    private int a;
    Inner(int i){
     this.a=i;
    }

    public void inheritFromInner(){
      System.out.println("Inherited from inner");
    }
  }       
}

class Test extends Outer.Inner{
  Test(int r){
   super(r);// This line does not compile.
  }
}

内部类是外部类的一部分(成员),因此必须通过外部类进行访问。 如何调用Test类的超级构造函数。

编译错误为:由于某些中间构造函数调用,没有Outer类型的封闭实例可用

现有的答案并未详细说明成员类别之间的差异。

成员类是在另一个类中声明的任何类。 它们有时被称为嵌套类。 在成员类的种类中,这里将不提及匿名内部类和局部类。 其余成员类型是内部类和静态成员类。

  • 内部阶层 内部类实例必须使用现有外部类实例的上下文实例化。 内部类包含对外部类实例的隐式引用(这可能导致内部类实例导致内存泄漏的事实)。 尽管不常见,您可以按以下方式实例化内部类实例:

     Outer out = new Outer(); Outer.Inner inner = out.new Inner(); 

    因为super()关键字必须是在子类构造函数中执行的第一行,所以如果确实需要将其构造在内部类中,则必须像这样声明构造函数:

     class Test extends Outer.Inner{ Test(Outer out, int r) { out.super(r); } } 
  • 静态成员类 在类声明中使用static修饰符声明了静态成员类。 在几乎所有重要的方面,静态成员类都是顶级类。 像顶级类(和内部类不同)一样,它们不需要任何其他对象实例进行实例化。 静态成员类对象通常被实例化为:

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

只要有可能,就应该强烈建议使用静态成员类,而不是内部类。 仅当成员类对象确实必须具有超类实例(应该不常见)时才使用内部类。

您需要将内部类声明为public static

class Outer{
  public static class Inner{
    private int a;
    Inner(int i){
     this.a=i;
    }

    public void inheritFromInner(){
      System.out.println("Inherited from inner");
    }
  }       
}

class Test extends Outer.Inner{
  Test(int r){
   super(r);// This line does not compile.
  }
}

该错误实际上与该特定代码行无关,也不与采用参数的超类构造函数无关。 您可以使用以下简单示例重现该错误:

class Outer {
    class Inner {
    }       
}

class Test extends Outer.Inner {
}

这给出了如下错误:

Outer.java:6: error: an enclosing instance that contains Outer.Inner is required
class Test extends Outer.Inner {
^
1 error

内部类有两种类型,非静态(默认)和静态(需要关键字static )。 静态内部类就像顶级类(它们始终是静态的)一样,但是非静态内部类需要其封闭类的实例才能实例化。 由于Outer.Inner是非静态内部类,因此只能在Outer实例的上下文中实例化,这意味着可以在Outer实例方法内部,也可以通过以下代码进行实例化:

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

(这种语法并不常见。)

由于Test是顶级类,因此它是静态的,因此它不能对非静态内部类进行子类化,因为通过new Test()创建实例时,不会提供Outer的实例。

但是请注意,此代码可正确编译:

class Outer {
    class Inner {
    }

    class Test extends Outer.Inner {
    }
}

在这种情况下, Test也是Outer的非静态内部类,因此Test实例必须在Outer的实例的上下文中创建,该实例满足其超类的要求。

当然,修改原始代码以使Inner静态也将允许其进行编译。 在真实世界的代码中,您创建了一个非静态内部类,因为您需要该类的实例才能访问该封闭类的关联实例。 在这种情况下,您无法选择将其设为静态。 但是,如果不需要此类访问,则应将内部类设为静态(或将其设为顶级类)。

编辑:显然,可以通过将必需的封闭类的实例作为构造函数参数显式传递给子类并在其上调用super()来创建非静态内部类的静态子类。 scottb的答案在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM