我需要在运行时使用反射而不是直接访问来获取类的构造函数。对于简单类型,这是微不足道的:
public class MyType {
public MyType(String a, Integer b, Long c) {}
}
Constructor constructor = MyType.class.getConstructor(String.class, Integer.class, Long.class);
但如果班级使用泛型作为其论点的一部分,那么我不清楚应该放什么:
public class MyType {
public MyType(Set<String> a, Integer b, List<Long> c) {}
}
Constructor constructor = MyType.class.getConstructor(Set<String>.class /*Doesn't compile*/, Integer.class, List<Long>.class /*doesn't compile*/);
我可以写一些类似MyType.class.getConstructor(Set.class, Integer.class, List.class);
的内容,但不清楚这会实现我想要的行为。编写这种代码的正确方法是什么?
答案 0 :(得分:1)
通用信息不是getConstructor
方法使用的信息的一部分。您表示的调用(Set.class, ...
)是正确的,因为它类似于运行时可用的信息。
正如Andy Turner所指出的,你只能有一个这种类型的构造函数 - 即使你试图在源代码中为第二个构造函数使用不同的泛型参数。
如果您有点好奇,可以使用javap
查看字节码:
$ javap -private -c MyType
Compiled from "MyType.java"
public class MyType {
public MyType(java.lang.String, java.lang.Integer, java.lang.Long);
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
}
答案 1 :(得分:0)
有一种方法可以使用反射获取所需的构造函数,但在这种情况下看起来更复杂。您必须检查类的所有构造函数及其所有参数。像这样:
public Constructor getConstructor() {
Constructor constructor = null;
Constructor<?>[] constructors = MyType.class.getConstructors();
for(Constructor constructor1 : constructors) {
Type[] types = constructor1.getGenericParameterTypes();
if(types.length == 3) {
if(types[0] instanceof ParameterizedType
&& types[1].equals(Integer.class)
&& types[2] instanceof ParameterizedType) {
ParameterizedType type0 = (ParameterizedType) types[0];
ParameterizedType type2 = (ParameterizedType) types[2];
if(type0.getActualTypeArguments().length == 1
&& type0.getRawType().equals(Set.class)
&& type0.getActualTypeArguments()[0].equals(String.class)
&& type2.getActualTypeArguments().length == 1
&& type2.getRawType().equals(List.class)
&& type2.getActualTypeArguments()[0].equals(Long.class)) {
return constructor;
}
}
}
}
return null;
}
但是,正如Andy Turner在评论中所指出的那样,您无法使用具有相同擦除(Set.class, Integer.class, List.class)
的参数创建另一个构造函数。