我希望能够从继承到子类的静态方法中获取N个新实例的List / ArrayList,这样我就不必在所有子类中都重写同一函数。
我想实现这一点,以便构建包含A和B的向量。我尝试了几种方法,但没有一种对我有用:
public class Parent {
public static List<Parent> getNInstances(int n) {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Parent newChildInstance = (Parent) MethodHandles
.lookup()
.lookupClass()
.getConstructor()
.newInstance()
out.add(newChildInstance);
}
}
}
我从here获得了MethodHandles的东西,因为我觉得我需要让该类能够调用.getConstructor().newInstance()
,这在理论上应该可以解决我的问题。但是,这是行不通的,它给了我一个NoSuchMethodException,因为他不能从给定的Class中找到构造函数。
MethodHandles.lookup().lookupClass()
,至少我认为这就是原因。
这就是我希望方法.getNInstances()
工作的方式。
public class Parent {
public Parent(){ }
public static List<Parent> getNInstances(int n) {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Parent newChildInstance = ...
out.add(newChildInstance);
}
}
}
public class A extends Parent {
public A(){ }
}
public class B extends Parent {
public B(){ }
}
public class Main {
public static void main(String[] args) {
List<Parent> total = new ArrayList<>();
total.addAll(A.getNInstances(3));
total.addAll(B.getNInstances(4));
}
}
因此,总数应类似于[a,a,a,b,b,b,b],其中a是A的实例,b是B的实例,但是到目前为止,它只是空的。
答案 0 :(得分:2)
这里根本不需要使用反射。为构造函数使用工厂和方法引用。
这样,您可以在编译时确保要使用的构造函数确实存在。
abstract class ParentFactory
{
public List<Parent> getNInstances(int n)
{
final List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++)
{
out.add(constructor().get());
}
return out;
}
protected abstract Supplier<Parent> constructor();
}
class AFactory extends ParentFactory
{
@Override
protected Supplier<Parent> constructor() {
return A::new;
}
}
class BFactory extends ParentFactory
{
@Override
protected Supplier<Parent> constructor() {
return B::new;
}
}
样品用量:
List<Parent> total = new ArrayList<>();
total.addAll(new AFactory().getNInstances(3));
total.addAll(new BFactory().getNInstances(4));
答案 1 :(得分:0)
我无法重现您的错误。 但请注意以下几点:
1)在这里,您将永远不会查找子类的类,因为lookupClass()
返回调用该方法的类,而该类始终是Parent.getNInstances()
:
Parent newChildInstance = (Parent) MethodHandles
.lookup()
.lookupClass()
.getConstructor()
.newInstance();
将其设为实例方法将产生相同的结果。
2)通用类应该足以解决您的问题并将其作为实例方法。
public class Parent<T extends Parent> {
public List<Parent> getNInstances(int n) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Class<T> clazz = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
Parent newChildInstance =
clazz.getConstructor().newInstance();
out.add(newChildInstance);
}
return out;
}
}
和子类:
public class A extends Parent<A> {
//...
}
public class B extends Parent<B> {
//...
}
样本测试:
List<Parent> total = new ArrayList<>();
total.addAll(new A().getNInstances(3));
total.addAll(new B().getNInstances(4));
System.out.println(total);
输出:
[A @ 506e6d5e,A @ 96532d6,A @ 3796751b,B @ 67b64c45,B @ 4411d970, B @ 6442b0a6,B @ 60f82f98]