从其子类调用Inner类的构造函数

时间:2015-06-17 00:56:48

标签: java inner-classes

我在学习内心阶级。出于好奇,我扩展了具有参数化构造函数的内部类。但是当我写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类型的实例

3 个答案:

答案 0 :(得分:4)

现有的答案没有说明成员类别之间的差异。

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

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

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

只要有可能,您应该强烈支持在内部类中使用静态成员类。仅当您的成员类对象确实必须具有超类实例(这应该是不常见的)时才使用内部类。

答案 1 :(得分:1)

您需要将您的内部课程陈述为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.
  }
}

答案 2 :(得分:1)

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

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静态也将允许它进行编译。在实际代码中,您创建了一个非静态内部类,因为您需要该类的实例才能访问封闭类的关联实例。在这种情况下,您无法选择将其设置为静态。但是如果它不需要这样的访问,那么你应该让你的内部类静态(或者,使它成为一个顶级类)。

编辑:显然可以通过将必要的封闭类的实例作为构造函数参数显式传递给子类并调用{{}来创建非静态内部类的静态子类。 1}}就可以了。请参阅scottb的回答here