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