我有下面的方法,可以帮助我创建一个类的实例,其构造函数接受一个参数。问题是我正在尝试创建一个类的实例,其构造函数将接口作为参数。当我调用下面的方法时,arg.getClass解析为派生类而不是接口,因此c.getConstructor失败并返回NoSuchMethodException。是否可以使用反射来创建以接口作为参数的对象实例?
public static <T> T getInstance(String className, Object arg)
{
Class<?> c = Class.forName(className);
Constructor<?> ctor = c.getConstructor(arg.getClass());
return (T)ctor.newInstance(arg);
}
答案 0 :(得分:1)
Apache Commons Lang提供了ConstructorUtils
类,它具有getMatchingAccessibleConstructor(Class, Class[])
方法,用于查找具有匹配类类型参数的可访问构造函数
示例:
public class Examples extends Object {
public static void main(String[] args) throws Exception {
Class<?> clazz = Examples.class;
Constructor<?> cons = ConstructorUtils.getMatchingAccessibleConstructor(clazz, new Class[]{B.class});
System.out.println(cons);
}
public Examples (A a) {}
interface A {}
static class B implements A {}
}
打印
public test.Examples(test.Examples$A)
您可以查看源代码并进行修改,以便找到所有构造函数,无论是否可访问。
答案 1 :(得分:0)
你可以尝试这样做,它会完成工作,但我不确定它是多么“干净”:
public static <T> T getInstance(String className, Object arg) {
Class<?> c = Class.forName(className);
Class<?>[] interfaces = arg.getClass().getInterfaces();
Constructor<?> ctor = null;
for (int i = 0; i < interfaces.length && ctor == null; i++) {
try {
ctor = c.getConstructor(interfaces[i]);
} catch (NoSuchMethodException e) { }
}
if (ctor != null) {
return (T)ctor.newInstance(arg);
} else {
return null;
}
}
答案 2 :(得分:0)
您的arg
不能是接口,它只能是实现它的对象。因此,对arg.getClass()
的调用将返回arg
对象的类,而不是在调用Class.getConstructor(Class... parameterTypes)
时用于匹配构造函数的接口。
鉴于此,你需要编写一个函数,在这些行中进行更宽松的匹配:
for (Constructor constructor : Class.forName(className).getDeclaredConstructors())
{
if (constructor.getParameterTypes().length == 1 && constructor.getParameterTypes()[0].isAssignableFrom(arg.getClass())
{
return (T)constructor.newInstance(arg);
}
}