我有两个类。
public class Shape1 extends javafx.scene.shape.Path {
public Shape1(PathElement... elements) {
super(elements);
}
}
public class Shape2 extends javafx.scene.shape.Path {
public Shape2(PathElement... elements) {
super(elements);
}
}
它们不一样。它们有不同的字段和方法,但为了简单起见我没有提及它们。
我为每种类型的对象创建两个数组,并且只需要使用一种方法来创建它们。
ArrayList<Shape1> first_shapes = create_array(50, 50, 100, 100, Class.forName("example3.Shape1"));
ArrayList<Shape2> second_shapes = create_array(50, 100, 100, 150, Class.forName("example3.Shape2"));
public static ArrayList create_array(int X1, int Y1, int X2, int Y2, Class my_class) {
var shapes = new ArrayList<>();
shapes.add(my_class.getConstructor(PathElement[].class).newInstance(new MoveTo(X1, Y1), new LineTo(X2, Y2)));
...
return shapes;
}
该代码有两个问题。
类定义不合适,因为更改类名或包名时它将不起作用,必须手动更改。
实际上,它根本不起作用,因为当您向数组添加对象时它会崩溃。
奇怪的是,在上面的表单中它会显示错误。
参数数量错误
但是如果我只使用一个参数,
shapes.add(my_class.getConstructor(PathElement[].class).newInstance(new MoveTo(X1, Y1)));
它将显示错误。
参数类型不匹配
这是解决我的问题的唯一方法。否则我就必须改变整个算法。
请帮忙
谢谢
最佳答案
首先,启用所有编译器警告,并注意它们。你永远不想使用Class
或ArrayList
没有泛型类型;请参阅What is a raw type and why shouldn't we use it? .
关于反射的最佳策略是避免使用反射。
- 反射很慢。它不太可能被即时编译器优化。
- 反射是不安全的。编译器无法检查您是否犯了错误,例如拼写错误或方法签名错误。
- 反射很难阅读。您始终需要能够在以后理解和维护您的代码。在专业领域,其他人可能需要维护您的代码,可能在您离开很久之后。
不要使用反射,而是将每个构造函数视为 function 。具体来说,该函数将 PathElements 序列作为输入,并生成特定类的新实例作为输出。在Java中,写为:
Function<PathElement[], S>
哪里S
本身定义为 <S extends Path>
,即继承自 Path 的已知类型。
您可以将此已知类型和已知构造函数传递给您的方法:
public static <S extends Path> ArrayList<S> create_array(
int X1, int Y1, int X2, int Y2,
Function<PathElement[], S> shapeConstructor) {
var shapes = new ArrayList<S>();
shapes.add(shapeConstructor.apply(new PathElement[] {
new MoveTo(X1, Y1), new LineTo(X2, Y2)
}));
//...
return shapes;
}
现在您拥有的代码既是类型安全的,又能够在编译时捕获任何拼写或语法错误。
此方法的调用如下所示:
ArrayList<Shape1> shapeList1 = create_array(10, 10, 50, 50, Shape1::new);
ArrayList<Shape2> shapeList2 = create_array(20, 20, 80, 80, Shape2::new);
关于java - 使用反射来使用特定的类构造函数并创建新对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58867618/