我现在面临一个非常令人困惑的问题。
我正在开发程序库的扩展。在所述库中,有多个类 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/