Java中JavaBean對(duì)象和Map的互相轉(zhuǎn)換方法實(shí)例
1.JavaBean轉(zhuǎn)Map
1.1.簡(jiǎn)介
這篇博客是通過(guò)反射來(lái)進(jìn)行實(shí)現(xiàn)轉(zhuǎn)換的
在學(xué)習(xí)redis中,發(fā)現(xiàn)了一個(gè)知識(shí)點(diǎn),就是Java對(duì)象轉(zhuǎn)map,視頻中的內(nèi)容是通過(guò)hutool工具轉(zhuǎn)換的,但是我們學(xué)習(xí)者肯定不能只通過(guò)工具來(lái)進(jìn)行轉(zhuǎn)換,更多的是通過(guò)這個(gè)知識(shí)點(diǎn)學(xué)習(xí)到他的底層是如何進(jìn)行轉(zhuǎn)換的。
1.2.反射知識(shí)
// 新建一個(gè)對(duì)象 UserDTO userDTO = new UserDTO(1L,"zhangsan","123"); // 通過(guò)reflect獲取所有屬性 // userDTO.getClass().getDeclaredFields() // 暴力獲取所有的屬性字段 for (Field field : userDTO.getClass().getDeclaredFields()) { // 設(shè)置暴力反射,獲取私有屬性 field.setAccessible(true); try { /** field.getName() 獲取屬性字段的字段名稱 field.get(userDTO) 相當(dāng)于 userDTO.getField(); */ map.put(field.getName(),field.get(userDTO)); } catch (IllegalAccessException e) { e.printStackTrace(); } } for (String s : map.keySet()) { System.out.println(s+"=="+map.get(s)); }
1.3.簡(jiǎn)單轉(zhuǎn)換
@Test void contextLoads() { Map<String, Object> map = new HashMap<>(); UserDTO userDTO = new UserDTO(1L,"zhangsan","123"); // 通過(guò)reflect獲取所有屬性 for (Field field : userDTO.getClass().getDeclaredFields()) { // 設(shè)置暴力反射,獲取私有屬性 field.setAccessible(true); try { map.put(field.getName(),field.get(userDTO)); } catch (IllegalAccessException e) { e.printStackTrace(); } } for (String s : map.keySet()) { System.out.println(s+"=="+map.get(s)); } }
1. 4.屬性里面套屬性轉(zhuǎn)換
實(shí)體類
package com.sky; import com.sky.dto.UserDTO; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; /** * @author 尹穩(wěn)健~ * @version 1.0 * @time 2022/11/9 */ @Data @AllArgsConstructor @NoArgsConstructor public class Clazz { private String ClazzName; @OneSelf List<UserDTO> userDTOList; }
自定義注解
package com.sky; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * @author 尹穩(wěn)健~ * @version 1.0 * @time 2022/11/9 */ @Retention(RetentionPolicy.RUNTIME) public @interface OneSelf { }
轉(zhuǎn)換方法:
public Map<String,Object> beanToMap(Object o){ Map<String, Object> map = new HashMap<>(); // 通過(guò)reflect獲取所有樹(shù)形 for (Field field : o.getClass().getDeclaredFields()) { // 設(shè)置暴力反射,獲取私有屬性 field.setAccessible(true); try { if (field.get(o) != null){ Class<?> aClass = field.get(o).getClass(); OneSelf annotation = aClass.getAnnotation(OneSelf.class); if (annotation!=null){ Map<String, Object> beanToMap = beanToMap(field.get(o)); map.put(field.getName(),beanToMap); }else{ map.put(field.getName(),field.get(o)); } } } catch (IllegalAccessException e) { e.printStackTrace(); } } return map; }
1. 5.總結(jié)
- 就是通過(guò)自定義注解來(lái)判斷是否需要遞歸轉(zhuǎn)換
- 嵌套的話,應(yīng)該還有其他方法可以研究一下
2.Map轉(zhuǎn)JavaBean對(duì)象
2.1.簡(jiǎn)介
在實(shí)際項(xiàng)目中相信大多數(shù)人都使用過(guò)工具類,比如說(shuō)commons下的和hutool工具類,但是我們只是知道如何調(diào)用這個(gè)API,而不知道他方法的底層是通過(guò)什么樣的思路進(jìn)行實(shí)現(xiàn)的。
通過(guò)對(duì)一些底層的了解和學(xué)習(xí),能學(xué)到更多的知識(shí),了解底層的一些實(shí)現(xiàn)方式,拓展自己的思維。
我將從下面開(kāi)始介紹如何將JavaBean對(duì)象轉(zhuǎn)換為Map。
2.2.Introspector介紹
Introspector是JDK中java.beans包下的類,它為目標(biāo)JavaBean提供了一種了解原類方法、屬性和事件的標(biāo)準(zhǔn)方法。通俗的說(shuō),就是可以通過(guò)Introspector構(gòu)建一個(gè)BeanInfo對(duì)象,而這個(gè)BeanInfo對(duì)象中包含了目標(biāo)類中的屬性、方法和事件的描述信息,然后可以使用這個(gè)BeanInfo對(duì)象對(duì)目標(biāo)對(duì)象進(jìn)行相關(guān)操作。
JDK原文:
- Introspector類提供了一種標(biāo)準(zhǔn)的工具來(lái)了解目標(biāo)Java Bean支持的屬性,事件和方法。
- 對(duì)于這三種信息中的每一種,Introspector將分別分析bean的類和超類,尋找顯式或隱式信息,并使用該信息構(gòu)建一個(gè)全面描述目標(biāo)bean的BeanInfo對(duì)象。
- 對(duì)于每個(gè)類“Foo”,如果存在相應(yīng)的“FooBeanInfo”類,在查詢信息時(shí)提供非空值,則顯式信息可能可用。 我們首先通過(guò)獲取目標(biāo)bean類的完整的包限定名稱并附加“BeanInfo”來(lái)形成一個(gè)新的類名稱來(lái)查找BeanInfo類。 如果失敗,那么我們將使用該名稱的最終類名組件,并在BeanInfo包搜索路徑中指定的每個(gè)包中查找該類。
方法介紹:
修飾符 | 返回類型 | 方法名稱和參數(shù) | 描述 |
---|---|---|---|
static | String | decapitalize(String name) | 實(shí)用方法來(lái)取一個(gè)字符串并將其轉(zhuǎn)換為正常的Java變量名稱大小寫(xiě)。 |
static | void | flushCaches() | 沖洗所有Introspector的內(nèi)部緩存。 |
static | void | flushFromCaches(類<?> clz) | 刷新內(nèi)部緩存信息給一個(gè)給定的類。 |
static | BeanInfo | getBeanInfo(類<?> beanClass) | 內(nèi)省Java Bean并了解其所有屬性,暴露的方法和事件。 |
static | BeanInfo | getBeanInfo(類<?> beanClass, 類<?> stopClass) | 內(nèi)省Java bean并了解其屬性,暴露的方法,低于給定的“停止”點(diǎn)。 |
static | BeanInfo | getBeanInfo(類<?> beanClass, 類<?> stopClass, int flags) | 對(duì)Java Bean進(jìn)行內(nèi)省,并了解其所有屬性,暴露的方法和事件,低于給定的 stopClass點(diǎn),受到一些控制 flags 。 |
static | BeanInfo | getBeanInfo(類<?> beanClass, int flags) | 對(duì)Java bean進(jìn)行內(nèi)省,并了解其所有屬性,公開(kāi)方法和事件,并遵守一些控制標(biāo)志。 |
static | String[] | getBeanInfoSearchPath() | 獲取將用于查找BeanInfo類的包名稱列表。 |
static | void | setBeanInfoSearchPath(String[] path) | 更改將用于查找BeanInfo類的包名稱列表。 |
2.3.BeanInfo介紹
JDK原文:
- 使用BeanInfo界面創(chuàng)建一個(gè)BeanInfo類,并提供關(guān)于bean的方法,屬性,事件和其他功能的顯式信息。
- 在開(kāi)發(fā)您的bean時(shí),您可以實(shí)現(xiàn)應(yīng)用任務(wù)所需的bean功能,省略其余的BeanInfo功能。
- 它們將通過(guò)自動(dòng)分析獲得,通過(guò)使用低級(jí)反射的bean方法和應(yīng)用標(biāo)準(zhǔn)設(shè)計(jì)模式。 您有機(jī)會(huì)通過(guò)各種描述符類提供其他bean信息。
關(guān)鍵方法介紹:
修飾符 | 返回類型 | 方法名稱和參數(shù) | 描述 |
---|---|---|---|
無(wú) | PropertyDescriptor[] | getPropertyDescriptors() | 返回bean的所有屬性的描述符。 |
2.4用反射實(shí)現(xiàn)轉(zhuǎn)換
實(shí)體類:
package com.sky.dto; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class UserDTO { private Long id; private String nickName; private String icon; }
方法封裝:
反射知識(shí)介紹:
// 利用反射調(diào)用構(gòu)造器實(shí)例化對(duì)象 Object object = beanClass.getDeclaredConstructor().newInstance(); // 通過(guò)實(shí)例化對(duì)象的class對(duì)象,獲取所有的字段 Field[] fields = object.getClass().getDeclaredFields(); // 返回屬性字段的修飾符 int mod = field.getModifiers();
關(guān)鍵方法:
public Object mapToBean(Map<String,Object> map,Class<?> beanClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { // 利用反射調(diào)用構(gòu)造器實(shí)例化對(duì)象 Object object = beanClass.getDeclaredConstructor().newInstance(); // 通過(guò)實(shí)例化對(duì)象的class對(duì)象,獲取所有的字段 Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { // 返回屬性字段的修飾符 int mod = field.getModifiers(); // 如果是靜態(tài)或者final修飾的不需要添加 if (Modifier.isStatic(mod)|| Modifier.isFinal(mod)){ continue; } // 暴力獲取私有屬性 field.setAccessible(true); // 相當(dāng)于object.setterField() field.set(object,map.get(field.getName())); } return object; }
2.5.利用Introspector(內(nèi)省)的方式轉(zhuǎn)換
public Object mapToBean2(Map<String,Object> map,Class<?> beanClass) throws Exception{ // 利用class對(duì)象調(diào)用構(gòu)造器實(shí)例化對(duì)象 Object object = beanClass.getDeclaredConstructor().newInstance(); // 內(nèi)省Java bean并了解其屬性,暴露的方法,==簡(jiǎn)單來(lái)說(shuō)就是將屬性封裝到了BeanInfo里面== BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass()); // 返回bean的所有屬性的描述符。 PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { /** * java.beans.PropertyDescriptor[ * name=icon; values={expert=false; visualUpdate=false; hidden=false; * enumerationValues=[Ljava.lang.Object;@75c77add; required=false}; * propertyType=class java.lang.String; readMethod=public java.lang.String com.sky.dto.UserDTO.getIcon(); * writeMethod=public void com.sky.dto.UserDTO.setIcon(java.lang.String)] */ System.out.println(propertyDescriptor); // 獲取屬性的setter方法 Method setter = propertyDescriptor.getWriteMethod(); if (setter!=null){ // 獲取值 Object o = map.get(propertyDescriptor.getName()); if (o!=null){ // 利用反射將屬性賦值 setter.invoke(object,o); } } } return object; }
總結(jié)
到此這篇關(guān)于Java中JavaBean對(duì)象和Map的互相轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)Java JavaBean和Map互相轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java并發(fā)編程之柵欄(CyclicBarrier)實(shí)例介紹
這篇文章主要介紹了Java并發(fā)編程之柵欄(CyclicBarrier)實(shí)例介紹,柵欄類似閉鎖,但是它們是有區(qū)別的,需要的朋友可以參考下2015-04-04java開(kāi)發(fā)分布式服務(wù)框架Dubbo暴露服務(wù)過(guò)程詳解
這篇文章主要為大家介紹了java開(kāi)發(fā)分布式服務(wù)框架Dubbo暴露服務(wù)的過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11SpringBoot使用@ControllerAdvice全局異常處理
這篇文章主要介紹了SpringBoot使用@ControllerAdvice全局異常處理,異常處理是非常重要的一部分,它可以幫助我們捕獲并處理應(yīng)用程序中出現(xiàn)的異常情況,提高應(yīng)用程序的健壯性和可靠性,需要的朋友可以參考下2023-07-07教你在?Java?中實(shí)現(xiàn)?Dijkstra?最短路算法的方法
這篇文章主要教你在?Java?中實(shí)現(xiàn)?Dijkstra?最短路算法的方法,在實(shí)現(xiàn)最短路算法之前需要先實(shí)現(xiàn)帶權(quán)有向圖,文章中給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Java 利用枚舉實(shí)現(xiàn)接口進(jìn)行統(tǒng)一管理
這篇文章主要介紹了Java 利用枚舉實(shí)現(xiàn)接口進(jìn)行統(tǒng)一管理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02