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

时间:2011-01-13 16:46:32

标签: java reflection constructor

我正在玩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的构造函数实例化派生类?或必须我声明那些哑代理构造函数?

4 个答案:

答案 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)

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