【BeanUtils】自己写的一个BeanUtils-代码方法详解

转载请注明出处:http://blog.csdn.net/qq_26525215

本文源自大学之旅_谙忆的博客

BeanUtils工具包是由Apache公司所开发,主要是方便程序员对Bean类能够进行简便的操作。

在这里,不讲解如何使用apache的BeanUtils工具,而是我们自己写底层,自己利用类反射来实现BeanUtils的功能。
需要先学习类反射!

通过给定bean对象的类,和封装的Map对象,返回出一个bean对象。

准备bean对象:

这里准备了User类和Book类:

User

package cn.hncu.domain;

/**
 * @author 陈浩翔
 *
 * 2016-8-25
 */
public class User {
    private String uuid;
    private String name;
    private int age;
    public String getUuid() {
        return uuid;
    }
    public void setUuid(String uuid) {
        this.uuid = uuid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (uuid == null) {
            if (other.uuid != null)
                return false;
        } else if (!uuid.equals(other.uuid))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "User [uuid=" + uuid + ", name=" + name + ", age=" + age + "]";
    }

}

Book

package cn.hncu.domain;

/**
 * @author 陈浩翔
 *
 * 2016-8-25
 */
public class Book {
    private String uuid;
    private String name;
    private double inPrice;
    private double outPrice;
    private int num;
    public String getUuid() {
        return uuid;
    }
    public void setUuid(String uuid) {
        this.uuid = uuid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getInPrice() {
        return inPrice;
    }
    public void setInPrice(double inPrice) {
        this.inPrice = inPrice;
    }
    public double getOutPrice() {
        return outPrice;
    }
    public void setOutPrice(double outPrice) {
        this.outPrice = outPrice;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Book other = (Book) obj;
        if (uuid == null) {
            if (other.uuid != null)
                return false;
        } else if (!uuid.equals(other.uuid))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "Book [uuid=" + uuid + ", name=" + name + ", inPrice=" + inPrice
                + ", outPrice=" + outPrice + ", num=" + num + "]";
    }
}

过度版的:

先看过度版的:接参后需要强转成对应的bean,因为返回类型是Object。

MyBeanUtils1

package cn.hncu.beanUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

public class MyBeanUtils1 {

    public static Object populate(Class cls ,Map map) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
        Object obj = null;

        //1、用类反射new出对象
        obj = cls.newInstance();

        //2 再用类反射对新new的对象设置属性值(必须遵守Java设置规范)--即通过setter方法设置
        //2.1遍历出所有该类声明的属性
        Field flds[] = cls.getDeclaredFields();//getDeclaredFields()返回Class中所有的字段,包括私有字段;
        for(Field fld:flds){
            //获取该fld对象所代表的属性名
            String fldName = fld.getName();
            //根据属性名,到map中去读取数据,只有数据非空才需要给该属性设置值
            Object value = map.get(fldName);
            if(value==null){//如果map中不存在对应的属性数据,我们在这里给出提示信息
                System.out.println(fldName+"的数据为空");
            }else{
                //如果map中存在对应的属性数据,则由属性名得出它的setter方法的名字
                String mothodName = "set"+fldName.substring(0, 1).toUpperCase()+fldName.substring(1);

                 //根据方法名和参数的数据类型(其实就是属性的类型),获得Method对象
                Class paramTypes[] = new Class[1];
                paramTypes[0] = fld.getType();
                Method method = cls.getDeclaredMethod(mothodName, paramTypes);

                //调用该method对象所代表的方法
                Object args[] = new Object[1];
                args[0]=value;
                method.invoke(obj, args);
            }
        }
        return obj;
    }

}

测试

@Test
    public void test1() {
        Map map = new HashMap();
        map.put("uuid", "001");
        map.put("name", "Jack");
        map.put("age", 20);

        Map map2 = new HashMap();
        map2.put("uuid", "001");
        map2.put("name", "红楼梦");
        map2.put("inPrice", 20.5);
        //数据可能不全
        map2.put("num", 123);
        try {
            User user =  (User) MyBeanUtils1.populate(User.class, map);
            System.out.println(user);
            Book book =  (Book) MyBeanUtils1.populate(Book.class, map2);
            System.out.println(book);
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }

测试结果:

这个还不是很完善,为什么呢,因为返回类型是Object,每次都要强转,比较麻烦,而且我们传了bean的class对象过去了,完全可以实现不用强转的,这个时候我们就需要用到泛型了。
而且Map的泛型我们可以确定了,肯定是Map<String,Object>这样的

好了,学习一下最终版的、

最终版:

MyBeanUtils

package cn.hncu.beanUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

public class MyBeanUtils {

    public static<T> T populate(Class<T> cls ,Map<String, Object> map) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
        T obj = null;

        //1、用类反射new出对象
        obj = cls.newInstance();

        //2 再用类反射对新new的对象设置属性值(必须遵守Java设置规范)--即通过setter方法设置
        //2.1遍历出所有该类声明的属性
        Field flds[] = cls.getDeclaredFields();//getDeclaredFields()返回Class中所有的字段,包括私有字段;
        for(Field fld:flds){
            //获取该fld对象所代表的属性名
            String fldName = fld.getName();
            //根据属性名,到map中去读取数据,只有数据非空才需要给该属性设置值
            Object value = map.get(fldName);
            if(value==null){//如果map中不存在对应的属性数据,我们在这里给出提示信息
                System.out.println(fldName+"的数据为空");
            }else{
                //如果map中存在对应的属性数据,则由属性名得出它的setter方法的名字
                String mothodName = "set"+fldName.substring(0, 1).toUpperCase()+fldName.substring(1);

                 //根据方法名和参数的数据类型(其实就是属性的类型),获得Method对象
                Class<?> paramTypes[] = new Class[1];
                paramTypes[0] = fld.getType();
                Method method = cls.getDeclaredMethod(mothodName, paramTypes);

                //调用该method对象所代表的方法
                Object args[] = new Object[1];
                args[0]=value;
                method.invoke(obj, args);
            }
        }
        return obj;
    }

}

测试方法:

@Test
    @SuppressWarnings("unchecked")
    public void test() {
        Map<String, Object> map = new HashMap();
        map.put("uuid", "001");
        map.put("name", "Jack");
        map.put("age", 20);

        Map<String, Object> map2 = new HashMap();
        map2.put("uuid", "001");
        map2.put("name", "红楼梦");
        map2.put("inPrice", 20.5);
        //数据可能不全
        map2.put("num", 123);
        try {
            User user = MyBeanUtils.populate(User.class, map);
            System.out.println(user);
            Book book = MyBeanUtils.populate(Book.class, map2);
            System.out.println(book);
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }

测试结果:

完整项目源码链接:

–>点击访问本系列源码–

转载请注明出处:http://blog.csdn.net/qq_26525215

本文源自大学之旅_谙忆的博客

时间: 2024-09-21 09:57:21

【BeanUtils】自己写的一个BeanUtils-代码方法详解的相关文章

Android中自定义一个View的方法详解_Android

本文实例讲述了Android中自定义一个View的方法.分享给大家供大家参考,具体如下: Android中自定义View的实现比较简单,无非就是继承父类,然后重载方法,即便如此,在实际编码中难免会遇到一些坑,我把自己遇到的一些问题和解决方法总结一下,希望对广大码友们有所帮助. 注意点① 用xml定义Layout时,Root element 最好使用merge 当我们需要继承一个布局比较复杂的ViewGroup(比较多的是LinearLayout.RelativeLayout)时,通常会用xml来

Android中自定义一个View的方法详解

本文实例讲述了Android中自定义一个View的方法.分享给大家供大家参考,具体如下: Android中自定义View的实现比较简单,无非就是继承父类,然后重载方法,即便如此,在实际编码中难免会遇到一些坑,我把自己遇到的一些问题和解决方法总结一下,希望对广大码友们有所帮助. 注意点① 用xml定义Layout时,Root element 最好使用merge 当我们需要继承一个布局比较复杂的ViewGroup(比较多的是LinearLayout.RelativeLayout)时,通常会用xml来

C++中用两个标准容器stack,实现一个队列的方法详解_C 语言

代码如下所示: 复制代码 代码如下: // StackToQueue.cpp : 定义控制台应用程序的入口点.//用两个标准容器stack,实现一个队列#include "stdafx.h"#include <iostream>#include <stack>using namespace std;template <class T>class StackToQueue{public: StackToQueue() {  stack1;  stack

jquery ajax局部加载方法详解(实现代码)_jquery

在jquery中实现ajax加载的方法有很多种,不像以前的js的ajax只有那一种,下面我们介绍jquery ajax实现局部加载方法总结,有需要了解的朋友可参考. 例 $.ajax({ url: "hotelQuery!queryHotelByCity.action", type: "post", dataType: "html", data: "queryHotel.city="+cityobj.value+"&

jQuery grep()方法详解及实例代码_jquery

什么是jQuery.grep()? jQuery.grep()是一个查找满足过滤函数的数组元素的函数.原始数组不受影响,返回值为数组. 用法介绍: 写法: jQuery.grep( array, function(elementOfArray, indexInArray) [, invert ] ) 参数介绍: array 类型: Array 用于查询元素的数组. function(elementOfArray, indexInArray) 类型: Function() 该函数来处理每项元素的比

JSONObject使用方法详解_javascript技巧

1.JSONObject介绍 JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包. 2.下载jar包 http://files.cnblogs.com/java-pan/lib.rar 提供了除JSONObject的jar之外依赖的其他6个jar包,一共7个jar文件 说明:因为工作中项目用到的版本是1.1的对应jdk1.3的版本,故本篇博客是基于1.1版本介绍的. 对应此版本的javadoc下载路径如下:htt

使用Java构造和解析Json数据的两种方法(详解二)_java

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包. 在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面接着介绍用org.json构造和解析Json数据的方法

Ruby中的钩子方法详解

  这篇文章主要介绍了Ruby中的钩子方法详解,本文讲解了什么是钩子方法.included.Devise中的 included.extended.ActiveRecord中的 extended.prepended.inherited等内容,需要的朋友可以参考下 Ruby的哲学理念是基于一个基本的要素,那就是让程序员快乐.Ruby非常注重程序员的快乐,并且也提供了许多不同的方法来实现它. 它的元编程能力能够让程序员编写在运行时动态生成的代码.它的线程功能使得程序员有一种优雅的的方式编写多线程代码.

JavaScript原生对象之Number对象的属性和方法详解

 这篇文章主要介绍了JavaScript原生对象之Number对象的属性和方法详解,本文讲解了创建 Number 对象的语法.MAX_VALUE.MIN_VALUE.NaN等属性或方法,需要的朋友可以参考下     创建 Number 对象的语法: 代码如下: var myNum = new Number(value); var myNum = Number(value); 当 Number() 和运算符 new 一起作为构造函数使用时,它返回一个新创建的 Number 对象.如果不用 new