2017-02-23 9 views
0

は、コードのこの部分を考えてみましょう:Java Reflectionは悪い練習ですか?

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

} 
... 
... 

私は、if構文を避けるためにここにJavaのリフレクションを使用しています。 choiceboxは、ユーザーが検索したい属性を決定させるために使用されます。現在、6つの可能性があります。私は、リフレクションを使うことが「悪い習慣」であるという、他の学生からのコメントを受けました。これは本当ですか?どうして?

+5

それは非常に悪いです完全に無関係です。後で一見無邪気な変化を起こすと予期せぬ悲惨な結果を招くことがあります。 – shmosel

+2

リフレクションの使用は悪いことではありません。 *この種のことは悪いことです。同様のIDを使っていくつかの類似したオブジェクトの中から選択したいときは、文字列から戦略オブジェクトへのマップです。 – chrylis

+0

@shmosel必ずしも彼らが結ばれているわけではありませんが、彼らはあまりにも不透明に結ばれています。 – chrylis

答えて

2

これは悪い習慣である多くの理由があります。中でも:

  1. 堅牢ではありません。ユーザーがテキストフィールドに入力するテキストは、メソッドの名前と一致する必要があります。関連性のないもの同士の混乱の恐れがあります。
  2. 反射がひどく実行されます。多分ここでは大したことではないかもしれませんが、リフレクションを使用する正当な理由がなければ、そうしてはいけません。
  3. ラムダ式を使用する既製の優れたソリューションがあります。

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

次に、あなただけの操作を行います。それはあるべきあなたのメソッド名のために、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); 

    } 
} 
+0

優秀な回答、ありがとうございます! – wimdetr

0

はい、反射が遅く、このように使用すると脆弱なコードが作成されます。

if文を避けたい場合は、多型を使用する必要があります。インターフェイスSearcherpublic void search(String query)で作成し、実行する検索の種類ごとに実装を作成し、各実装のインスタンスをMap<String, Searcher>の値に置き、検索選択ボックスの値をキーにします。

Javaのenumはオブジェクトなので、enumをマップとして使用することもできます。それぞれのenum値は独自の​​実装を定義します。 SearchEnumTypeName.valueOf(searchChoiceBox.getValue()).search(query)

関連する問題