java - 使用反射来使用特定的类构造函数并创建新对象

标签 java class javafx reflection

我有两个类。

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;
}

该代码有两个问题。

  1. 类定义不合适,因为更改类名或包名时它将不起作用,必须手动更改。

  2. 实际上,它根本不起作用,因为当您向数组添加对象时它会崩溃。

奇怪的是,在上面的表单中它会显示错误。

参数数量错误

但是如果我只使用一个参数,

shapes.add(my_class.getConstructor(PathElement[].class).newInstance(new MoveTo(X1, Y1)));

它将显示错误。

参数类型不匹配

这是解决我的问题的唯一方法。否则我就必须改变整个算法。

请帮忙

谢谢

最佳答案

首先,启用所有编译器警告,并注意它们。你永远不想使用ClassArrayList没有泛型类型;请参阅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/

相关文章:

java - 如何通过邮件启动 AWS SWF 工作流程?

java - 获取两个数字之间的位数差

Java Scanner.nextLine() 不等待输入

php - 函数内部定义的常量无法通过类名访问,请参阅代码

JavaFx将文件复制到系统剪贴板并粘贴到操作系统中

java - NoClassDefFoundError 但类存在

c++ - 类对象成员的顺序对性能有影响吗?

r - Rcpp 中如何判断 SEXP 中存储的对象的类?

Javafx显示虚拟键盘

JavaFX - 图像、imageview 和