2021/04/02

[筆記] Effective Java #65 介面優先於反射機制

Effective Java 3rd 簡體中文版筆記 #65 介面優先於反射機制
核心反射機制 (core reflection facility),package java.lang.reflect 提供訪問任意 class 的能力,給定一 Class 可以拿到 ConstructorMethodField,它們可以對 class 進行調用,像是 Method.invoke 就可以讓你調用該 class 的方法。

反射機制雖然方便,但也要付出一點代價,像是
  1. 損失編譯時類型檢查的優勢,像是某變數為 String 誤用為 Integer,這種錯誤一般在編譯時就會發生錯誤,但使用反射機制,就變成在執行時才會發生例外。
  2. 執行反射訪問所需要的程式碼不易閱讀且冗長。
  3. 效能損失,使用反射機制調用比普通方法慢許多。
有一些複雜的應用程式會需要使用反射機制,像是程式碼分析工具和依賴注入 (dependency injection),如果只在有限的形式下使用反射機制,雖付出少許代價,但能獲得許多好處。
以下程式碼中 args[0]java.util.HashMap 或是 java.util.TreeSet,它的輸出結果就會不一樣。這類的程式碼可以使用在服務提供者框架 (service provider framework),同時也顯示出兩個缺點,第一為產生非常多的例外要處理,若不使用反射機制,上述的錯誤都會在編譯時發生錯誤。第二就是冗長的程式碼,一般調用 constructor 只需要一行,但是透過反射機制的程式碼相當冗長。
public static void main(String[] args) {
    // Translate the class name into a Class object
    Class<? extends Set<String>> cl = null;
    try {
        cl = (Class<? extends Set<String>>) // Unchecked cast!
        Class.forName(args[0]);
    } catch (ClassNotFoundException e) {
        fatalError("Class not found.");
    }
    // Get the constructor
    Constructor<? extends Set<String>> cons = null;
    try {
        cons = cl.getDeclaredConstructor();
    } catch (NoSuchMethodException e) {
        fatalError("No parameterless constructor");
    }
    // Instantiate the set
    Set<String> s = null;
    try {
        s = cons.newInstance();
    } catch (IllegalAccessException e) {
        fatalError("Constructor not accessible");
    } catch (InstantiationException e) {
        fatalError("Class not instantiable.");
    } catch (InvocationTargetException e) {
        fatalError("Constructor threw " + e.getCause());
    } catch (ClassCastException e) {
        fatalError("Class doesn't implement Set");
    }
    // Exercise the set
    s.addAll(Arrays.asList(args).subList(1, args.length));
    System.out.println(s);
}
private static void fatalError(String msg) {
    System.err.println(msg);
    System.exit(1);
}
反射機制為一強大的功能,固有其存在的價值,但是缺點就是使用者變成與一個未知的 class 作溝通,盡量只使用反射機制來生成實體,並由其介面或 super class 來使用它。

轉載請註明原文網址 https://cookieandcoketw.blogspot.com/2021/03/effective-java-65-interface-reflection.html

沒有留言:

張貼留言