我有一个界面
public interface IDrawing
接下来我有一个实现此接口的类:
public class Line implements IDrawing
现在我有一个带有构造函数的类,它接受上面的参数:
public LineChanger(Line line)
没有问题。
当我使用反射调用上面的构造函数时,它会抛出NoSuchMethodException
//drawing variable is of class Line implementing IDrawing
.getDeclaredConstructor(IDrawing.class).newInstance(drawing);
当我将构造函数更改为:
时,异常消失了public LineChanger(IDrawing line)
是否可以在不更改构造函数的情况下使反射工作?
我希望保持构造函数的严格性(即在这种情况下只接受一个特定的类Line
),但保持反射适用于我的工厂。
答案 0 :(得分:2)
public LineChanger(Line line)
当我使用反射调用上面的构造函数时,它会抛出
NoSuchMethodException
只有你弄错了。
//drawing variable is of class Line implementing IDrawing
.getDeclaredConstructor(IDrawing.class).newInstance(drawing);
你弄错了。参数的类型为Line.class
,而不是IDrawing.class
。
当我将构造函数更改为:
时,异常消失了
public LineChanger(IDrawing line)
当然可以。当您这样做时,您的Java代码和反射代码都是一致的。如果他们没有,它就无法工作,可以吗?
是否可以在不更改构造函数的情况下使反射工作?
是的,请致电.getDeclaredConstructor(Line.class).newInstance(drawing);
,前提是drawing
是Line
的实例。
你似乎在期待奇迹。
答案 1 :(得分:1)
当您调用getConstructor
时,API会找到具有该签名的构造函数,因此如果没有构造函数采用IDrawing
参数,则代码会抛出异常。
无论如何,API的行为都没有意义。您无法将类型为IDrawing
的对象传递给Line
类型的参数,因为您传递的对象可以是IDrawing
的任何实现。
但是,反过来是可行的,您可以将Line
类型的对象传递给采用IDrawing
的构造函数。这是一个方法,它查找可以传递给定类型集的所有构造函数。
public static List<Constructor<?>> getCompatibleConstructors(Class<?> clazz, Class<?>... parameterTypes) {
Constructor<?>[] ctrs = clazz.getConstructors();
ArrayList<Constructor<?>> list = new ArrayList<>();
outer: for (Constructor<?> ctr : ctrs) {
if (ctr.getParameterCount() == parameterTypes.length) {
for (int i = 0 ; i < parameterTypes.length ; i++) {
if (!ctr.getParameterTypes()[i].isAssignableFrom(parameterTypes[i])) {
continue outer;
}
}
list.add(ctr);
}
}
return list;
}
它可以找到这个构造函数:
public MyClass(IDrawing drawing) {}
如果您传递这些参数:
getCompatibleConstructors(MyClass.class, Line.class);
答案 2 :(得分:1)
如果遍历所有构造函数并找到只有一个可从IDrawing
分配的参数的构造函数,就有可能按照您想要的方式进行构建。
Constructor ctor = Arrays.stream(LineChanger.class.getConstructors())
.filter(c -> c.getParameterCount() == 1)
.filter(c -> c.getParameterTypes()[0].isAssignableFrom(IDrawing.class))
.findFirst()
.orElse(LineChanger.class.getConstructors()[0]);