java反射工具類--通過指定屬性名,獲取/設定物件屬性值
阿新 • • 發佈:2018-12-30
java物件通過點運算子操作物件屬性的方式沒法使用for,while等迴圈,此工具主要解決這一問題.
例如:有一物件包含屬性有一定規律
obj1: { name1: "張三", age1: 1, name2: "李四", age2: 2, .... }
要將此物件拆為多個小物件
objList:[ { name: "張三", age: 1 }, { name: "李四", age: 2 } ]
為了應對這種不能使用迴圈獲取屬性的情況,編寫了此工具類
核心實現程式碼如下:
/** * @param o * 操作物件 * @param methodName * 方法名 * @param attName * 屬性名 * @param value * 值 * @return get方法返回實際值 set方法返回操作後物件 */ private static Object Operation(Object o, String methodName, String attName, Class<?> paramType, Object value) { // 方法賦值出錯標誌 boolean opErr = false; Object res = null; Class<?> type = o.getClass(); try { Method method = null; if (methodName.indexOf("get") != -1) { // get方法 // 獲取方法 method = type.getMethod(methodName); // 執行 res = method.invoke(o); } else { // set方法 // 當沒有傳入引數型別時通過value獲取引數型別 paramType = paramType == null ? value.getClass() : paramType; // 獲取方法 method = type.getMethod(methodName, paramType); // 執行 method.invoke(o, value); res = o; } } catch (Exception e) { // 通過get/set方法操作屬性失敗 opErr = true; if (SHOW_LOG) { System.err.println(getThisName() + ": [WARN] 直接對屬性'" + attName + "進行操作(不借助get/set方法)."); } } if (opErr) { // 通過打破封裝方式直接對值進行操作 try { Field field = null; // 獲取屬性 field = type.getDeclaredField(attName); // 打破封裝 field.setAccessible(true); if (methodName.indexOf("get") != -1) { // get方法 // 獲取屬性值 res = field.get(o); } else { // set方法 // 設定屬性值 field.set(o, value); res = o; } } catch (Exception e) { //兩種方法都操作失敗 if (SHOW_LOG) { System.err.println(getThisName() + ": [ERROR] 屬性'" + attName + "'操作失敗."); } } } return res; }
set方法如下:
/** * 設定屬性值 * * @param o * 操作物件 * @param attName * 屬性名 * @param value * 引數值 * @param paramType * 引數型別 * @return 操作後物件 */ @SuppressWarnings("unchecked") public static <T> T set(T o, String attName, Object value, Class<?> paramType) { if (o == null || attName == null || attName.isEmpty()) { return null; } String methodName = attNameHandle("set", attName); return (T) Operation(o, methodName, attName, paramType, value); }
get方法如下:
/** * 獲取屬性值 * * @param o * 操作物件 * @param attName * 屬性名 * @param returnType * 返回值型別 * @return */ @SuppressWarnings("unchecked") public static <T> T get(Object o, String attName, Class<T> returnType) { if (o == null || attName == null || attName.isEmpty()) { return null; } String methodName = attNameHandle("get", attName); return (T) Operation(o, methodName, attName, null, null); }
通過屬性名獲取get/set方法名:
/** * 屬性名處理 * * @param method * 方法(get/set) * @param attName * @return */ private static String attNameHandle(String method, String attName) { StringBuffer res = new StringBuffer(method); // 屬性只有一個字母 if (attName.length() == 1) { res.append(attName.toUpperCase()); } else { // 屬性包含兩個字母及以上 char[] charArray = attName.toCharArray(); // 當前兩個字元為小寫時,將首字母轉換為大寫 if (Character.isLowerCase(charArray[0]) && Character.isLowerCase(charArray[1])) { res.append(Character.toUpperCase(charArray[0])); res.append(attName.substring(1)); } else { res.append(attName); } } return res.toString(); }
完整程式碼:https://github.com/GFuZan/reflexTools
如果你現在在JAVA這條路上掙扎,也想在IT行業拿高薪,可以參加我們的訓練營課程,選擇最適合自己的課程學習,技術大牛親授,7個月後,進入名企拿高薪。我們的課程內容有:Java工程化、高效能及分散式、高效能、深入淺出。高架構。效能調優、Spring,MyBatis,Netty原始碼分析和大資料等多個知識點。如果你想拿高薪的,想學習的,想就業前景好的,想跟別人競爭能取得優勢的,想進阿里面試但擔心面試不過的,你都可以來,q群號為:856443934