2017-02-23 70 views
0

考慮這段代碼:是Java反思不好的做法?

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反射這裏如果結構來避免。選擇框用於讓用戶決定他想要搜索的屬性,現在有6種可能性。我從其他學生那裏得到一些評論,認爲使用反思是'壞習慣'。是這樣嗎?爲什麼?

+5

這是非常糟糕的,因爲這樣會使得你的用戶界面,以你的方法名,這應該是完全無關。稍後做出看似無害的改變會產生意想不到的災難性後果。 – shmosel

+2

使用反射並不是一個壞習慣。 *做這種事*是一種不好的做法。當你想通過ID在幾個相似的對象中選擇一個更好的方法是從字符串到策略對象的映射。 – chrylis

+0

@shmosel這並不一定是他們綁在一起,而是他們被捆綁得如此不透明。 – chrylis

回答

2

這是不好的做法有很多原因。其中:

  1. 它不健壯。用戶在文本字段中鍵入的文本必須與方法的名稱匹配,這意味着應該完全不相關的事物之間存在可怕的級聯。
  2. 反射性能很差。這裏可能不是什麼大不了的事,但如果沒有充分的理由來使用反思,你就不應該這樣做。
  3. 有一個使用lambda表達式的現成更好的解決方案。

請考慮改用填充組合框與Consumer<String>對象:

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

然後你只需要做:

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

    } 
} 
+0

優秀的答案,謝謝! – wimdetr

0

是的,反射速度很慢,並以這種方式使用時會產生脆弱的代碼。

如果你想避免if語句,你應該使用多態。使用public void search(String query)創建一個接口Searcher,爲每個要執行的搜索類型創建實現,然後將每個實現的實例作爲Map<String, Searcher>的值,並以搜索選擇框的值作爲關鍵字。

由於Java枚舉是對象,因此您也可以使用枚舉作爲映射。每個枚舉值將定義它們自己的​​實現。然後你可以調用你想要的實現SearchEnumTypeName.valueOf(searchChoiceBox.getValue()).search(query)