简体   繁体   English

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

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

I am learning inner class . 我正在学习内部课程。 Out of curiosity i extended the inner class which has a parameterized constructor. 出于好奇,我扩展了具有参数化构造函数的内部类。 But when i write super(int i) to call it the code does not compile. 但是当我编写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.
  }
}

As inner classes are part(member) of the outer class and they have to be accessed through the outer class. 内部类是外部类的一部分(成员),因此必须通过外部类进行访问。 How the super constructor of Test class can be called. 如何调用Test类的超级构造函数。

The compile error is: No enclosing instance of type Outer is available due to some intermediate constructor invocation 编译错误为:由于某些中间构造函数调用,没有Outer类型的封闭实例可用

The existing answers do not expound upon the differences among the kinds of member classes. 现有的答案并未详细说明成员类别之间的差异。

A member class is any class that is declared within another class. 成员类是在另一个类中声明的任何类。 They are sometimes called nested classes. 它们有时被称为嵌套类。 Of the kinds of member classes, anonymous inner classes and local classes will not be mentioned here. 在成员类的种类中,这里将不提及匿名内部类和局部类。 The remaining kinds of member classes are inner classes and static member classes. 其余成员类型是内部类和静态成员类。

  • Inner Class . 内部阶层 An inner class instance must be instantiated with the context of an existing outer class instance. 内部类实例必须使用现有外部类实例的上下文实例化。 Inner classes contain an implicit reference to the outer class instance (a fact which can cause inner class instances to lead to memory leaks). 内部类包含对外部类实例的隐式引用(这可能导致内部类实例导致内存泄漏的事实)。 Although uncommon, you can instantiate an inner class instance as follows: 尽管不常见,您可以按以下方式实例化内部类实例:

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

    Because the super() keyword must be the 1st line to execute within a subclass constructor, you would have to declare your constructor like this if it really does need to be in an inner class: 因为super()关键字必须是在子类构造函数中执行的第一行,所以如果确实需要将其构造在内部类中,则必须像这样声明构造函数:

     class Test extends Outer.Inner{ Test(Outer out, int r) { out.super(r); } } 
  • Static Member Class . 静态成员类 A static member class is declared with the modifer static in the class declaration. 在类声明中使用static修饰符声明了静态成员类。 In almost every way that matters, a static member class is a top level class. 在几乎所有重要的方面,静态成员类都是顶级类。 Like top level classes (and unlike inner classes), they do not require any other object instances for instantiation. 像顶级类(和内部类不同)一样,它们不需要任何其他对象实例进行实例化。 Static member class objects are commonly intantiated as: 静态成员类对象通常被实例化为:

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

Whenever possible, you should strongly favor the use of static member classes over inner classes. 只要有可能,就应该强烈建议使用静态成员类,而不是内部类。 Use inner classes only when your member class objects really must have a superclass instance (which should be uncommon). 仅当成员类对象确实必须具有超类实例(应该不常见)时才使用内部类。

You need to state your Inner class to public static 您需要将内部类声明为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.
  }
}

The error actually has nothing to do with that specific line of code, nor with the superclass constructor taking a parameter. 该错误实际上与该特定代码行无关,也不与采用参数的超类构造函数无关。 You can reproduce the error with a simpler example: 您可以使用以下简单示例重现该错误:

class Outer {
    class Inner {
    }       
}

class Test extends Outer.Inner {
}

This gives an error such as: 这给出了如下错误:

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

There are two type of inner classes, non-static (the default) and static (which requires the keyword static ). 内部类有两种类型,非静态(默认)和静态(需要关键字static )。 Static inner classes are just like top-level classes (which are always static), but non-static inner classes require an instance of their enclosing class in order to be instantiated. 静态内部类就像顶级类(它们始终是静态的)一样,但是非静态内部类需要其封闭类的实例才能实例化。 Since Outer.Inner is a non-static inner class, it can only be instantiated "in the context of" an instance of Outer , which means either inside of a instance method of Outer , or via code such as: 由于Outer.Inner是非静态内部类,因此只能在Outer实例的上下文中实例化,这意味着可以在Outer实例方法内部,也可以通过以下代码进行实例化:

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

(This syntax is not commonly encountered.) (这种语法并不常见。)

Since Test is a top-level class, it's static, and so it can't subclass a non-static inner class, because when creating an instance via new Test() , there won't be an instance of Outer provided. 由于Test是顶级类,因此它是静态的,因此它不能对非静态内部类进行子类化,因为通过new Test()创建实例时,不会提供Outer的实例。

Note however that this code compiles without error: 但是请注意,此代码可正确编译:

class Outer {
    class Inner {
    }

    class Test extends Outer.Inner {
    }
}

In this case, Test is also a non-static inner class of Outer , so instances of Test must be created in the context of an instance of Outer , which satisfies the requirements of its superclass. 在这种情况下, Test也是Outer的非静态内部类,因此Test实例必须在Outer的实例的上下文中创建,该实例满足其超类的要求。

Of course, modifying the original code to make Inner static will also allow it to compile. 当然,修改原始代码以使Inner静态也将允许其进行编译。 In real-world code, you create a non-static inner class because you need an instance of that class to have access to the associated instance of the enclosing class. 在真实世界的代码中,您创建了一个非静态内部类,因为您需要该类的实例才能访问该封闭类的关联实例。 In that case, you don't have the option of making it static. 在这种情况下,您无法选择将其设为静态。 But if it doesn't need such access, then you should make your inner class static (or, make it a top-level class instead). 但是,如果不需要此类访问,则应将内部类设为静态(或将其设为顶级类)。

Edit: Apparently it is possible to create a static subclass of a non-static inner class, by explicitly passing an instance of the necessary enclosing class as a constructor parameter to the subclass and invoking super() on it. 编辑:显然,可以通过将必需的封闭类的实例作为构造函数参数显式传递给子类并在其上调用super()来创建非静态内部类的静态子类。 See scottb 's answer here . scottb的答案在这里

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

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