我正在玩Java的Reflection。我有一个带有构造函数的抽象类Base
。
abstract class Base {
public Base( String foo ) {
// do some magic
}
}
我还有一些扩展Base
的课程。它们没有太多逻辑。我想用Base
的构造函数实例化它们,而不必在这些派生类中编写一些代理构造函数。当然,我想用Reflection实例化那些派生类。说:
Class cls = SomeDerivedClass.class;
Constructor constr;
constr = cls.getConstructor( new Class[] { String.class } ); // will return null
Class clsBase = Base.class;
constr = clsBase.getConstructor( new Class[] { String.class } ); // ok
Base obj = (Base) constr.newInstance( new Object[] { "foo" } ); // will throw InstantiationException because it belongs to an abstract class
任何想法,我如何使用Base的构造函数实例化派生类?或必须我声明那些哑代理构造函数?
答案 0 :(得分:9)
类不从父级继承构造函数。一个类没有它的父构造函数(虽然它可以调用它们)所以你必须调用类所具有的构造函数,而不是超类的构造函数。
默认构造函数似乎只是这样做,因为它默认调用父项的默认构造函数。如果父级没有默认构造函数,则它的直接子级也不能。
答案 1 :(得分:2)
我担心你的子类甚至不会编译,直到你有一个显式构造函数调用其中一个super()构造函数。
答案 2 :(得分:2)
如果不指定将使其成为“非抽象”的所有细节,则无法构造抽象类。
这意味着在示例中:
public abstract class Parent {
String name;
public Parent(String name) {
this.name = name;
}
abstract public String getName();
}
通过反射操作的构造函数的数量不会返回仅父类。但是,您可以通过在构造时指定抽象详细信息来返回“匿名”类,如下所示:
Parent parent = new Parent() {
public String getName() { return "Bob"; }
};
请记住,即使您没有明确地放置代码,子类也会调用父构造函数。一个写成如下的子类:
public class Child extends Parent {
public Child(String name) {
}
}
将在Parent
类中查找no arg构造函数。如果找到一个,那么它将被编译成等同于
public class Child extends Parent {
public Child(String name) {
super();
}
}
如果在Parent
类中没有找到无参数构造函数,则在使用super(name);
构造函数调用显式指定父类构造之前,它将无法编译。
要记住的另一件事是,所有类都是Object
的子类,所以如果你没有这样提供extends SomeClass
:
public class JustMe {
}
编译器会在编译时将您的代码“纠正”到:
public class JustMe extends Object {
public JustMe() {
super();
}
}
Object类中有一堆本机(非Java)代码,用于向JVM注册,确保在Object的生命周期内遵循正确的垃圾收集,内存管理,类型实施等。
即。你不能绕过它,JVM将阻止你构建和抽象类,除非所有的方法都可以通过匿名类或子类来解决。
答案 3 :(得分:1)
问题是你的基类构造函数是非默认的(有一个参数)。因此,生成的默认子类构造函数无法隐式调用它。 (实际上你应该得到关于此的编译警告/错误。)我担心你需要添加显式的子类构造函数。