反射&注解

【主要内容】

  1. 反射的概念

  2. Java类加载的三个阶段

  3. Class、Field、Constructor、Method类详解

  4. 注解的概述

  5. 元注解

  6. 自定义注解

  7. 类加载器

  8. 泛型擦除问题

【学习目标】

知识点要求
反射的概念掌握
Java类加载的三个阶段掌握
Class、Field、Constructor、Method类详解掌握
注解的概述掌握
元注解掌握
自定义注解掌握
类加载器掌握
泛型擦除问题掌握

1. 反射

1.1 【掌握】反射概念和功能

1.1.1 概念

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

说人话,反射机制就是将类的各个组成部分(属性,方法,构造器)封装为其它对象。

如图所示:

举例说明:

在IDEA中展示的Student.class文件看到的不是乱码!

原因是: IDEA中后台已经通过反射将Student.class文件进行就反编译。

1.1.2 反射提供的功能

在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

1,反编译:.class-->.java

2,通过反射机制访问java对象的属性,方法,构造方法,注解等;

1.1.3 反射的相关类
java.lang.Class;                
java.lang.reflect.Constructor; 
java.lang.reflect.Field;        
java.lang.reflect.Method;
java.lang.reflect.Modifier; 权限修饰符事物描述类

1.2 【掌握】Java类加载的三个阶段

1.2.1 源代码(source)

源代码不是指.java文件,而是经编译器编译后生成的.class字节码文件

1.2.2 类加载(class)

  class字节码文件经类加载器classloader加载到虚拟机内存。类加载器解析class文件生成Class类型的对象

1.2.3 运行时(runtime)

newInstance()根据java类型生成对象

1.2.4 图解

1.3 【掌握】获取Class的三种方式

1.3.1 概述

Class对象的三种获取方式对应上面Java类加载的三个阶段

1.3.2 准备工作创建Student
/*
    @Author yangge
    @Date 2023/8/17 
    @Description 学生类
*/
public class Student  {
    private String name;
    private int age;
    public Student() {
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    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 String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
​
        Student student = (Student) o;
​
        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}

1.3.3 反射机制获取类有三种方法,我们来获取Student类型
/*
    @Author yangge
    @Date 2023/8/17 
    @Description 反射机制获取类有三种方法,我们来获取Student类型
*/
public class RefleDemo2 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 方式一:
        Class clazz1 = Class.forName("com.huayu.reflection.demo1.Student");
        System.out.println("clazz1 = " + clazz1);//clazz1 = class com.huayu.reflection.demo1.Student
        // 方式二:任何类都有class属性
        Class<Student> clazz2 = Student.class;
        System.out.println("clazz2 = " + clazz2);
        // 方式三:任何对象都有getClass()方法
        Student student = new Student();
        Class clazz3 = student.getClass();
        System.out.println("clazz3 = " + clazz3);
    }
}
注意事项: Class.forName("com.huayu.reflection.demo1.Student")
      1. 在java中表示路径时使用.连接各个包 , 而在进行IO操作时,使用 / 或者 \\ 连接各个包
      2. 使用类加载器读字节码文件时,默认从src包中读, 而且读取时使用类的全类名
      3. 三种方式获得的类对象是同一个对象,一个类文件只对应一个类对象。

1.4 【掌握】Class的功能

1.3.1 获取功能
1.3.1.1 获取成员变量
FieldgetField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段类对象。
Field[]getFields() 返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段类对象。
FieldgetDeclaredField(String name) 返回一个 Field对象,它反映此表示的类或接口的指定已声明字段类对象。
Field[]getDeclaredFields() 返回的数组 Field对象反映此表示的类或接口声明的所有字段类对象。

代码如下:

package com.huayu.reflection.demo2;
​
import java.lang.reflect.Field;
​
/*
    @Author yangge
    @Date 2023/8/17 
    @Description 获取字节码中的成员变量
 明确: 一个Class对象就是一个.java 或者 .class文件, 里面封装了java类的属性,成员方法,构造方法等各个信息
       getField(String name) : 根据属性名称获取公有属性
       getFields() : 获取所有公有属性
       getDeclaredField(String name) : 根据名称获取属性(公有,私有均可)
       getDeclaredFields() :获取所有属性(公有,私有均可)
*/
public class RefleDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        // 1. 获得Student类对象, 或者说是Student.java文件
        Class aClass = Class.forName("com.huayu.reflection.demo1.Student");
        // 2. 获取Student.java文件中的公有属性:name
        Field nameField = aClass.getField("name");
        System.out.println("nameField = " + nameField);
​
        // 3. 获取Student.java文件中的所有的公有属性:name , score
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("--------------------------------");
​
        // 4. 获取Student.java文件中的私有属性:age
        Field ageField = aClass.getDeclaredField("age");
        System.out.println("ageField = " + ageField);
​
        System.out.println("--------------------------------");
        // 5. 获取Student.java文件中所有的公有和私有属性:age,school
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
    }
}

1.3.1.2 获取构造方法
Constructor<T>getConstructor(类<?>... parameterTypes) 返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共类函数
Constructor<?>[]getConstructors() 返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造类对象。
Constructor<T>getDeclaredConstructor(类<?>... parameterTypes) 返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定类函数。
Constructor<?>[]getDeclaredConstructors() 返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组类 。

代码如下:

/*
    @Author yangge
    @Date 2023/8/17 
    @Description  获取构造方法对象
Constructor<T> getConstructor(类<?>... parameterTypes) :根据参数类型返回对应的公共构造方法对象
Constructor<?>[] getConstructors() :返回所有公共构造方法对象,存入构造方法对象数组
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) : 根据参数类型返回对应的构造方               法对象(公有和私有均可)
Constructor<?>[]getDeclaredConstructors() : 返回所有的构造方法对象,存入构造方法对象数组(公有和私                 有均可)
​
        注意事项: int类型的字节码: int.class
                  Integer类型的字节码:Integer.class
*/
public class RefleDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        // 1. 获取Student字节码对象
        Class aClass = Class.forName("com.huayu.reflection.demo1.Student");
        // 2. 获取公有的无参构造
        Constructor cons1 = aClass.getConstructor();
        System.out.println("cons1 = " + cons1);
        // 3. 获取公有的满参构造
        Constructor cons2 = aClass.getConstructor(String.class, int.class, int.class, String.class);
        System.out.println("cons2 = " + cons2);
​
        System.out.println("------------------------------------");
        // 4. 获取所有的公共的构造方法
        Constructor[] conss = aClass.getConstructors();
        for (Constructor constructor : conss) {
            System.out.println(constructor);
        }
        System.out.println("------------------------------------");
        // 5. 获取2个参数的私有的构造方法
        Constructor dcons1 = aClass.getDeclaredConstructor(String.class, int.class);
        System.out.println("dcons1 = " + dcons1);
        System.out.println("------------------------------------");
​
        // 6. 获取所有的构造方法
        Constructor[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
    }
}

1.3.1.3 获取成员方法
MethodgetMethod(String name, 类<?>... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定声明的方法类对象。
Method[]getMethods() 返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法类对象,包括那些由类或接口和那些从超类和超接口继承的声明。
MethodgetDeclaredMethod (String name, 类<?>... parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定声明的方法类对象。
Method[]getDeclaredMethods 返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。

代码如下:

/*
    @Author yangge
    @Date 2023/8/17 
    @Description 获取方法对象
      Method  getMethod(String name, 类<?>... parameterTypes) : 根据方法名和参数类型获得对应的公共方法对象
      Method[]  getMethods() : 获取所有的公共的方法对象,存入数组
      Method getDeclaredMethod(String name, 类<?>... parameterTypes):根据方法名和参数类型获得对应的方法对象(公有和私有)
      Method[] getDeclaredMethods():获取所有的方法对象,存入数组(公有和私有)
*/
public class RefleDemo3 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        // 1. 获取Student的字节码对象
        Class aClass = Class.forName("com.huayu.reflection.demo1.Student");
        // 2. 分别获得getName() 和setName() 对象
        Method getName = aClass.getMethod("getName");
        Method setName = aClass.getMethod("setName", String.class);
        System.out.println("getName = " + getName);
        System.out.println("setName = " + setName);
        System.out.println("-----------------------------");
​
        //3. 获取所有的公有的方法对象 : aClass.getMethods() : 把父类Object中继承过来的也获取了
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("-----------------------------");
​
        // 4. 分别获取私有的getAge() , setAge() 对象
        Method getAge = aClass.getDeclaredMethod("getAge");
        Method setAge = aClass.getDeclaredMethod("setAge", int.class);
        System.out.println("getAge = " + getAge);
        System.out.println("setAge = " + setAge);
        System.out.println("-----------------------------");
        // 5. 获取所有的方法对象 :  无法获取父类Object中的方法,只能获取当前类中公有和私有方法
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
​
​
    }
}

总结:

getXFields() , getMethods() ,getConstructors(): 获取当前类以及父类中所有公共的方法
getXDeclaredFields() , getDeclaredMethods() ,getDeclaredConstructors(): 
      获取当前类中所有方法,包括共有和私有,但是无法获取从父类继承的 

1.3.1.4 获取类名
StringgetName(): 返回由 类对象表示的实体(类,接口,数组类,原始类型或空白)的名称,作为 String 。
StringgetSimpleName(): 返回源代码中给出的基础类的简单名称。

代码如下:

/*
    @Author yangge
    @Date 2023/8/17 
    @Description 获取类名
          String getName() : 获取类的全类型名称 : 包名 + 类名
          String getSimpleName() :  获取类的简单名称 :  类名
*/
public class RefleDemo4 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1. 获取Student类对象
        Class aClass = Class.forName("com.huayu.reflection.demo1.Student");
        //2. 获取aclass类对象的全类型名称
        String name = aClass.getName();
        System.out.println("name = " + name);//name = com.huayu.reflection.demo1.Student
        // 3. 获取aclass类对象的简单简单名称
        String simpleName = aClass.getSimpleName();
        System.out.println("simpleName = " + simpleName);//simpleName = Student
    }
}

1.3.2 Field成员变量相关方法
Objectget(Object obj) 获取obj对象的对应的field对象属性对应的属性值
intgetModifiers() 返回由该 Field对象表示的字段的Java语言修饰符,作为整数。
StringgetName() 返回由此 Field对象表示的字段的名称。
类<?>getType() 返回由此 Field对象对应属性的类型
voidset(Object obj, Object value) 将obj对象的对应的field对象属性值修改为:value
voidsetAccessible(boolean flag) 打开暴力访问开关

代码示例:

package com.huayu.reflection.demo2;
​
import com.huayu.reflection.demo1.Student;
​
import java.lang.reflect.Field;
import java.lang.reflect.Type;
​
/*
    @Author yangge
    @Date 2023/8/17 
    @Description
      int getModifiers 返回由该 Field对象表示的字段的Java语言修饰符,作为整数。
      String getName()  返回由此 Field对象表示的字段的名称。
      类<?>getType()  返回由此 Field对象对应属性的类型
      Object get(Object obj)  获取obj对象的对应的field对象属性对应的属性值
      void set(Object obj, Object value): 将obj对象的对应的field对象属性值修改为:value
      void setAccessible(boolean flag) :打开暴力访问开关
      
      注意事项:
          1. 只有getDeclaredField()才能访问私有属性,并且要打开暴力访问开关才能获取对应的私有属性值
*/
public class RefleDemo5 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        // 1. 获取Student.java文件
        Class aClass = Class.forName("com.huayu.reflection.demo1.Student");
        //2. 获得age属性对象
        Field ageField = aClass.getDeclaredField("age");
        // 3. 获取该属性对象的权限修饰符
        int modifiers = ageField.getModifiers();// private : 2 ,public : 1 ,protected : 4 , default : 0 , static : 8
        System.out.println("modifiers = " + modifiers);
​
        //4. 获取该属性对象的类型
        Class type = ageField.getType();
        System.out.println("type = " + type);//type = int
​
        //5. 获取该属性对象的名称
        String name = ageField.getName();
        System.out.println("name = " + name);//name = age
​
        // 6. 获取该属性对象的属性值
        ageField.setAccessible(true);
        int o = (int) ageField.get(new Student("张三", 25, 99, "华育大学"));
        System.out.println("o = " + o);
​
        // 7. 修改当前对象的,这个age属性的值为:30
        Student stu = new Student("张三", 25, 99, "华育大学");
        ageField.set(stu,30);
        int o1 = (int) ageField.get(stu);
        System.out.println("o1 = " + o1);
​
        // 8. 获取school属性对象
        Field schoolField = aClass.getDeclaredField("school");
        // 打开暴力访问开关
        schoolField.setAccessible(true);
        // 获取学生对象的私有属性school的值
        String o2 = (String) schoolField.get(new Student("张三", 25, 99, "华育大学"));
        System.out.println("o2 = " + o2);
    }
}

1.3.3 Constructor成员变量相关方法
intgetModifiers() 返回构造方法的权限修饰符
StringgetName() 以字符串形式返回此构造函数的名称。
intgetParameterCount() 返回构造方法对象中参数的个数。
Class<?>[]getParameterTypes() 按照顺序将构造方法的参数类型存入数组中并返回
voidsetAccessible(boolean flag) 打开暴力访问开关
TnewInstance(Object... initargs) 执行该构造方法对象并创建实例化对象

代码如下:

/*
    @Author yangge
    @Date 2023/8/20 
    @Description
     int getModifiers() 返回构造方法的权限修饰符的魔法值
     String getName()   以字符串形式返回此构造函数的名称。
     int getParameterCount() 返回构造方法对象中参数的个数。
     Class<?>[] getParameterTypes() 按照顺序将构造方法的参数类型存入数组中并返回
     void setAccessible(boolean flag) 打开暴力访问开关
     T newInstance(Object... initargs):执行该构造方法对象并创建实例化对象
*/
public class RefleDemo6 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 1. 获取Student.java类文件
        Class aClass = Class.forName("com.huayu.reflection.demo1.Student");
        //2. 获取构造方法对象
        Constructor constructor = aClass.getDeclaredConstructor(String.class, int.class, int.class, String.class);
        //3. 获取该构造方法的权限修饰符魔法值
        int modifiers = constructor.getModifiers();
        System.out.println("modifiers = " + modifiers);//modifiers = 1
        //4. 获取该构造方法的名称
        String name = constructor.getName();
        System.out.println("name = " + name);//name = com.huayu.reflection.demo1.Student
        //5. 获取该构造方法的形参的个数
        int parameterCount = constructor.getParameterCount();
        System.out.println("parameterCount = " + parameterCount);//parameterCount = 4
​
        //6. 获取该构造方法的形参的类型并按照顺序存入数组
        Class[] parameterTypes = constructor.getParameterTypes();
        for (Class parameterType : parameterTypes) {
            System.out.println(parameterType);
        }
        // 7. 执行该构造方法对象并创建实例化对象
        // 打开暴力访问开关
        constructor.setAccessible(true);
        Student stu = (Student) constructor.newInstance("zhangsan", 18, 95, "华育大学");
        System.out.println("stu = " + stu);
    }
}
​

1.3.4 Method成员变量相关方法
intgetModifiers() : 获取成员方法的权限修饰符魔法值
StringgetName() 返回由此 方法对象表示的方法的名称,作为 String 。
intgetParameterCount() 返回由此方法对象的参数个数。
类<?>[]getParameterTypes() 返回该方法对象的形式参数类型并按照顺序存入数组中。
类<?>getReturnType() 返回该方法对象的返回值类型
Objectinvoke(Object obj , Object ... args) 执行obj对象的该方法对象并使用实参args

代码示例:

/*
    @Author yangge
    @Date 2023/8/20 
    @Description
         int getModifiers() : 获取成员方法的权限修饰符魔法值
         String getName()返回由此 方法对象表示的方法的名称,作为 String 。
         int getParameterCount()返回由此方法对象的参数个数。
         类<?>[]getParameterTypes() 返回该方法对象的形式参数类型并按照顺序存入数组中。
         类<?> getReturnType() 返回该方法对象的返回值类型
         Object invoke(Object obj , Object ... args)  执行obj对象的该方法对象并使用实参args
*/
public class RefleDemo7 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1. 获取Student.java文件
        Class aClass = Class.forName("com.huayu.reflection.demo1.Student");
        //2. 获取equals方法对象
        Method setAgeMethod = aClass.getDeclaredMethod("setAge", int.class);
​
        //3. 获取setAgeMethod的权限修饰符魔法值
        int modifiers = setAgeMethod.getModifiers();
        System.out.println("modifiers = " + modifiers);
        //4. 获取setAgeMethod方法对象的返回值类型
        Class<?> returnType = setAgeMethod.getReturnType();
        System.out.println("returnType = " + returnType.getName());
​
        //5. 获取方法名
        String name = setAgeMethod.getName();
        System.out.println("name = " + name);//name = setAge
        //6. 获取参数个数
        int parameterCount = setAgeMethod.getParameterCount();
        System.out.println("parameterCount = " + parameterCount);
​
        // 7. 获取参数类型并按照顺序存入数组
        Class<?>[] parameterTypes = setAgeMethod.getParameterTypes();
        for (Class<?> parameterType : parameterTypes) {
            System.out.println(parameterType.getName());
        }
​
        //8. 执行该方法
        // 打开暴力访问开关
        setAgeMethod.setAccessible(true);
        Student stu = new Student();
        setAgeMethod.invoke(stu, 20);
​
        // 获取stu对象的age值
        Method getAgeMethod = aClass.getDeclaredMethod("getAge");
        getAgeMethod.setAccessible(true);
        int invoke = (int) getAgeMethod.invoke(stu);
        System.out.println("invoke = " + invoke);
        
    }
}

1.5 【案例】写一个框架

1.5.1 需求

写一个框架,不能改变类的任何代码的前提下,可以帮我们创建任意类的对象,并执行其中任意方法

1.5.2 实现
  • 配置文件

  • 反射

1.5.3 步骤
  • 将需要创建的对象的全类名和需要执行的方法定义在配置文件中

  • 在程序加载读取配置文件

  • 使用反射加载类文件进内存

  • 创建对象

  • 执行方法

1.5.4 创建User类
/*
    @Author yangge
    @Date 2023/8/20 
    @Description 定义用户类实体类
*/
public class User {
    private String name;
    private int age;
    private String address;
​
    public User() {
    }
​
    public User(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
​
    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;
    }
​
    public String getAddress() {
        return address;
    }
​
    public void setAddress(String address) {
        this.address = address;
    }
​
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
​
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
​
        User user = (User) o;
​
        if (age != user.age) return false;
        if (name != null ? !name.equals(user.name) : user.name != null) return false;
        return address != null ? address.equals(user.address) : user.address == null;
    }
​
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        result = 31 * result + (address != null ? address.hashCode() : 0);
        return result;
    }
}

1.5.5 创建pro.properties
className=com.huayu.reflection.demo2.User
methodName=toString

注意:要将pro.properties文件放置在resources包下,并将resources包设置为项目资源包

1.5.6 写代码
/*
    @Author yangge
    @Date 2023/8/20 
    @Description 读取配置文件pro.properties创建User对象并执行toString方法
*/
public class RefleDemo8 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        // 需求:使用类加载器读取配置文件pro.properties中的配置信息并存入Properties集合中
        //1. 获得当前类文件的类加载器并读取pro.properties文件中内容到流中
        ClassLoader classLoader = RefleDemo8.class.getClassLoader();
        InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
​
        //2. 将resourceAsStream流中的内容存入到Properties集合中
        Properties properties = new Properties();
        properties.load(resourceAsStream);
​
        //3. 根据全类名获取类文件对象
        String className = (String) properties.get("className");
        Class aClass = Class.forName(className);
​
        //4. 根据类文件来创建实例化对象
        User user = (User) aClass.newInstance();
        user.setName("jack");
​
        // 5. 获取要执行的方法名,根据要执行的方法名获取方法对象并调用
        String methodName = (String) properties.get("methodName");
        Method declaredMethod = aClass.getDeclaredMethod(methodName);
​
        //6. 执行该user对象中的declaredMethod方法
        System.out.println(declaredMethod.invoke(user));
    }
}

1.6 自定义一个JSON生成Json串

1.6.1 创建User类
/*
    @Author yangge
    @Date 2023/8/20 
    @Description 定义用户类实体类
*/
public class User {
    private String name;
    private int age;
    private String address;
​
    public User() {
    }
​
    public User(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
​
    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;
    }
​
    public String getAddress() {
        return address;
    }
​
    public void setAddress(String address) {
        this.address = address;
    }
​
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
​
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
​
        User user = (User) o;
​
        if (age != user.age) return false;
        if (name != null ? !name.equals(user.name) : user.name != null) return false;
        return address != null ? address.equals(user.address) : user.address == null;
    }
​
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        result = 31 * result + (address != null ? address.hashCode() : 0);
        return result;
    }
}

1.6.2 创建JSON类
/*
    @Author yangge
    @Date 2023/8/20 
    @Description 把简单对象转成json字符串
*/
public class RefleDemo9 {
    private RefleDemo9() {
    }
    // 将简单对象User user转成json字符串
    public static String toJsonObject(User user) throws IllegalAccessException { // user = {"name":"jack","age":18}
​
        StringBuilder sb = new StringBuilder();
        sb.append("{");
​
        // 1. 获取user的字节码对象
        Class aClass = user.getClass();
        // 2. 获取aClass中所有的属性对象
        Field[] declaredFields = aClass.getDeclaredFields();
        // 3. 遍历declaredFields 获取每一个field对象
        for (Field declaredField : declaredFields) {
            // 4. 获取declaredField 名称作为key
            String fieldName = declaredField.getName();
            // 5. 获取declaredField 属性值作为:value
            declaredField.setAccessible(true);
            Object fieldValue = declaredField.get(user);
            if (fieldValue instanceof String || fieldValue instanceof StringBuffer || fieldValue instanceof StringBuilder){
                fieldValue = "\""+ fieldValue+"\"";
            }
​
            // 6. 将键值对拼接到sb中
            sb.append("\""+fieldName+"\"" +":"+fieldValue+",");
        }
​
        // 将最后的 , 去掉
        sb.replace(sb.length()-1, sb.length(), "");
        sb.append("}");
​
        return sb.toString();
    }
​
​
    public static void main(String[] args) throws IllegalAccessException {
        User user = new User("jack", 18, "武汉");
        String s = toJsonObject(user);
        System.out.println("s = " + s);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值