2021/04/02

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

Effective Java 3rd 簡體中文版筆記 #65 介面優先於反射機制
核心反射機制 (core reflection facility),package java.lang.reflect 提供訪問任意 class 的能力,給定一 Class 可以拿到 Constructor、Method 和 Field,它們可以對 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