Java 反射4-反射与单级VO操作

  我们在开发过程中,经常会遇到这样的场景:

class Person {
    private String name;
    private String gender;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }

}
public class Test {
    public static void main(String[] args) throws Exception {
        Person person = new Person();
        // 利用set/get方法设置属性值
        person.setName("张三");
        person.setGender("男");
    }
}

  当类中属性只有一两个的时候,还可以耐心的调用set/get方法,如果类中有几十个,成百上千个属性需要设置呢,怎么办?

  如果这种情况下还一个一个设置,那岂不是要忙死了,而且主方法代码不久爆炸多了吗。

  如果我们可以通过传入一个字符串,就把所有的属性设置了,这不就简单了很多了吗。如上面的程序,我们可以传入:

// 字符串的格式随便都可以定义,我们这里选择如下格式
// 类名.属性名1:属性值1|类名.属性名2:属性值2|...
String value = "person.name:张三|person.gender:男";

  接下来,我们实现一下这种方式。

1. 单级VO操作

  上面所讨论的方法其实是Java中的 VO操作。

  vo:value object,值对象,使用一个值作为数据的存储与传递。

  vo一般是来做值的存储与传递。

  我们这里的值就是字符串。

2. 设计思路

  我们看一个图,以此为基准进行程序设计。
图

2.1 Person类

  我们要操作的类,这里以Person类为例子。

package class.vo;

public class Person {
    private String name;
    private String gender;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }

    @
    Override
    public String toString() {
        return "Person[" +
            "name: " + this.name + ", gender: " + this.gender +"]";
    }
}

2.2 PersonAction类

  其实就是实际要操作的类上层的一个封装,根据我们工程中不同的操作类进行相对的修改。

package class.vo;

import class13.util.BeanOpreation;

public class PersonAction {
    private Person person = new Person();
    public void setValue(String value) throws Exception {
        BeanOpreation.setBeanValue(this, value);
    }

    public Person getPerson() {
        return this.person;
    }
}

2.3 BeanOpreation工具类

  单级VO的核心操作,利用到大量的反射操作

// 工具类一般都存放在util包下
package class13.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class BeanOpreation {
    private BeanOpreation() {}

    // 传入修改命令,格式为 "类名.属性名1:属性值1|类名.属性名2:属性值2|..."
    public static void setBeanValue(Object actionObject, String msg) throws Exception{
        // 根据 '|' 把命令分为两部分
        String[] result = msg.split("\\|");
        for(int i = 0; i < result.length; i++) {
            // 根据 ':' 再分,得到 类.属性 和 属性值
            String[] temp = result[i].split("\\:");
            // 拿到 类名
            String className = temp[0].split("\\.")[0];
            // 拿到 属性名
            String fieldName = temp[0].split("\\.")[1];
            // 拿到属性内容
            String fieldValue = temp[1];

            // 获取要操作的类(通过PersonAction类拿到Person类)
            Object curObject = getObject(actionObject, className);
            // 通过当前操作类的set方法,进行属性值修改
            setObject(curObject, fieldName, fieldValue);
        }
    }

    // 因为在PersonAction类中获取Person类的方法叫做getPerson,而传入的命令中,类名首字母是小写的,所以这里要对类名做一下修改
    public static String initCap(String str) {
        return str.substring(0, 1).toUpperCase()+str.substring(1);
    }


    // 获取要操作的类(通过PersonAction类拿到Person类)
    public static Object getObject(Object obj, String className) throws Exception {
        // 通过真实操作类的类名字符串,转换为Action类中获取真实操作类得的方法名
        String getClassMethodName = "get"+initCap(className);

        // 在正式获取get方法前做一个判断,判断Action类中是否按照约定定义了private person 对象,如果没有这个对象,何谈之后的修改
        Field field = obj.getClass().getDeclaredField(className);
        if(field == null) {
            // 再给一次机会,在父类中查找
            field = obj.getClass().getField(className);
        }
        if(field == null) {
            return null;
        }
        // 通过上面经过处理的来的 get方法 方法名在Action类中查找该方法
        Method getClassMethod = obj.getClass().getMethod(getClassMethodName);
        return getClassMethod.invoke(obj);
    }

    // 传入一个类对象,属性名,属性值,调用它的set将该属性修改为给定的属性值
    public static void setObject(Object curObj, String fieldName, String fieldValue) throws Exception {
        Field field = curObj.getClass().getDeclaredField(fieldName);
        // 判断该属性是否存在
        if(field == null) {
            field = curObj.getClass().getField(fieldName);
        }
        if(field == null) {
            return;
        }
        String setMethodName = "set"+initCap(fieldName);
        Method setMethod = curObj.getClass().getMethod(setMethodName, field.getType());
        setMethod.invoke(curObj, fieldValue);
    }
}

2.4 Test测试类

package class;

import class.vo.PersonAction;

public class Test {
    public static void main(String[] args) throws Exception {
        String value = "person.name:张三|person.gender:男";
        PersonAction personAction = new PersonAction();
        personAction.setValue(value);
        System.out.println(personAction.getPerson());
    }
}

运行结果:

运行结果

  完全符合我们的预期。

  上面的例子只是以一个简单的Person类为例子,核心是BeanOpreation工具类与Action类的配合使用。

  BeanOpreation工具类可以适应不同的类,只要有相应的Action类即可,所以说反射VO的作用还是很强大的,希望大家都能够掌握。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值