IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> BeanToMap or MapToBean -> 正文阅读

[开发测试]BeanToMap or MapToBean

前期也写beanToMap、mapToBean的工具类,只是有点土而已。

今天的beanToMap、mapToBean比以往更具有健壮性、高效性,也算是了结了。

健壮性体现在:

若Bean中的实例成员变量为null,则在转换成Map后,对应的键值对中的值也为null。

若Map中没有与Bean的实例成员变量相对应键值对,则在转换成Bean后,Bean实例的那些成员变量也为null。

若Map中键值对的值的真实类型全是String,与Bean的实例成员变量类型无法挨个对应,则对Map中的Value挨个进行类型转换。

高效性体现在:

对于同一个Bean不会进行第二次内省和反射操作。在Bean第一次进行内省和反射操作后,将其操作结果存入缓存中。后面若再对Bean进行内省和反射操作时,先在缓存中看看该Bean是否出现过,若出现过,直接由缓存返回结果;若没有出现过,再对该Bean进行内省和反射操作,再将其操作结果存入缓存,最后返回操作结果。

一、核心代码介绍

private static List<Field> getBeanClassField(Class beanClass)

该方法通过传入的参数beanClass,运用内省和反射,将其所有的Field对象(继承的不要,没有对应的setter、getter方法的不要)取出,并存储于List<Field>集合中;再以beanClass的全限定类名为Key,以List<Field>为Value,存入Map<String, List<Field>>中。

这个Map<String, List<Field>>就是用作缓存的,对于同一个beanClass,只会进行一次内省和反射操作,第二次就从缓存中直接取出内省和反射的操作结果。

private static final Map<String, List<Field>> fieldListMap;
    /*
    该Map<String,List<Field>>用作缓存,避免对同一个beanClass进行重复的内省和反射操作
    Key存储beanClass的全限定类名
    Value存储关于beanClass的所有Field的集合List<Field>
    */
    static {
        fieldListMap = new TreeMap<>();

    }

    private static List<Field> getBeanClassField(Class beanClass) {
        if (fieldListMap.containsKey(beanClass.getName()))
        //若缓存Map<String, List<Field>>的Key中已存储beanClass的全限定类名
        {
            System.err.println("Leave it alone--------"+beanClass.getName()+"---------beanClassField from buffer-------");
            return fieldListMap.get(beanClass.getName());
            //则直接由缓存Map<String, List<Field>>返回List<Field>
            //这样一来,就省去下面的一波内省、反射操作了
        }
        List<Field> fieldList = null;
        Method writeMethod;
        Method readMethod;
        Field beanClassField;
        String beanClassFieldName;
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);//内省
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();//Field的描述器
            fieldList = new ArrayList<>();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                readMethod = propertyDescriptor.getReadMethod();//与Field对应的读方法
                writeMethod = propertyDescriptor.getWriteMethod();//与Field对应的写方法
                if (readMethod != null && writeMethod != null) //读方法、写方法必须同时存在,这样判断是为了排除getClass()方法
                {
                    beanClassFieldName = propertyDescriptor.getName();//获取出Field的名字
                    beanClassField = beanClass.getDeclaredField(beanClassFieldName);//根据Field的名字获取beanClass的Field对象
                    beanClassField.setAccessible(true);//暴力反射
                    fieldList.add(beanClassField);//将beanClass的Field对象依次存入List<Field>
                }
            }
        }
        catch (IntrospectionException | NoSuchFieldException e)
        {
            e.printStackTrace();
        }
        fieldListMap.put(beanClass.getName(), fieldList);//缓存Map以beanClass的全限定类名为Key,将List<Field>存入Value
        return fieldList;
    }

二、运行展示

1.?mapToBean

1.1 Map中键值对与Bean中实例成员变量的名字、类型 一 一 对 应

?

?

1.2 Map中只有与Bean中部分实例成员变量的名字、类型对应的键值对

?

1.3 Map中的值全是字符串类型

2. beanToMap

2.1 Bean中实例成员变量均已赋值

?

2.2 Bean中实例成员变量部分赋值

?3.同一个Bean,一次(反射和内省)就好

运行信息由BeanUtility输出。Bean只要进行了内省和反射操作后,相同的Bean后续就不用再进行内省和反射操作了。

这里用一个for循环、两个Bean进行测试,for循环执行五次,循环体内对两个Bean进行beanToMap操作。当i=0时,两个Bean都会进行内省和反射操作;当i=1,2,3,4时,两个Bean分别从缓存中获取内省和反射操作的结果,同时还会输出一行上述的信息,刚好八次。

三、完整代码

3.1Bean代码

package com.rt.pojo;

import java.sql.Date;

public class Student {
    private Integer studentId;
    private String name;
    private Integer age;
    private String gender;
    private Date birthdate;
    private String grade;//年级
    private Double comprehensiveScore;//综合评分

    public Student(Integer studentId, String name, Integer age, String gender, Date birthdate, String grade, Double comprehensiveScore) {
        this.studentId = studentId;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.birthdate = birthdate;
        this.grade = grade;
        this.comprehensiveScore = comprehensiveScore;
    }

    public Student() {
    }

    public Integer getStudentId() {
        return studentId;
    }

    public void setStudentId(Integer studentId) {
        this.studentId = studentId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Date getBirthdate() {
        return birthdate;
    }

    public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

    public Double getComprehensiveScore() {
        return comprehensiveScore;
    }

    public void setComprehensiveScore(Double comprehensiveScore) {
        this.comprehensiveScore = comprehensiveScore;
    }

    @Override
    public String toString() {
        return "Student{" +
                "studentId=" + studentId +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", birthdate=" + birthdate +
                ", grade='" + grade + '\'' +
                ", comprehensiveScore=" + comprehensiveScore +
                '}';
    }
}

3.2主要代码BeanUtility.java

package com.rt.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class BeanUtility {

    private static final Map<String, List<Field>> fieldListMap;
    /*
    该Map<String,List<Field>>用作缓存,避免对同一个beanClass进行重复的内省和反射操作
    Key存储beanClass的全限定类名
    Value存储关于beanClass的所有Field的集合List<Field>
    */
    static {
        fieldListMap = new TreeMap<>();

    }

    private static List<Field> getBeanClassField(Class beanClass) {
        if (fieldListMap.containsKey(beanClass.getName()))
        //若缓存Map<String, List<Field>>的Key中已存储beanClass的全限定类名
        {
            System.err.println("Leave it alone--------"+beanClass.getName()+"---------beanClassField from buffer-------");
            return fieldListMap.get(beanClass.getName());
            //则直接由缓存Map<String, List<Field>>返回List<Field>
            //这样一来,就省去下面的一波内省、反射操作了
        }
        List<Field> fieldList = null;
        Method writeMethod;
        Method readMethod;
        Field beanClassField;
        String beanClassFieldName;
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);//内省
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();//Field的描述器
            fieldList = new ArrayList<>();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                readMethod = propertyDescriptor.getReadMethod();//与Field对应的读方法
                writeMethod = propertyDescriptor.getWriteMethod();//与Field对应的写方法
                if (readMethod != null && writeMethod != null) //读方法、写方法必须同时存在,这样判断是为了排除getClass()方法
                {
                    beanClassFieldName = propertyDescriptor.getName();//获取出Field的名字
                    beanClassField = beanClass.getDeclaredField(beanClassFieldName);//根据Field的名字获取beanClass的Field对象
                    beanClassField.setAccessible(true);//暴力反射
                    fieldList.add(beanClassField);//将beanClass的Field对象依次存入List<Field>
                }
            }
        }
        catch (IntrospectionException | NoSuchFieldException e)
        {
            e.printStackTrace();
        }
        fieldListMap.put(beanClass.getName(), fieldList);//缓存Map以beanClass的全限定类名为Key,将List<Field>存入Value
        return fieldList;
    }


    public static <T> T mapToBean(Map<String, Object> beanMap, Class<T> beanClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException
    {
        if (beanMap.isEmpty())
            return null;
        List<Field> fieldList = getBeanClassField(beanClass);
        T beanObject = beanClass.getConstructor().newInstance();
        Object valueOfMap;
        Object valueOfField;
        Class fieldClass;
        Method method;
        String keyOfMap;
        for (Field field : fieldList)
        {
            keyOfMap=field.getName();
            valueOfMap = beanMap.get(keyOfMap);
            if(valueOfMap==null)//若beanMap中没有与Field名字对应的Value
                continue;//直接跳过本次对beanObject实例成员变量的赋值
            fieldClass=field.getType();//获取Field对应的类型Class
            if (valueOfMap.getClass()==fieldClass)//若beanMap的Value类型与beanObject的Field类型相同
            {
                field.set(beanObject,valueOfMap);//则直接为beanObject对应的Field赋值
            }
            else//若beanMap的Value类型与beanClass的Field类型不同
            {
                method=fieldClass.getMethod("valueOf",String.class);//从Field类型对应的Class中获取静态方法"valueOf"对象,即Method对象
                valueOfField=method.invoke(null,valueOfMap.toString());//用Method对象重新封装beanMap的Value
                field.set(beanObject,valueOfField);//将重新封装的Value赋值给beanObject对应的Field
            }
        }
        return beanObject;
    }

    public static <T> Map<String, Object> beanToMap(T beanObject) throws IllegalAccessException {
        List<Field> fieldList = getBeanClassField(beanObject.getClass());
        Map<String, Object> beanMap = new TreeMap<>();
        for (Field field : fieldList) {
            beanMap.put(field.getName(), field.get(beanObject));
        }
        return beanMap;
    }

}

四、感受

写代码能够随心所欲,写注释有点很费劲,不过很练脑子,对技术的认识和把握,又会更上一层?楼!加油!

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 13:03:57  更:2022-05-09 13:04:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/17 22:18:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码