Java——反射

谁说我不能喝 提交于 2020-03-05 01:35:56

1、定义

​ java反射机制是说:在运行状态中,对于任意的一个类,我们都能知道它的所有属性和方法;对于任意的一个对象,我们都能够调用它的所有方法和得到所有属性。这种动态调用方法和动态获取属性的功能成为java语言的反射机制。

​ 实际上,我们创建的每一个类都是Class对象,称之为类对象。

2、反射机制的方法

//创建一个类
package reflex;

public class Student {
    private int id;
    private String name;
    private String gender;
    private String address;

    public Student(){

    }

    public Student(String name){
        this.name = name;
    }

    private Student(String name, String address){
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    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 String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

1)、获取类对象

package reflex;

import org.junit.Test;

public class ReflexTest {
    //获取类对象
    @Test
    public void m1() throws ClassNotFoundException {
        //方法一
        Student student = new Student();
        System.out.println(student.getClass());
        //方法二
        String className = "reflex.Student";
        System.out.println(Class.forName(className));
    }
}
//输出结果
class reflex.Student
class reflex.Student

2)、获取类成员

获取类的构造方法

//获取类的所有public类型的构造方法
    @Test
    public void m2(){
        Student student = new Student();
        Class c = student.getClass();
        //获取类的所有构造方法
        Constructor[] constructors = c.getDeclaredConstructors();
        /**
         * 通过getDeclaredConstructors方法可以返回类的构造方法,返回的是一个数组
         * 通过getModifiers可以得到构造方法的类型,返回的是数字,1-public 2-private
         * 通过getParameterTypes可以得到某构造方法的所有参数类型
         */
        for(int i = 0;i < constructors.length;++i){
            System.out.print(Modifier.toString(constructors[i].getModifiers()) + " " + "参数:");  //获取构造方法的类型
            Class[] parameterTypes = constructors[i].getParameterTypes();  //获取构造方法的参数类型
            for(int j = 0 ;j < parameterTypes.length;++j){
                System.out.print(parameterTypes[j].getName()+ " ");
            }
            System.out.println("");
        }
    }
//运行结果
private 参数:java.lang.String java.lang.String 
public 参数:java.lang.String 
public 参数:

获取类的特定的构造方法

//返回特定的构造方法
    @Test
    public void m3() throws NoSuchMethodException {
        Student stu = new Student();
        Class[] c = {String.class,String.class};
        Constructor constructor = stu.getClass().getConstructor(c);
        System.out.print(Modifier.toString(constructor.getModifiers()) + " " + "参数:");
        Class[] parameterTypes = constructor.getParameterTypes();
        for(int j = 0 ;j < parameterTypes.length;++j){
            System.out.print(parameterTypes[j].getName()+ " ");
        }
        System.out.println("");
    }
//运行结果
public 参数:java.lang.String 

//调用构造方法

//调用构造方法
    @Test
    public void m4() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Student stu = new Student();

        //调用公有构造函数
        Class[] c1 = {String.class};
        Constructor constructor1 = stu.getClass().getDeclaredConstructor(c1);
        constructor1.newInstance("yanjundong");

        //调用私有构造函数
        Class[] c2 = {int.class,String.class};
        Constructor constructor2 = stu.getClass().getDeclaredConstructor(c2);
        constructor2.setAccessible(true);  //多出的一步
        constructor2.newInstance(1001,"yanjundong");
    }
//运行结果
该学生的姓名为yanjundong
该学生的姓名为yanjundong学号为1001

调用类的私有方法

//调用类的私有方法
    @Test
    public void m5() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Student stu = new Student();

        Class[] p = {String.class};
        //通过getDeclaredMethod方法获取这个私有方法,第一个参数为方法名,第二个为参数类型
        Method method = stu.getClass().getDeclaredMethod("welcome", p);
        method.setAccessible(true);
        //通过invoke方法执行,第一个参数为类的实例,第二个参数为方法参数
        Object args[] = {"java反射测试"};
        method.invoke(stu,args);
    }
//运行结果
java反射测试

调用类的私有字段,并修改值

//调用类的私有字段,并修改值
    @Test
    public void m6() throws NoSuchFieldException, IllegalAccessException {
        Student stu = new Student();
        stu.setId(1000);
        stu.setName("yanjundong");
        stu.setAddress("陕西省西安市");

        Field field = stu.getClass().getDeclaredField("name");
        field.setAccessible(true);
        field.set(stu,"yan俊东");
        String name = field.get(stu).toString();
        System.out.println(name);
    }
//运行结果
yan俊东

3、Fastjson

–还是爸爸的产品好用,简单、方便,虽然网上有人说没有Jackson稳定,

//添加maven依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.62</version>
    </dependency>

将Java对象转化为JSON字符串

@Test
    public void m3() throws IOException {
        Student student = new Student();
        student.setId(1000);
        student.setAddress("XXXXXXXX");
        student.setName("zhangsan");
        student.setGender("M");
        student.setDate(new Date());
        
        String jsonString = JSON.toJSONString(student);
        System.out.println(jsonString);
    }
//输出结果
{"address":"XXXXXXXX","date":1571925626901,"gender":"M","id":1000,"name":"zhangsan"}

将JSON字符串转化为Java对象

@Test
    public void m3() throws IOException {
        Student student = new Student();
        student.setId(1000);
        student.setAddress("XXXXXXXX");
        student.setName("zhangsan");
        student.setGender("M");
        student.setDate(new Date());
        //序列化
        String jsonString = JSON.toJSONString(student);
        System.out.println(jsonString);
        //反序列化
        Student student1 = JSON.parseObject(jsonString,Student.class);
        System.out.println(student1);
    }
//输出结果
{"name":"zhangsan","gender":"M","birthday":"2019-10-24","address":"XXXXXXXX"}
Student{id=0, name='zhangsan', gender='M', address='XXXXXXXX', date=Thu Oct 24 00:00:00 CST 2019}

注解符的使用

	@JSONField(serialize=false)
    private int id;
    @JSONField(ordinal = 1)
    private String name;
    @JSONField(ordinal = 2)
    private String gender;
    @JSONField(ordinal = 4)
    private String address;
    @JSONField(format="yyyy-MM-dd",name = "birthday",ordinal = 3)
    private Date date;

//可以使用serialize指定字段不序列化,使用deserialize指定字段不反序列化
//format参数用于格式化date属性
//使用ordinal可以指定字段的顺序

使用 ContextValueFilter 配置 JSON 转换

实现对value的过滤,

    @Test
    public void m4(){
        Student student = new Student();
        student.setId(1000);
        student.setAddress("XXXXXXXX");
        student.setName("zhangsan");
        student.setGender("M");
        student.setDate(new Date());
        
        ContextValueFilter valueFilter = new ContextValueFilter() {
            @Override
            public Object process(BeanContext beanContext, Object o, String name, Object value) {
                if (name.equals("gender")) {
                    return "NOT TO DISCLOSE";
                }
                if (value.equals("zhangsan")) {
                    return ((String) value).toUpperCase();
                }else{
                    return value;
                }
            }
        };
        
        String jsonOutput = JSON.toJSONString(student, valueFilter);
        System.out.println(jsonOutput);
    }
//输出结果
{"name":"ZHANGSAN","gender":"NOT TO DISCLOSE","birthday":"2019-10-25","address":"XXXXXXXX"}

使用 NameFilter 和 SerializeConfig

NameFilter 序列化时修改key;

SerializeConfig 内部是个map容器主要功能是配置并记录每种Java类型对应的序列化类;

    @Test
    public void m5(){
        List<Student> studentList = new ArrayList<Student>();
        Student student = new Student();
        student.setId(1000);
        student.setAddress("XXXXXXXX");
        student.setName("zhangsan");
        student.setGender("M");
        student.setDate(new Date());
        studentList.add(student);
        Student student1 = new Student();
        student1.setId(1001);
        student1.setAddress("XXXX-XXXX");
        student1.setName("lisi");
        student1.setGender("W");
        student1.setDate(new Date());
        studentList.add(student1);

        //使用NameFilter过滤器处理字段名称
        NameFilter formatName = new NameFilter() {
            @Override
            public String process(Object o, String name, Object value) {
                if("address".equals(name))
                    return "address of home";
                else
                    return name;
            }
        };
        // 新创建的过滤器与Student类相关联,然后添加到全局实例,它是SerializeConfig类中的静态属性。
        SerializeConfig.getGlobalInstance().addFilter(Student.class,  formatName);
        //使用toJSONStringWithDateFormat而不是toJSONString,它可以更快速的格式化日期。
        String jsonString = JSON.toJSONStringWithDateFormat(studentList, "yyyy-MM-dd");
        //String jsonString = JSON.toJSONString(studentList);
        System.out.println(jsonString);
    }
//输出结果
[
  {
    "address of home": "XXXXXXXX",
    "date": 1583304236873,
    "gender": "M",
    "id": 1000,
    "name": "zhangsan"
  },
  {
    "address of home": "XXXX-XXXX",
    "date": 1583304236873,
    "gender": "W",
    "id": 1001,
    "name": "lisi"
  }
]
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!