Java 使用反射从抽象基类访问构造函数

Java 使用反射从抽象基类访问构造函数,java,reflection,constructor,Java,Reflection,Constructor,我正在玩Java的反射。我有一个带有构造函数的抽象类Base abstract class Base { public Base( String foo ) { // do some magic } } 我还有一些扩展Base的类。它们没有多少逻辑性。我想用Base的构造函数实例化它们,而不必在这些派生类中编写一些代理构造函数。当然,我想用反射实例化这些派生类。说: Class cls = SomeDerivedClass.class; Constructor

我正在玩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

有什么想法吗?我如何用基类的构造函数实例化派生类?或者我必须声明那些哑代理构造函数吗?

问题是基类构造函数是非默认的(有一个参数)。因此,它不能被生成的默认子类构造函数隐式调用。(事实上,你应该得到一个编译警告/错误。)我担心你需要添加显式子类构造函数。

我担心你的子类甚至不会编译,除非你有一个显式构造函数调用其中一个super()构造函数。

一个类不会从它的父类继承构造函数。一个类没有它的父构造函数(尽管它可以调用它们),所以你必须调用这个类拥有的构造函数,而不是一个超类拥有的构造函数


默认构造函数似乎只执行此操作,因为它在默认情况下调用父级的默认构造函数。如果父级没有默认构造函数,则其直接子级也不能。如果不指定将使其成为“非抽象”的所有详细信息,则无法构造抽象类

这意味着在示例中:

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) {
  }
}
将在父类中查找无参数构造函数。如果它找到一个,那么它将被编译成与

public class Child extends Parent {
  public Child(String name) {
    super();
  }
}
如果在
父类
中找不到无参数构造函数,它将无法编译,直到您使用
super(名称)显式指定父类构造构造函数调用

要记住的另一件事是,所有类都是
对象的子类,因此如果不提供
扩展SomeClass
,如下所示:

public class JustMe {
}
编译器会在编译时将您的代码“更正”为:

public class JustMe extends Object {

   public JustMe() {
     super();
   }
}
对象类中有一堆本机(非Java)代码,用于向JVM注册,以确保在对象的生命周期中遵循正确的垃圾收集、内存管理、类型强制等


例如,你无法绕过它,JVM将阻止你构造和抽象类,除非它的所有方法都可以通过匿名类或子类来解析。

在实例化这些类之前,你确定所有的东西都在编译吗?是的,它编译得很好。这是一个简化的示例,它缺少那些catch子句,但基本上这段代码编译得很好。啊,而且
Base
还有一个额外的空默认构造函数(javac坚持这样做)。我没有收到任何警告。可能是因为
Base
和派生类驻留在不同的包中,位于不同的Eclipse项目中
Base(String)
不会在任何子类中被调用。但是我必须为
Base
定义一个空的默认构造函数,这是一个关键的区别。这意味着子类将编译ans实例化,但只调用空的父构造函数。除非子类在其构造函数中显式调用它,否则无法访问其他构造函数。子类化只隐式调用无参数父构造函数(如果存在)。它肯定不会自己传递参数。此外,如果抽象类的构造函数需要一个参数,那么您也应该在创建匿名类时指定它,因此anon示例应该是:new Parent(“foo”){…}@biziclop感谢您的出色观察,为了子孙后代的缘故进行了后期更正