java - 使用构造函数参数实例化泛型类型?

标签 java inheritance types

我现在面临一个非常令人困惑的问题。

我正在开发程序库的扩展。在所述库中,有多个类 A、B、C 和 D,它们都继承自同一个父类(super class) Base

现在,我正在为这些类中的每一个做单独的扩展,A1、B1、C1 和 D1,它们都继承自 A、B、C 和 D分别。除此之外,它们都实现了一个自定义接口(interface)I1,我也自己添加了这个接口(interface)。

基类(以及所有子类,包括我的)的构造函数接受一个 E 类型的参数。

为了以简单的方式实例化这些类,我尝试编写一个处理程序类,在需要时创建一个实例。它应该像这样工作:

public class Handler
{
    private Base ctype;
    public Handler(Class<T extends Base implements I1> ctype)
    {
          this.ctype = new ctype.class(E.instance);
    }
}

现在,当然不是那样,但我确信我理解了这个想法。

截至目前,我已经有了我的扩展的一个工作版本,尽管非常草率,因为我没有使用处理程序类,而是手动检查每种类型并实例化适当的对象。由于将来我将不得不修改更多的类,因此我想不惜一切代价避免这种情况,以避免文件困惑。

我知道 ctype.newInstance() 方法,但是由于 Base 类在其构造函数中需要一个参数,恐怕它不会起作用。 (除非我遗漏了什么,在这种情况下请指点我!)

感谢您的帮助!

最佳答案

好吧,你可以使用例如 getConstructor(Class...) 获取不同于默认无参数构造函数的构造函数。

你会有这样的东西:

import java.lang.reflect.*;

public class Handler<B extends Base & I1> {
    private E instanceOfE = ...; // Not sure where you get the E from.
    private Constructor<B> ctor;

    public Handler(Class<B> ctype) {
        if (Modifier.isAbstract(ctype.getModifiers())) {
            throw new IllegalArgumentException(ctype + " is abstract");
        }
        if (!Modifier.isPublic(ctype.getModifiers())) {
            throw new IllegalArgumentException(ctype + " is not public");
        }
        try {
            ctor = ctype.getConstructor(E.class);
        } catch (NoSuchMethodException x) {
            throw new IllegalArgumentException(x);
        }
        Arrays.stream(ctor.getExceptionTypes())
              .filter(x -> !RuntimeException.class.isAssignableFrom(x)
                        && !Error.class.isAssignableFrom(x))
              .findFirst()
              .ifPresent(x -> throw new IllegalArgumentException(ctor + " declares a checked exception");
    }

    private B create() {
        try {
             return ctor.newInstance(instanceOfE);
        } catch (InvocationTargetException x) {
             Throwable cause = x.getCause();
             if (cause instanceof RuntimeException)
                 throw (RuntimeException) cause;
             if (cause instanceof Error)
                 throw (Error) cause;
             // This won't happen because we checked for
             // it in the constructor.
             throw new RuntimeException(cause);
        } catch (IllegalAccessException
               | InstantiationException x) {
             // These also won't happen because we checked
             // for it in the constructor.
             throw new RuntimeException(x);
        }
    }
}

但是,我并不完全相信您需要使用反射。您现在可以使用 lambda 表达式和方法引用来执行此类操作,而且通常效果要好得多。

您不会通过类(class),而是通过某种 Function<E, Base> :

public class Handler<B extends Base & I1> {
    public Handler(Function<E, B> ctorFn) {
        Base b = ctorFn.apply(instanceOfE);
    }
}

然后您使用方法引用创建新的处理程序:

Handler<A1> h = new Handler<>(A1::new);

反射很好,也很强大,但现在它并不总是处理这类事情的最佳方式。

关于java - 使用构造函数参数实例化泛型类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44212335/

相关文章:

c++ - 派生类对象是否包含基类的私有(private)成员?它在内存中是什么样子的?

ruby-on-rails - 通过继承检索的记录上调用ActiveRecord::Relation的未定义方法 `update_attribute'

列的数据类型更改后的 MySQL 警告

types - 什么变量类型用于表示 SSIS 中的 Money

mysql - mysql 中的数据类型文本(Ruby on Rails)

java - 将消息记录到 JUnit 控制台

java - Java 中覆盖成员变量(变量隐藏)

java - 我可以从导入的包中为类创建对象吗

JavaFX - 可重用的 FXML 组件

c# - 继承具有相同命名空间和相同类名的类