简体   繁体   English

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

[英]Accessing constructor from abstract base class with reflection

I'm playing around with Java's Reflection. 我正在玩Java的Reflection。 I have an abstract class Base with a constructor. 我有一个带有构造函数的抽象类Base

abstract class Base {
    public Base( String foo ) {
        // do some magic
    }
}

I have some further classes extending Base . 我还有一些扩展Base类。 They don't contain much logic. 它们没有太多逻辑。 I want to instantiate them with Base 's constructor, without having to write some proxy contructors in those derived classes. 我想用Base的构造函数实例化它们,而不必在这些派生类中编写一些代理构造函数。 And of course, I want to instantiate those derived classes with Reflection. 当然,我想用Reflection实例化那些派生类。 Say: 说:

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

Any ideas, how I can instantiate a derived class with Base's constructor? 任何想法,我如何用Base的构造函数实例化派生类? Or must I declare those dumb proxy constructors? 或者我必须声明那些愚蠢的代理构造函数?

A class does not inherit constructors from it parent. 类不从父级继承构造函数。 A class does not have it parents constructors (though it can call them) So you have to call the constructors the class has, not a constructor a super class has. 类没有父类构造函数(虽然它可以调用它们)所以你必须调用类所具有的构造函数,而不是超类所具有的构造函数。

The default constructor only appears to do this because it calls the default constructor of the parent by default. 默认构造函数似乎只是这样做,因为它默认调用父项的默认构造函数。 If the parent doesn't have a default constructor, neither can its immediate children. 如果父级没有默认构造函数,则它的直接子级也不能。

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

You cannot construct an abstract class without specifying all of the details that will make it "non-abstract". 如果不指定将使其成为“非抽象”的所有细节,则无法构造抽象类。

That means in the example: 这意味着在示例中:

public abstract class Parent {
  String name;

  public Parent(String name) {
    this.name = name;
  }

  abstract public String getName();

}

no amount of constructor manipulating via reflection will return a Parent-only class. 没有任何构造函数通过反射操作将返回一个Parent-only类。 You can however, return an "anonymous" class by specifying the abstract details at construction time, like so: 但是,您可以通过在构造时指定抽象详细信息来返回“匿名”类,如下所示:

Parent parent = new Parent() {
    public String getName() { return "Bob"; }
  };

Remember, sub-classing also calls the parent constructor, even if you don't put the code in explicitly. 请记住,即使您没有明确地放置代码,子类也会调用父构造函数。 A sub-class written like: 一个写成如下的子类:

public class Child extends Parent {
  public Child(String name) {
  }
}

will look for a no arg constructor in the Parent class. 将在Parent类中查找no arg构造函数。 If it finds one, then it will be compiled into code equivalent to 如果找到一个,那么它将编译成相当于的代码

public class Child extends Parent {
  public Child(String name) {
    super();
  }
}

If it doesn't find a no argument constructor in the Parent class, it will fail to compile until you explicitly specify the parent class construction with the super(name); 如果在Parent类中没有找到无参数构造函数,则在使用super(name);显式指定父类构造之前,它将无法编译super(name); constructor call. 构造函数调用。

Another thing to remember, all classes are subclasses of Object , so if you don't provide an extends SomeClass like so: 另外要记住的是,所有类都是Object子类,所以如果你不提供像这样的extends SomeClass

public class JustMe {
}

The compiler conceputally "corrects" you code at compile time to: 编译器在编译时将代码“纠正”您的代码:

public class JustMe extends Object {

   public JustMe() {
     super();
   }
}

The Object class has a bunch of native (non-Java) code within it to register with the JVM ensuring correct garbage collection, memory management, type enforcement, etc. are followed over the life of the Object. Object类中有一堆本机(非Java)代码,用于向JVM注册,确保在Object的生命周期内遵循正确的垃圾收集,内存管理,类型实施等。

ie. 即。 You can't get around it, the JVM will stop you from constructing and abstract class unless all of it's methods can be resolved via anonymous classes or subclasses. 你不能绕过它,JVM将阻止你构建和抽象类,除非它的所有方法都可以通过匿名类或子类来解决。

The problem is your base class constructor is nondefault (has a parameter). 问题是你的基类构造函数是非默认的(有一个参数)。 Thus it can't be called implicitly by a generated default subclass constructor. 因此,生成的默认子类构造函数无法隐式调用它。 (In fact you should get a compilation warning/error about this.) I am afraid you need to add explicit subclass constructor(s). (实际上你应该得到关于此的编译警告/错误。)我担心你需要添加显式的子类构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM