我有以下类:
package org.gradle;
public class Supcl {
public class Inner extends Supsupcl {
public Inner(int a) {
System.out.println(a);
}
}
}
和
package org.gradle;
public class Subcl extends Supcl.Inner {
public Subcl() {
Supcl.Inner.super(34); //error: No enclosing instance of type Supcl is
//available due to some
//intermediate constructor invocation
}
}
和类别Supsupcl
:
package org.gradle;
public class Supsupcl {}
如果我尝试用super(34);
替换Supcl.Inner.super(34);
,则会发生相同的错误。它是怎么做的?
您正在引用嵌套到Supcl
实例的内部类,因此初始化内部类的正确习惯用法是:
new Supcl().new Inner(int i)
(assuming Supcl has a 0-argument constructor or the default constructor)
不能在构造函数之外调用super
,因此必须将其作为Inner(int i)
构造函数代码的第一行来调用。
由于非静态内部类与其外部类有特殊关系,因此您总是需要外部类的实例来创建内部类的实例。
在您的情况下,如果非内部类扩展了内部类,则需要创建外部类的实例或传递它:
public class Subcl extends Supcl.Inner {
public Subcl() {
//assuming there is a no-argument constructor Supcl()
//this only works in one statement so the call to super is still
//part of the first statment in this constructor
new Supcl().super(34); //will call Inner(34)
}
public Subcl( Supcl sup) {
sup.super(34); //will call Inner(34)
}
}
请注意,即使Inner
有一个无参数构造函数,您也必须这样做,因为您需要以某种方式获得Supcl
的实例,而编译器无法推导出这一点。
最后提一句建议(尽管这主要是我的观点):正如你所看到的,内部类的语法并不总是直截了当的,在某些情况下可能很难理解发生了什么,因此我建议只在简单的情况下使用内部类,并且只有当你真的需要它们时才使用。它会让你的生活轻松很多:)
使内部static
public static class InnerClass {
}
并像一样访问它
ParentClass.InnerClass innerClass = new ParentClass.InnerClass(args);
其中args
是您的自定义参数,如果您有任何