簡體   English   中英

Java 反射是不好的做法嗎?

[英]Is Java Reflection bad practice?

考慮這段代碼:

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 構造。 選擇框用於讓用戶決定他要搜索的屬性,目前有 6 種可能性。 我從其他學生那里得到了一些評論,認為使用反射是“不好的做法”。 是這樣嗎? 為什么?

造成這種情況的原因有很多。 其中:

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

    }
}

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

如果要避免使用if語句,則應使用多態。 使用public void search(String query)創建一個接口Searcher ,為您想要執行的每種類型的搜索創建實現,然后將每個實現的實例作為Map<String, Searcher>的值,鍵入值搜索選擇框。

因為Java枚舉是對象,所以您也可以使用枚舉作為地圖。 每個枚舉值都將定義自己的search(string)實現。 然后,您可以使用SearchEnumTypeName.valueOf(searchChoiceBox.getValue()).search(query)調用所需的實現SearchEnumTypeName.valueOf(searchChoiceBox.getValue()).search(query)

本機圖像創建

如果你對使用 GraalVM 的Ahead of Time Compilation世界感興趣(這對微服務世界越來越感興趣),我可以告訴你反射是最大的障礙。 在我看來,這是不必要的。

您必須手動(通過反射.json)識別 Java linker 必須保留的類,因為它試圖減少未使用的代碼使二進制文件膨脹。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM