Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值
Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值
说到循环遍历,最常见的遍历数组/列表、Map等。但是,在开发过程中,有时需要循环遍历一个对象的所有属性。遍历对象的属性该如何遍历呢?查了一下资料,需要用到一些反射的知识!
话不多说,先上代码
首先先定义一个测试对象 Test
public class Test {
    private String aa;
    private int bb;
    private String cc;
    public String dd;
    public String getAa() {
        return aa;
    }
    public void setAa(String aa) {
        this.aa = aa;
    }
    public int getBb() {
        return bb;
    }
    public void setBb(int bb) {
        this.bb = bb;
    }
    public String getCc() {
        return cc;
    }
    public void setCc(String cc) {
        this.cc = cc;
    }
}
这个对象里分别有aa bb cc 三个私有属性,dd一个公有属性,接下来通过反射来获取这个对象的四个属性值
    public static void main(String[] args) {
        /**
         *  返回Class 对象所表示的类或接口的所有可访问公共字段。
         */
        Field[] f1=Test.class.getFields();
        System.out.println("Test类里面的公共字段属性的个数为:" +f1.length+"个,分别为:");
        for(int i=0;i<f1.length;i++){
            String attributeName=f1[i].getName();
            System.out.println(attributeName);
        }
        /**
         * 返回 Class 对象所表示的类或接口所声明的所有字段,
         * 包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。
         */
        Field[] f=Test.class.getDeclaredFields();
        System.out.println("Test类里面的所有字段属性的个数为:"+f.length+"个,分别为:");
        for(int i=0;i<f.length;i++){
            String attributeName=f[i].getName();
            System.out.println(attributeName);
        }
    }
运行main函数,输出如下:
Test类里面的公共字段属性的个数为:1个,分别为:
dd
Test类里面的所有字段属性的个数为:4个,分别为:
aa
bb
cc
dd
getFields()方法只能获取Test类里面的所有公有属性,getDeclaredFields()方法可获取Test类所有公有/私有属性。需要注意的是,如果Test类继承了别的类,这两个方法都无法获取父类里面的属性的。
现在,已经获取到了Test类里面的所有属性名,然后通过这些属性名给这个类的实例赋值和取值操作。
先来给实例赋值,代码如下:
        Test test=new Test();
        //给test对象赋值
        for(int i=0;i<f.length;i++){
            //获取属相名
            String attributeName=f[i].getName();
            //将属性名的首字母变为大写,为执行set/get方法做准备
            String methodName=attributeName.substring(0,1).toUpperCase()+attributeName.substring(1);
            try{
                //获取Test类当前属性的setXXX方法(私有和公有方法)
                /*Method setMethod=Test.class.getDeclaredMethod("set"+methodName);*/
                //获取Test类当前属性的setXXX方法(只能获取公有方法)
                Method setMethod=Test.class.getMethod("set"+methodName,String.class);
                //执行该set方法
                setMethod.invoke(test,attributeName+"方法赋值");
            }catch (NoSuchMethodException e) {
                try {
                    Method setMethod=Test.class.getMethod("set"+methodName,int.class);
                    setMethod.invoke(test,123);
                } catch (Exception e2) {
                    f[i].set(test,attributeName+"直接赋值");
                }
            }
        }   
如上代码,之前已经获取到了Test类里面的所有属性名,在这部分代码中,就可以通过属性名来获取与之对应的set方法。需要注意的是,在上面代码中try-catch了两次,是因为在Test这个类中的属性的set方法的参数,有的是String类型,有的是int类型的,还有的属性是没有set方法的。第一次try是未了抓取所有参数类型不是String类型和不存在的set方法。第二次抓取的是参数不是int类型的和不存在的set方法。依次进行处理。除此之外,假如set方法的参数类型还有更多的类型的话,可以通过Filed类的getGenericType() 这个方法先判断类型,这个以后再做赘述。
接下来从实例中通过get方法来取值,代码如下:
        //从test对象取值
        for(int i=0;i<f.length;i++){
            //获取属相名
            String attributeName=f[i].getName();
            //将属性名的首字母变为大写,为执行set/get方法做准备
            String methodName=attributeName.substring(0,1).toUpperCase()+attributeName.substring(1);
            Object result;
            try{
                //获取Test类当前属性的setXXX方法(私有和公有方法)
                /*Method setMethod=Test.class.getDeclaredMethod("set"+methodName);*/
                //获取Test类当前属性的setXXX方法(只能获取公有方法)
                Method getMethod=Test.class.getMethod("get"+methodName);
                //执行该set方法
                result=getMethod.invoke(test);
            }catch(NoSuchMethodException e){
                result=f[i].get(test);
            }
            System.out.println("属性:"+attributeName+"="+result);
        }
这里的代码也try-catch一次,get方法不存在参数类型判断的,这里的try-catch只是为了抓取公有属性不存在get方法的情况以做相应的处理。
运行测试程序,输出结果如下:
属性:aa=aa方法赋值
属性:bb=123
属性:cc=cc方法赋值
属性:dd=dd直接赋值
最后附上完整的测试程序
    public static void main(String[] args) throws Exception{
        /**
         *  返回Class 对象所表示的类或接口的所有可访问公共字段。
         */
        Field[] f1=Test.class.getFields();
        System.out.println("Test类里面的公共字段属性的个数为:" +f1.length+"个,分别为:");
        for(int i=0;i<f1.length;i++){
            String attributeName=f1[i].getName();
            System.out.println(attributeName);
        }
        /**
         * 返回 Class 对象所表示的类或接口所声明的所有字段,
         * 包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。
         */
        Field[] f=Test.class.getDeclaredFields();
        System.out.println("Test类里面的所有字段属性的个数为:"+f.length+"个,分别为:");
        for(int i=0;i<f.length;i++){
            String attributeName=f[i].getName();
            System.out.println(attributeName);
        }
        Test test=new Test();
        //给test对象赋值
        for(int i=0;i<f.length;i++){
            //获取属相名
            String attributeName=f[i].getName();
            //将属性名的首字母变为大写,为执行set/get方法做准备
            String methodName=attributeName.substring(0,1).toUpperCase()+attributeName.substring(1);
            try{
                //获取Test类当前属性的setXXX方法(私有和公有方法)
                /*Method setMethod=Test.class.getDeclaredMethod("set"+methodName);*/
                //获取Test类当前属性的setXXX方法(只能获取公有方法)
                Method setMethod=Test.class.getMethod("set"+methodName,String.class);
                //执行该set方法
                setMethod.invoke(test,attributeName+"方法赋值");
            }catch (NoSuchMethodException e) {
                try {
                    Method setMethod=Test.class.getMethod("set"+methodName,int.class);
                    setMethod.invoke(test,123);
                } catch (Exception e2) {
                    f[i].set(test,attributeName+"直接赋值");
                }
            }
        }
        //从test对象取值
        for(int i=0;i<f.length;i++){
            //获取属相名
            String attributeName=f[i].getName();
            //将属性名的首字母变为大写,为执行set/get方法做准备
            String methodName=attributeName.substring(0,1).toUpperCase()+attributeName.substring(1);
            Object result;
            try{
                //获取Test类当前属性的setXXX方法(私有和公有方法)
                /*Method setMethod=Test.class.getDeclaredMethod("set"+methodName);*/
                //获取Test类当前属性的setXXX方法(只能获取公有方法)
                Method getMethod=Test.class.getMethod("get"+methodName);
                //执行该set方法
                result=getMethod.invoke(test);
            }catch(NoSuchMethodException e){
                result=f[i].get(test);
            }
            System.out.println("属性:"+attributeName+"="+result);
        }
    }												
											Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值的更多相关文章
- java使用反射给对象属性赋值的两种方法
		
java反射无所不能,辣么,怎么通过反射设置一个属性的值呢? 主程序: /** * @author tengqingya * @create 2017-03-05 15:54 */ public cl ...
 - Java中short、int、long、float、double的取值范围
		
一.基本数据类型的特点,位数,最大值和最小值.1.基本类型:short 二进制位数:16 包装类:java.lang.Short 最小值:Short.MIN_VALUE=-32768 (-2的15此方 ...
 - Java的8种基本数据类型的内存占用字节数和取值范围
		
这是8中基本类型的内存中占用字节数(取值范围是2的(字节数X8-1)次方) 1.整型 类型 存储需求 bit数 取值范围 byte 1字节 1*8 -128-127 short 2字节 2*8 -32 ...
 - SQL state [72000]; error code [1461]; ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值 ; nested exception is java.sql.BatchUpdateException: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
		
本文转自 https://www.cnblogs.com/yingsong/p/5685790.html 原 因:某一个字段本为varchar2(1024),但是实际要插入的值超过varchar2允 ...
 - 反射中的 Method 的 getReadMethod 与 getWriteMethod 使用 【获取一个对象的所有属性字段名称和其对应的值】
		
转: class反射(一),以及Method 的 getReadMethod 与 getWriteMethod 使用 2018年11月28日 17:27:42 zich77521 阅读数 788 ...
 - Java反射给泛型集合赋值
		
Java反射给泛型集合赋值 泛型 Java泛型简单描述下: 比如创建一个List集合,我想在里边只放Student对象信息,就需要写成 List<Student> studentList ...
 - [置顶] js中如何复制一个对象,如何获取所有属性和属性对应的值
		
在js中如何复制一个对象,例如如下一个js对象. 如果知道这个对象的所有属性自然就可以重新new一个,然后对每个属性赋值,就可以做到,但如果不知道呢?如何创建一个内容相同 的对象呢? var obj= ...
 - 乐字节Java循环:循环控制和嵌套循环
		
乐字节小乐上次讲完了Java反射,接下来小乐给大家讲述Java循环. 循环有以下四部分: 一.循环控制 1. do..while 直到型 ( 先执行后判断) ,结构为: 先执行循环体,后判断布尔表达式 ...
 - java 通过反射获取类属性结构,类方法,类父类及其泛型,类,接口和包
		
首先自定义三个类 package reflection1; public interface MtInterface { void info(); } package reflection1; imp ...
 
随机推荐
- 关于引用外部类要用static 的问题
			
一.直接用 static 引用 import static net.mindview.util.Print.*; //net...为引用的类,此方法在程序加载时就已实例化 二. 也可以手动在需要时实例 ...
 - 目标检测-yolo2
			
转载自:http://blog.csdn.net/qq_34784753/article/details/78825493 对于现在的最好的检测系统来说,yolo_v1 的问题主要出现在两方面,也就是 ...
 - 【C++ Primer 第11章】2. 关联容器操作
			
练习答案 一.访问元素 关联容器额外类型别名 key_type 此容器类型的关键字类型 mapped_type 每个关键字关联的类型,只 适用于map mapped_type 对于set,与key_ ...
 - jq:翻页时,保存上页多选框checkbox选中状态
			
这里主要讲一种:中间的 checkbox 是 通过Ajax调出的. 则翻页时,为了保存上页的选定状态,可在页面中定义一个变量,用来存储选中状态的值. <input class="cli ...
 - Android使用帧动画内存溢出解决方法
			
Android使用帧动画内存溢出解决方法https://blog.csdn.net/daitu_liang/article/details/52336015https://blog.csdn.net/ ...
 - hdu 1548 升降梯
			
题目大意:有一个升降机,它有两个按钮UP和DOWN,给你一些数i表示层数,并且每层对应的Ki,如果按UP按钮,会从第i层升到第i+Ki层:如果按了DOWN则会从第i层降到第i-Ki层:并规定能到的层数 ...
 - Delphi---TServerSocket和TClientSocket发送和接收大数据包
			
https://www.cnblogs.com/zhangzhifeng/p/6065244.html TServerSocket和TClientSocket用非阻塞模式发送和接收比较大的数据时,可能 ...
 - sed & awk之sed
			
sed处理文本的方法 sed在处理文本时,会先读取第一个输入行,将编辑命令应用于输入行,然后读取下一个输入行,并应用编辑命令.sed总是处理最新版本的行,因此sed中有多个编辑命令时,编辑命令的顺序对 ...
 - Codeforces 442C Artem and Array (看题解)
			
Artem and Array 经过分析我们能发现, 如果对于一个a[ i ] <= a[ i + 1 ] && a[ i ] <= a[ i - 1 ]可以直接删掉. 最 ...
 - PHP函数比较变量
			
作为一个PHPer,一定要多看PHP手册,每过一遍手册,你总会发现一些以前被你忽略的一些东西:我们可以从各个不同的地方/渠道学习到PHP的相关知识,但也不要忘记我们的手册,PHP手册永远是学习和提升P ...