Java這種以囉嗦著稱的編程語言,反射代碼也很囉嗦。每次看到不少人使用原生的反射接口,我內心都在想,愚蠢的人類啊,爲何不封裝一下再用。java
不能靜態決定,好比根據URL參數的字符串調用相應方法的時候。git
避免樣板代碼的時候,例如能夠用反射代替,繁瑣的JSON對象解析代碼。github
避免顯式依賴的時候,有時候能用來打破項目之間的循環依賴關係。但要慎用,若是之間接口比較複雜,仍是建議單獨使用協議接口的方法。編程
訪問私有成員,作一些黑科技的事情的時候。編程語言
封裝前的反射調用方法:code
try { Class<?> class = obj.getClass(); Method method = class.getDeclaredMethod("foo", new Class[] { String.class }); method.invoke(obj, new Object[] {"hi"}); } catch (Exceptione ex) { }
非反射直接調用:對象
obj.foo("hi");
封裝後的反射調用:繼承
Reflection.callMethod(obj, "foo", "hi");
封裝前的反射調用方法:接口
try { Class<?> class = obj.getClass(); Field field = class.getDeclaredField("bar"); field.setAccessible(true); Object old = field.get(obj); field.set(obj, "hi"); return old; } catch (Exceptione ex) { }
非反射直接字段賦值:字符串
obj.bar = "hi";
封裝後字段賦值:
Reflection.setField(obj, "bar", "hi");
Talk is cheap, show me the code.
這裏是我簡單的反射封裝代碼,不是很完整,只是解決了目前本身的需求。源碼也就100行,本身看吧。
在Class類接口中,getDeclaredMethod getDeclaredField和getMethod getField的區別。帶Declared的包含本類的私有和公開成員,不包含繼承的成員。不帶Declare不含繼承的和自身的公開成員,不包含私有成員。若是要訪問全體的成員,包括全部繼承的和私有的,那麼代碼只會更加複雜。幸運的是Reflection類的封裝已經幫你實現了。