Java中JavaBean对象和Map的互相转换方法实例
作者:毕竟尹稳健
为什么需要将javaBean和map进行转换,在很多应用场景中,需要将key=value形式的数据与javaBean对象相互转换,下面这篇文章主要给大家介绍了关于Java中JavaBean对象和Map的互相转换的相关资料,需要的朋友可以参考下
1.JavaBean转Map
1.1.简介
这篇博客是通过反射来进行实现转换的
在学习redis中,发现了一个知识点,就是Java对象转map,视频中的内容是通过hutool工具转换的,但是我们学习者肯定不能只通过工具来进行转换,更多的是通过这个知识点学习到他的底层是如何进行转换的。
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.简单转换
@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.属性里面套属性转换
实体类
package com.sky; import com.sky.dto.UserDTO; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; /** * @author 尹稳健~ * @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 尹稳健~ * @version 1.0 * @time 2022/11/9 */ @Retention(RetentionPolicy.RUNTIME) public @interface OneSelf { }
转换方法:
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.总结
- 就是通过自定义注解来判断是否需要递归转换
- 嵌套的话,应该还有其他方法可以研究一下
2.Map转JavaBean对象
2.1.简介
在实际项目中相信大多数人都使用过工具类,比如说commons下的和hutool工具类,但是我们只是知道如何调用这个API,而不知道他方法的底层是通过什么样的思路进行实现的。
通过对一些底层的了解和学习,能学到更多的知识,了解底层的一些实现方式,拓展自己的思维。
我将从下面开始介绍如何将JavaBean对象转换为Map。
2.2.Introspector介绍
Introspector是JDK中java.beans包下的类,它为目标JavaBean提供了一种了解原类方法、属性和事件的标准方法。通俗的说,就是可以通过Introspector构建一个BeanInfo对象,而这个BeanInfo对象中包含了目标类中的属性、方法和事件的描述信息,然后可以使用这个BeanInfo对象对目标对象进行相关操作。
JDK原文:
- Introspector类提供了一种标准的工具来了解目标Java Bean支持的属性,事件和方法。
- 对于这三种信息中的每一种,Introspector将分别分析bean的类和超类,寻找显式或隐式信息,并使用该信息构建一个全面描述目标bean的BeanInfo对象。
- 对于每个类“Foo”,如果存在相应的“FooBeanInfo”类,在查询信息时提供非空值,则显式信息可能可用。 我们首先通过获取目标bean类的完整的包限定名称并附加“BeanInfo”来形成一个新的类名称来查找BeanInfo类。 如果失败,那么我们将使用该名称的最终类名组件,并在BeanInfo包搜索路径中指定的每个包中查找该类。
方法介绍:
修饰符 | 返回类型 | 方法名称和参数 | 描述 |
---|---|---|---|
static | String | decapitalize(String name) | 实用方法来取一个字符串并将其转换为正常的Java变量名称大小写。 |
static | void | flushCaches() | 冲洗所有Introspector的内部缓存。 |
static | void | flushFromCaches(类<?> clz) | 刷新内部缓存信息给一个给定的类。 |
static | BeanInfo | getBeanInfo(类<?> beanClass) | 内省Java Bean并了解其所有属性,暴露的方法和事件。 |
static | BeanInfo | getBeanInfo(类<?> beanClass, 类<?> stopClass) | 内省Java bean并了解其属性,暴露的方法,低于给定的“停止”点。 |
static | BeanInfo | getBeanInfo(类<?> beanClass, 类<?> stopClass, int flags) | 对Java Bean进行内省,并了解其所有属性,暴露的方法和事件,低于给定的 stopClass点,受到一些控制 flags 。 |
static | BeanInfo | getBeanInfo(类<?> beanClass, int flags) | 对Java bean进行内省,并了解其所有属性,公开方法和事件,并遵守一些控制标志。 |
static | String[] | getBeanInfoSearchPath() | 获取将用于查找BeanInfo类的包名称列表。 |
static | void | setBeanInfoSearchPath(String[] path) | 更改将用于查找BeanInfo类的包名称列表。 |
2.3.BeanInfo介绍
JDK原文:
- 使用BeanInfo界面创建一个BeanInfo类,并提供关于bean的方法,属性,事件和其他功能的显式信息。
- 在开发您的bean时,您可以实现应用任务所需的bean功能,省略其余的BeanInfo功能。
- 它们将通过自动分析获得,通过使用低级反射的bean方法和应用标准设计模式。 您有机会通过各种描述符类提供其他bean信息。
关键方法介绍:
修饰符 | 返回类型 | 方法名称和参数 | 描述 |
---|---|---|---|
无 | PropertyDescriptor[] | getPropertyDescriptors() | 返回bean的所有属性的描述符。 |
2.4用反射实现转换
实体类:
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; }
方法封装:
反射知识介绍:
// 利用反射调用构造器实例化对象 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 { // 利用反射调用构造器实例化对象 Object object = beanClass.getDeclaredConstructor().newInstance(); // 通过实例化对象的class对象,获取所有的字段 Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { // 返回属性字段的修饰符 int mod = field.getModifiers(); // 如果是静态或者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(内省)的方式转换
public Object mapToBean2(Map<String,Object> map,Class<?> beanClass) throws Exception{ // 利用class对象调用构造器实例化对象 Object object = beanClass.getDeclaredConstructor().newInstance(); // 内省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; }
总结
到此这篇关于Java中JavaBean对象和Map的互相转换的文章就介绍到这了,更多相关Java JavaBean和Map互相转换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!