《Java高级-反射API:Field类的使用(5种)》

一、想对你说


(1)之前一直有小伙伴让我总结下Java相关的知识点,这里我针对有一定Java基础的同学做了一个系列的总结,感兴趣的同学可以看看顶部的【Java专栏】希望对大家有所帮助。
(2)要是对您有所帮助的话,可以给 “大大大钢琴” 点个赞,这是我继续下去的动力,谢谢大家了!废话不多说了,直接上干货。

二、反射API:Field类

(一)获取Field类对象属性

Field是一个类,位于Java.lang.reflect包下,在Java反射中Field用于获取某个类的属性或该属性的属性值。

Field类中最常用的是get(Object obj)和set(Object obj, Object value)这两个方法,所以这两个方法是最重要的。

获取Field类对象:4种方法
(1)Class.getDeclaredField(String name);
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有成员)。
(2)Class.getDeclaredFields();
返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)。

(3) Class.getField(String name);
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
(4)Class.getFields();
返回一个包含某些 Field 对象的数组,该数组包含此 Class 对象所表示的类或接口的所有可访问公共字段。

import java.lang.reflect.*;

public class test_demo {
    public static void main(String[] args) throws Exception {
        //获取Field类对象
        //1. Class.getDeclaredField(String name);
        //返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有成员)。
        //2. Class.getDeclaredFields();
        //返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)。
        //3. Class.getField(String name);
        //返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
        //4. Class.getFields();
        //返回一个包含某些 Field 对象的数组,该数组包含此 Class 对象所表示的类或接口的所有可访问公共字段。
        
        Person person =new Person();
        //(1)通过Class.getDeclaredField(String name)获取类或接口的指定已声明字段。  
        Field f1=person.getClass().getDeclaredField("name");
        System.out.println("getDeclaredFields(String name)用法:"+f1);
        
        //(2)通过Class.getDeclaredFields()获取类或接口的指定已声明字段。  
        Field []f2=person.getClass().getDeclaredFields();
        for(Field field:f2){
            System.out.println("getDeclaredFields()用法:"+field);
        }
        
        //(3)通过Class.getField(String name)返回一个类或接口的指定公共成员字段,私有成员报错。  
        Field f3=person.getClass().getField("name");//(private私有成员) 则会报错  
        System.out.println("Class.getField(String name)用法:"+f3);
        
        //(4)通过Class.getField(),返回 Class 对象所表示的类或接口的所有可访问公共字段。  
        Field []f4=person.getClass().getFields();
        for(Field fields:f4){
            //因为只有name属性为共有,因此只能遍历出name属性  
            System.out.println("Class.getFields()用法:"+fields);
        }
    }
}

//定义一个类,用于反射中的调用
class Person {
    public String name;
    public int age;
    public Person() {}
    public Person(String name) { this.name = name;}
    public Person(int age) { this.age = age; } 
}

//主要方法【后面会单独介绍】
//(单独介绍)getType(): 获取属性声明时类型对象(返回class对象)
//(单独介绍)getGenericType() : 返回属性声的Type类型
//getName() : 获取属性声明时名字
//getAnnotations() : 获得这个属性上所有的注释
//getModifiers() : 获取属性的修饰
//isEnumConstant() : 判断这个属性是否是枚举类
//isSynthetic() : 判断这个属性是否是 复合类
//(单独介绍)get(Object obj) : 取得obj对象这个Field上的值
//(单独介绍)set(Object obj, Object value) : 向obj对象的这个Field设置新值value

(二)Field.getType()返回一个Class对象

介绍Java Field.getType()获取属性声明时类型对象,Field对象所表示字段的声明类型。如果属性是一个泛型,从getType()只能得到这个属性的接口类型。

定义public Class<?>getType() 返回一个Class 对象。
返回:标识此对象所表示字段的声明类型的 Class 对象

import java.lang.reflect.*;

public class test_demo {
    public boolean[][] b = {{true, true}, {false, false}};
    public String name = "大大大钢琴";
    public Integer age = 23;

    public static void main(String[] args) throws Exception {
        //getType()返回一个Class对象(放回类中的字段类型)
        try {         
            Class<?> aClass = Class.forName("test_demo");
            Field[] fields = aClass.getFields();
            for (Field field : fields) {
                System.out.println("Field:"+field.getName());
                System.out.println("Type:"+field.getType().getCanonicalName());
                System.out.println("GenericType:"+field.getGenericType().toString() +"\n");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

(三)Field.getGenericType()返回属性类型

getType(): 获取属性声明时类型对象(返回class对象)

getGenericType() : 返回属性声明的Type类型

getType() 和 getGenericType()的区别

(1)首先是返回的类型不一样,一个是Class对象一个是Type接口。

(2)如果属性是一个泛型,从getType()只能得到这个属性的接口类型。但从getGenericType()还能得到这个泛型的参数类型。

(3)getGenericType()如果当前属性有签名属性类型就返回,否则就返回 Field.getType()。

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

public class test_demo {
    public static void main(String[] args) throws Exception {
        Person person = new Person();
        Field[] field = person.getClass().getDeclaredFields(); // 获取实体类的所有属性,返回Field数组
        try {
            // 遍历所有属性
            for (int j = 0; j < field.length; j++) {
                // 获取属性的名字
                String name = field[j].getName();
                // 将属性的首字符大写,方便构造get,set方法
                name = name.substring(0, 1).toUpperCase() + name.substring(1);
                // 获取属性的类型
                String type = field[j].getGenericType().toString();
                // 如果type是类类型,则前面包含"class ",后面跟类名
                if (type.equals("class java.lang.String")) {
                    Method method = person.getClass().getMethod("get" + name);
                    String value = (String) method.invoke(person); // 调用getter方法获取属性值
                    if (value == null) {
                        method = person.getClass().getMethod("set" + name, String.class);
                        method.invoke(person, "大大大钢琴");
                        method = person.getClass().getMethod("Person1", String.class);
                        method.invoke(person, "大大大钢琴");
                    }
                }
                if (type.equals("class java.lang.Integer")) {
                    Method method = person.getClass().getMethod("get" + name);
                    Integer value = (Integer) method.invoke(person);
                    if (value == null) {
                        method = person.getClass().getMethod("set" + name, Integer.class);
                        method.invoke(person, 0);
                    }
                }
                if (type.equals("class java.lang.Boolean")) {
                    Method method = person.getClass().getMethod("get" + name);
                    Boolean value = (Boolean) method.invoke(person);
                    if (value == null) {
                        method = person.getClass().getMethod("set" + name, Boolean.class);
                        method.invoke(person, false);
                    }
                }
                if (type.equals("class java.util.Date")) {
                    Method method = person.getClass().getMethod("get" + name);
                    Date value = (Date) method.invoke(person);
                    if (value == null) {
                        method = person.getClass().getMethod("set" + name, Date.class);
                        method.invoke(person, new Date());
                    }
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

//定义一个类,用于反射中的调用
class Person {
    public String name;
    public Integer age;

    public Person() {
        System.out.println("hello!");
    }

    public void Person1(String name) {
        System.out.println("hello my name is :" + name);
    }

    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;
    }

}

(四)Field.set()设置新值value

将指定对象变量上此 Field 对象表示的字段设置为指定的新值.

import java.lang.reflect.Field;
public class test_demo {
    public static void main(String[] args) throws Exception {
        Person person = new Person();
        person.setName("大大大钢琴");
        person.setAge(24);
        person.setSex("男");

        //(1)通过Class.getDeclaredField(String name)获取类或接口的指定属性值。
        Field f1 = person.getClass().getDeclaredField("name");
        System.out.println("Class.getDeclaredField(String name)用法:"+f1.get(person));


        //(2)通过Class.getDeclaredFields()获取类或接口的指定属性值。
        Field[] f2 = person.getClass().getDeclaredFields();
        for (Field field: f2) {
            field.setAccessible(true);
            System.out.println("Class.getDeclaredFields()用法:"+field.get(person));
        }

        //(3)使用set修改属性值,再遍历各属性的值*************
        f1.set(person, "钢琴");
        Field[] f3 = person.getClass().getDeclaredFields();
        for (Field fields: f3) {
            fields.setAccessible(true);
            System.out.println("修改name属性:"+fields.get(person));
        }
    }
}

//定义一个类,用于反射中的调用
class Person {
    public String name;
    public Integer age;
    public String sex;

    public Person() {
        System.out.println("hello!");
    }
    public void Person1(String name) {
        System.out.println("hello my name is :" + name);
    }
    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 getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }

}

(五)Field.get()取得对象的Field属性值

1. 如果字段不是静态字段的话,要传入反射类的对象.如果传null是会报java.lang.NullPointerException

2. 如果字段是静态字段的话,传入任何对象都是可以的,包括null

import java.lang.reflect.Field;
public class test_demo {
    public static void main(String[] args) throws Exception {

        //(1)获取执行class类的field字段属性
        Field field=number.class.getDeclaredField("field");
        int a= (Integer)field.get(new number()) ;
        //int c= (Integer)field.get(null) ; //不是静态字段不能传null
        System.out.println(a);

        //(2)获取执行class类的staticField字段属性(静态字段)
        Field staticfield=number.class.getDeclaredField("staticField");
        int b= (Integer)staticfield.get("") ;
        int d= (Integer)staticfield.get(null) ;
        System.out.println(b);
        System.out.println(d);
    }
}

class number{
    int field=3;
    static int staticField=4;//static静态属性
}

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大大大钢琴

喜欢!就请他吃3块钱好吃的吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值