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
