Java中JavaBean對象和Map的互相轉(zhuǎn)換方法實例
1.JavaBean轉(zhuǎn)Map
1.1.簡介
這篇博客是通過反射來進行實現(xiàn)轉(zhuǎn)換的
在學習redis中,發(fā)現(xiàn)了一個知識點,就是Java對象轉(zhuǎn)map,視頻中的內(nèi)容是通過hutool工具轉(zhuǎn)換的,但是我們學習者肯定不能只通過工具來進行轉(zhuǎn)換,更多的是通過這個知識點學習到他的底層是如何進行轉(zhuǎn)換的。
1.2.反射知識
// 新建一個對象
UserDTO userDTO = new UserDTO(1L,"zhangsan","123");
// 通過reflect獲取所有屬性
// userDTO.getClass().getDeclaredFields() // 暴力獲取所有的屬性字段
for (Field field : userDTO.getClass().getDeclaredFields()) {
// 設置暴力反射,獲取私有屬性
field.setAccessible(true);
try {
/**
field.getName() 獲取屬性字段的字段名稱
field.get(userDTO) 相當于 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.簡單轉(zhuǎn)換
@Test
void contextLoads() {
Map<String, Object> map = new HashMap<>();
UserDTO userDTO = new UserDTO(1L,"zhangsan","123");
// 通過reflect獲取所有屬性
for (Field field : userDTO.getClass().getDeclaredFields()) {
// 設置暴力反射,獲取私有屬性
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)換
實體類
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<>();
// 通過reflect獲取所有樹形
for (Field field : o.getClass().getDeclaredFields()) {
// 設置暴力反射,獲取私有屬性
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é)
- 就是通過自定義注解來判斷是否需要遞歸轉(zhuǎn)換
- 嵌套的話,應該還有其他方法可以研究一下
2.Map轉(zhuǎn)JavaBean對象
2.1.簡介
在實際項目中相信大多數(shù)人都使用過工具類,比如說commons下的和hutool工具類,但是我們只是知道如何調(diào)用這個API,而不知道他方法的底層是通過什么樣的思路進行實現(xiàn)的。
通過對一些底層的了解和學習,能學到更多的知識,了解底層的一些實現(xiàn)方式,拓展自己的思維。
我將從下面開始介紹如何將JavaBean對象轉(zhuǎn)換為Map。
2.2.Introspector介紹
Introspector是JDK中java.beans包下的類,它為目標JavaBean提供了一種了解原類方法、屬性和事件的標準方法。通俗的說,就是可以通過Introspector構(gòu)建一個BeanInfo對象,而這個BeanInfo對象中包含了目標類中的屬性、方法和事件的描述信息,然后可以使用這個BeanInfo對象對目標對象進行相關操作。
JDK原文:
- Introspector類提供了一種標準的工具來了解目標Java Bean支持的屬性,事件和方法。
- 對于這三種信息中的每一種,Introspector將分別分析bean的類和超類,尋找顯式或隱式信息,并使用該信息構(gòu)建一個全面描述目標bean的BeanInfo對象。
- 對于每個類“Foo”,如果存在相應的“FooBeanInfo”類,在查詢信息時提供非空值,則顯式信息可能可用。 我們首先通過獲取目標bean類的完整的包限定名稱并附加“BeanInfo”來形成一個新的類名稱來查找BeanInfo類。 如果失敗,那么我們將使用該名稱的最終類名組件,并在BeanInfo包搜索路徑中指定的每個包中查找該類。
方法介紹:
| 修飾符 | 返回類型 | 方法名稱和參數(shù) | 描述 |
|---|---|---|---|
| static | String | decapitalize(String name) | 實用方法來取一個字符串并將其轉(zhuǎn)換為正常的Java變量名稱大小寫。 |
| static | void | flushCaches() | 沖洗所有Introspector的內(nèi)部緩存。 |
| static | void | flushFromCaches(類<?> clz) | 刷新內(nèi)部緩存信息給一個給定的類。 |
| static | BeanInfo | getBeanInfo(類<?> beanClass) | 內(nèi)省Java Bean并了解其所有屬性,暴露的方法和事件。 |
| static | BeanInfo | getBeanInfo(類<?> beanClass, 類<?> stopClass) | 內(nèi)省Java bean并了解其屬性,暴露的方法,低于給定的“停止”點。 |
| static | BeanInfo | getBeanInfo(類<?> beanClass, 類<?> stopClass, int flags) | 對Java Bean進行內(nèi)省,并了解其所有屬性,暴露的方法和事件,低于給定的 stopClass點,受到一些控制 flags 。 |
| static | BeanInfo | getBeanInfo(類<?> beanClass, int flags) | 對Java bean進行內(nèi)省,并了解其所有屬性,公開方法和事件,并遵守一些控制標志。 |
| static | String[] | getBeanInfoSearchPath() | 獲取將用于查找BeanInfo類的包名稱列表。 |
| static | void | setBeanInfoSearchPath(String[] path) | 更改將用于查找BeanInfo類的包名稱列表。 |
2.3.BeanInfo介紹
JDK原文:
- 使用BeanInfo界面創(chuàng)建一個BeanInfo類,并提供關于bean的方法,屬性,事件和其他功能的顯式信息。
- 在開發(fā)您的bean時,您可以實現(xiàn)應用任務所需的bean功能,省略其余的BeanInfo功能。
- 它們將通過自動分析獲得,通過使用低級反射的bean方法和應用標準設計模式。 您有機會通過各種描述符類提供其他bean信息。
關鍵方法介紹:
| 修飾符 | 返回類型 | 方法名稱和參數(shù) | 描述 |
|---|---|---|---|
| 無 | PropertyDescriptor[] | getPropertyDescriptors() | 返回bean的所有屬性的描述符。 |
2.4用反射實現(xiàn)轉(zhuǎn)換
實體類:
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;
}方法封裝:
反射知識介紹:
// 利用反射調(diào)用構(gòu)造器實例化對象 Object object = beanClass.getDeclaredConstructor().newInstance(); // 通過實例化對象的class對象,獲取所有的字段 Field[] fields = object.getClass().getDeclaredFields(); // 返回屬性字段的修飾符 int mod = field.getModifiers();
關鍵方法:
public Object mapToBean(Map<String,Object> map,Class<?> beanClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 利用反射調(diào)用構(gòu)造器實例化對象
Object object = beanClass.getDeclaredConstructor().newInstance();
// 通過實例化對象的class對象,獲取所有的字段
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);
// 相當于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對象調(diào)用構(gòu)造器實例化對象
Object object = beanClass.getDeclaredConstructor().newInstance();
// 內(nèi)省Java bean并了解其屬性,暴露的方法,==簡單來說就是將屬性封裝到了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é)
到此這篇關于Java中JavaBean對象和Map的互相轉(zhuǎn)換的文章就介紹到這了,更多相關Java JavaBean和Map互相轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
關于SpringBoot在有Ajax時候不跳轉(zhuǎn)的問題解決
最近在使用Ajax來發(fā)送一些數(shù)據(jù)給后臺一個Controller,但是遇到些問題,所以下面這篇文章主要給大家介紹了關于SpringBoot在有Ajax時候不跳轉(zhuǎn)問題的解決辦法,需要的朋友可以參考下2022-05-05

