Java反射是一种糟糕的做法吗?

Java反射是一种糟糕的做法吗?,java,javafx,reflection,Java,Javafx,Reflection,考虑这段代码: public void doSearch(ActionEvent event) { String query = searchTextField.getText(); if (query.isEmpty()) { data = FXCollections.observableArrayList(dc.getJobCoachRepo().getList()); usersTableView.setItems(data); }

考虑这段代码:

public void doSearch(ActionEvent event) {
    String query = searchTextField.getText();
    if (query.isEmpty()) {
        data = FXCollections.observableArrayList(dc.getJobCoachRepo().getList());
        usersTableView.setItems(data);
    } else {

        String searchOn = "search" + searchChoiceBox.getValue();
        try {
            Method m = this.getClass().getMethod(searchOn, String.class);
            m.invoke(this, query);
        } catch (Exception e) {

        }
    }
}

public void searchFirstName(String query) {
    data = FXCollections.observableArrayList(dc.getJobCoachRepo().searchFirstName(query));
    usersTableView.setItems(data);

}
...
...

我在这里使用java反射来避免if构造。choicebox用于让用户决定要搜索的属性,现在有6种可能性。我从其他学生那里得到一些评论,认为使用反思是“糟糕的做法”。是这样吗?为什么?

是的,反射很慢,以这种方式使用时会产生脆弱的代码

如果要避免使用If语句,应该使用多态性。使用
public void search(String query)
创建一个界面
Searcher
,为您要执行的每种类型的搜索创建实现,然后将每个实现的一个实例作为
映射的值,由搜索选择框的值键入


因为Java枚举是对象,所以也可以使用枚举作为映射。每个枚举值将定义它们自己的
搜索(字符串)
实现。然后,您可以使用
SearchEnumTypeName.valueOf(searchChoiceBox.getValue()).search(query)

这是一种不好的做法,有很多原因。其中:

  • 它并不健壮。用户在文本字段中键入的文本必须与方法的名称相匹配,这意味着不应该相关的事物之间的耦合达到了可怕的程度
  • 反射性能很差。这里可能没什么大不了的,但是如果没有充分的理由使用反射,你就不应该这样做
  • 使用lambda表达式有一个现成的更好的解决方案
  • 考虑用
    消费者
    对象填充组合框:

    ComboBox<Consumer<String>> searchChoiceBox = new ComboBox<>();
    searchChoiceBox.getItems().add(createSearchOption(this::searchFirstName, "First Name"));
    
    // ...
    
    private Consumer<String> createSearchOption(Consumer<String> search, String name) {
        return new Consumer<String>() {
            @Override
            public void accept(String s) {
                search.accept(s);
            }
            @Override
            public String toString() {
                return name ;
            }
        };
    }
    

    这是非常糟糕的,因为它将UI与方法名绑定在一起,而方法名应该是完全不相关的。以后做出看似无辜的改变可能会带来意想不到的灾难性后果。使用反思并不是一个坏习惯。做这种事是不好的做法。当你想通过ID从几个相似的对象中挑选时,一个更好的方法是从字符串映射到策略对象。@shmosel不一定是因为它们被绑定了,而是因为它们被绑定得非常不透明。当你被要求添加一个选项以不同的(人类)语言运行UI时,我会喜欢你脸上的表情……所以,完全颠覆了这个问题:在哪些情况下,反思是可以接受的、好的甚至是推荐的做法?
    public void doSearch(ActionEvent event) {
        String query = searchTextField.getText();
        if (query.isEmpty()) {
            data = FXCollections.observableArrayList(dc.getJobCoachRepo().getList());
            usersTableView.setItems(data);
        } else {
    
            searchChoiceBox.getValue().accept(query);
    
        }
    }