更多關(guān)于Java方面的文章,歡迎訪(fǎng)問(wèn)燕歸來(lái)https://www.zhoutao123.com
前不久有個(gè)需求,實(shí)現(xiàn)對(duì)象轉(zhuǎn)換為map,這里思考了一些,沒(méi)有用別人的輪子,自己實(shí)現(xiàn)了這個(gè)需求,寫(xiě)了一個(gè)簡(jiǎn)單的工具類(lèi)來(lái)做這個(gè)。
分析問(wèn)題
問(wèn)題主要有以下幾點(diǎn)
- 如何獲取對(duì)象中的屬性的名稱(chēng)?
- 如何獲取對(duì)象的屬性值?如何這個(gè)屬性被private修飾,該如何處理?
- 返回的是一個(gè)對(duì)象該如何獲取對(duì)象的屬性參數(shù)呢?
解決問(wèn)題
- 問(wèn)題1:可以使用反射來(lái)獲取POJO對(duì)象的get方法(當(dāng)然包括boolean類(lèi)型的is方法),然后來(lái)處理成為屬性,主要邏輯是分析是否包以is或者get關(guān)鍵字開(kāi)頭,如果是的話(huà)那么返回處理后的數(shù)據(jù)信息。轉(zhuǎn)換簡(jiǎn)略代碼如下:
/**
* 處理方法,將get方法轉(zhuǎn)換為屬性名
*
* @param methodName
* @return
*/
public static String dealMethodName(String methodName) {
StringBuilder stringBuilder = new StringBuilder();
if (methodName.startsWith("get")) {
stringBuilder.append(methodName.toLowerCase().charAt(3)).append(methodName.substring(4));
} else if (methodName.startsWith("is")) {
stringBuilder.append(methodName.toLowerCase().charAt(2)).append(methodName.substring(3));
} else {
return methodName;
}
return stringBuilder.toString();
}
問(wèn)題2:由于可以獲取到POJO對(duì)象的get方法,因此我們可執(zhí)行這個(gè)方法來(lái)進(jìn)行獲取到結(jié)果,從而也避免了private修飾的問(wèn)題。
問(wèn)題3:如果使用get方法獲取過(guò)來(lái)的是一個(gè)對(duì)象,那么我們可以通過(guò)判斷是不是Object類(lèi)來(lái)判斷是不是需要迭代處理,后來(lái)發(fā)現(xiàn),在使用一些基礎(chǔ)數(shù)據(jù)類(lèi)的時(shí)候,比如int,char,float等,他會(huì)自定的裝箱,從而導(dǎo)致我們無(wú)法處理,后來(lái)取了一個(gè)折中的辦法自定義了一個(gè)注解,在返回值是POJO對(duì)象的地方標(biāo)注,在使用反射獲取get方法中獲取這個(gè)注解,如果注解是null說(shuō)明不是POJO,如果不是null,那么我們進(jìn)行二次的迭代處理該對(duì)象,注解代碼如下:
//作用于方法上,運(yùn)行時(shí)保留
@Target(value={METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedIterative {
//參數(shù)沒(méi)有作用
String value() default "";
}
詳細(xì)代碼
首先實(shí)現(xiàn)POJO類(lèi),POJO類(lèi)主要代碼如下所示<span style="color:red;">set方法已省略,自行補(bǔ)充,People類(lèi)也是</span>,
public class Student{
private String name;
private int age;
private float height;
private double weight;
private char sex;
private boolean allow;
private People people;
public Student(String name, int age, float height, double weight, char sex, boolean allow) {
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
this.sex = sex;
this.allow = allow;
}
public String getName() { return name;}
public int getAge() { return age; }
public float getHeight() { return height;}
public double getWeight() {return weight;}
public char getSex() {return sex;}
public boolean isAllow() { return allow;}
//此處添加了注解,說(shuō)明此處返回的是一個(gè)POJO需要迭代處理
@NeedIterative
public People getPeople() { return new People("李亞偉",12); }
需要返回的對(duì)象POJO對(duì)象是People類(lèi)的代碼內(nèi)容為
public class People{
private String people;
private int work;
public People(String people, int work) {
this.people = people;
this.work = work;
}
public String getPeople() { return people; }
public int getWork() { return work; }
}
反射返回對(duì)象
代碼很見(jiàn)到,都是Class等常見(jiàn)的API,這里不做贅述。
public static Map toMap(Object obj) throws Exception {
Class clazz = obj.getClass();
//獲得屬性
Field[] fields = obj.getClass().getDeclaredFields();
HashMap hashMap = new HashMap(fields.length);
for (Field field : fields) {
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
//獲得get方法
Method getMethod = pd.getReadMethod();
//執(zhí)行g(shù)et方法返回一個(gè)Object
Object exeValue = getMethod.invoke(obj);
String key = dealMethodName(getMethod.getName());
NeedIterative annotation = getMethod.getAnnotation(NeedIterative.class);
//獲取的注解不為空,那么說(shuō)明此處返回的結(jié)果是對(duì)象,那么需要迭代處理
if (annotation != null) {
exeValue = toMap(exeValue);
}
hashMap.put(key, exeValue);
}
return hashMap;
}
輸出結(jié)果
由此可見(jiàn),不管是基本數(shù)據(jù)類(lèi)型,還是POJO類(lèi)都能正常的轉(zhuǎn)換。
斷點(diǎn)數(shù)據(jù)類(lèi)型查看:

sout輸出效果如下:
{
allow=true,
sex=m,
name=周濤,
weight=12.23,
people={
people=李亞偉,
work=12
},
age=23,
height=12.12
}
更多關(guān)于Java方面的文章,歡迎訪(fǎng)問(wèn)燕歸來(lái)https://www.zhoutao123.com