使用反射从抽象基类访问构造函数
Posted
技术标签:
【中文标题】使用反射从抽象基类访问构造函数【英文标题】:Accessing constructor from abstract base class with reflection 【发布时间】:2011-01-13 16:46:31 【问题描述】:我正在玩 Java 的反射。我有一个带有构造函数的抽象类Base
。
abstract class Base
public Base( String foo )
// do some magic
我还有一些扩展Base
的课程。它们不包含太多逻辑。我想用Base
的构造函数来实例化它们,而不必在这些派生类中编写一些代理构造函数。当然,我想用反射实例化那些派生类。说:
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 的构造函数实例化派生类?或者必须我声明那些愚蠢的代理构造函数?
【问题讨论】:
在实例化这些类之前,你确定一切都在编译吗? 是的,它编译得很好。这是一个简化的示例,它缺少那些 catch 子句,但基本上这段代码编译得很好。啊,Base
有一个额外的空默认构造函数(javac 坚持这样做)。
【参考方案1】:
一个类不会从它的父类继承构造函数。一个类没有它的父构造函数(尽管它可以调用它们)所以你必须调用类的构造函数,而不是超类的构造函数。
默认构造函数似乎只执行此操作,因为它默认调用父级的默认构造函数。如果父级没有默认构造函数,则其直接子级也没有。
【讨论】:
【参考方案2】:恐怕你的子类甚至不会编译,除非你有一个显式的构造函数调用 super() 构造函数之一。
【讨论】:
一切编译正常。Base(String)
不会在任何子类中被调用。但是我必须为Base
定义一次空的默认构造函数。
这是一个至关重要的区别。这意味着您的子类将编译和实例化,但只会调用空的父构造函数。除非子类在其构造函数中显式调用它,否则您无法访问其他构造函数。【参考方案3】:
如果不指定使其“非抽象”的所有细节,您就无法构造抽象类。
例子中的意思是:
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
类中查找无参数构造函数。如果找到,则将其编译为等价于
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会阻止你构造和抽象类,除非它的所有方法都可以通过匿名类或子类解决。
【讨论】:
子类化除了无参数的父构造函数(如果存在的话)不会隐式调用任何东西。它绝对不会自行传递参数。此外,如果抽象类的构造函数需要参数,您也应该在创建匿名类时指定它,因此匿名示例应为: new Parent( "foo" ) ... @biziclop 感谢您的出色观察,为子孙后代而更正【参考方案4】:问题是你的基类构造函数是非默认的(有一个参数)。因此它不能被生成的默认子类构造函数隐式调用。 (事实上你应该得到一个关于这个的编译警告/错误。)恐怕你需要添加显式的子类构造函数。
【讨论】:
我没有收到任何警告。可能是因为Base
和派生类位于不同的包中,位于不同的 Eclipse 项目中。以上是关于使用反射从抽象基类访问构造函数的主要内容,如果未能解决你的问题,请参考以下文章