天天看點

一文讀懂《Effective Java》第53條:接口優先于反射機制

給定一個Class執行個體,我們可以獲得Constructor(構造器)、Method(方法)和Field(域),而這些對象提供了“通過程式來通路類的成員變量、域類型、方法簽名等資訊”的能力。通過調用Constructor、Method、Field執行個體上的方法,可以:構造底層類的執行個體、調用底層類的方法、通路底層類中的域。例如,Method.invoke 使你可以調用任何類的任何對象上的任何方法(遵從正常的安全限制);反射機制甚至能允許一個類使用另一個類,即使目前者被編譯時後者還根本不存在(執行個體化)。

一文讀懂《Effective Java》第53條:接口優先于反射機制
反射機制使用的代價
一文讀懂《Effective Java》第53條:接口優先于反射機制
使用反射機制能力,是要付出一些代價的:

  • 喪失了編譯時類型檢查的好處。(如果程式企圖使用反射通路不存在的或者不可通路的方法,運作時便會失敗抛出異常,除非我們采取特别的預防措施)
  • 執行反射通路所需要的代碼非常笨拙和冗長。(反射代碼塊的可閱讀性是非常低的)
  • 性能損失。(反射方法調用比普通方法調用慢了許多,具體慢了多少,是受到多個因素的影響的,包括虛拟機被配置設定的記憶體/堆棧使用情況/目前CPU使用情況等等,書作者給了一個大概的說法:速度差異可能小到2倍,也可能大到50倍)
一文讀懂《Effective Java》第53條:接口優先于反射機制

反射應用描述

下面舉個例子:建立一個Set<String> 執行個體,它的類是由第一個指令行參數指定的,然後将剩餘參數插入到集合裡面。

public class ReflectClass {              public static void main(String[] args) {              Class<?> c1 = null;              try {              c1 = Class.forName(args[0]);              } catch (ClassNotFoundException e) {              System.err.println("Class not found.");              System.exit(1);              }                  Set<String> s = null;              try {              s = (Set<String>) c1.newInstance();              } catch (InstantiationException e) {              e.printStackTrace();              } catch (IllegalAccessException e) {              e.printStackTrace();              }                  s.addAll(Arrays.asList(args).subList(1, args.length));              System.out.println(s);              }              }               

輸出結果:

[1,2,3,45]           
一文讀懂《Effective Java》第53條:接口優先于反射機制
一文讀懂《Effective Java》第53條:接口優先于反射機制

這個程式像一個“玩偶”,但它示範的這種方法時很強大的:

  • 通用的集合測試器,通過侵入式操作一個或多個集合執行個體,并檢查是否遵守Set 接口的約定
  • 缺點一:反射的使用可能導緻3個運作時錯誤,如果不使用反射方式的執行個體化,那麼這3個錯誤都會成為編譯時錯誤
  • 缺點二:根據類名生成它的執行個體,需要20行冗長的代碼,而調用一個構造器可以非常間接地使用一行代碼。一旦對象被執行個體化,它與其他的Set 執行個體就難以區分。
一文讀懂《Effective Java》第53條:接口優先于反射機制

總結

反射機制是一種功能強大的機制,對于特定的複雜系統程式設計任務,它是非常必要的,但也有一些缺點。如果你編寫的程式必須要與編譯時未知的類一起工作,如有可能,就應該僅僅使用反射機制來執行個體化對象,而通路對象時則使用編譯時已知的某個接口或超類。

一文讀懂《Effective Java》第53條:接口優先于反射機制

—END—

掃描二維碼

擷取技術幹貨

一文讀懂《Effective Java》第53條:接口優先于反射機制

繼續閱讀