java反射实操案例

一、反射介绍:

Reflection(反射)可以在运行时获取一个类的所有信息,并且可以操作类的字段、方法和构造器等。

二、常用反射操作:

1、获取类对应的字节码对象(后缀为.class):

(1)类对象.getClass()

说明:追根溯源,使用的是Object类的getClass()方法,因为所有类都继承Object类,所以下面的子类也可以使用getClass()方法。

Student s = new Student();
Class cla = s.getClass();

(2)类名.class

说明:此处调用的是该类的class属性,获取该类对应的Class字节码对象。

Class cla = Student.class;

(3)Class.forname("类的路径")

说明:使用java自带的Class类中的forName("类的路径")静态方法。

Class cla = Class.forName("类的路径");

总结:反射机制的设计是为了灵活获取类,进而得到类的对象

。第一种方法对象已经存在,此时反射的价值不大。

第二种方法导入类的包,依赖性过强,耦合度高,没导报错。

第三种方法比较常用,安全且性能好。

测试以上三种方法:

package reflectTest;
/**
 * @author:tengsen
 * @create: 2022-10-08 21:19
 * @Description:
 */
public class TestReflect {
    public static void main(String[] args) throws ClassNotFoundException {

        //通过Student类拿到字节码对象
        Class cla1 = new Student().getClass();

        //通过类的class属性拿到字节码对象
        Class cla2 = Student.class;

        //根据类的路径拿到字节码对象
        Class cla3 = Class.forName("reflectTest.Student");

        System.out.println("cla1:"+cla1);
        System.out.println("cla2:"+cla2);
        System.out.println("cla3:"+cla3);
    }
}

 运行测试结果:

 java反射实操案例_第1张图片

2、获取了类的Class对象后,可通过该字节码对象获取该类的多种信息

 (1)测试用的学生类:

package reflectTest;

/**
 * @author:tengsen
 * @create: 2022-10-08 15:57
 * @Description:
 */
public class Student {
    private String id;
    private String name;
    public int age;
    public String gender;
    public double waterFee;
    public Student() {
    }

    public Student(String id, String name, int age, String gender) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        waterFee=0;
    }

    public void study(){
        System.out.println("学习ing");
    }

    public boolean rechargeWaterBill(double money){
        waterFee+=money;
        System.out.println("成功充值"+money+"元,水费余额:"+waterFee+"元");
        return true;
    }

    public String getId() {
        return id;
    }

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

    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 getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public double getWaterFee() {
        return waterFee;
    }

    public void setWaterFee(double waterFee) {
        this.waterFee = waterFee;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", waterFee=" + waterFee +
                '}';
    }
}

 (2)得到类属性的方法:

1>字节码对象.getFields()。说明:得到公有属性。

2>字节码对象.getDeclareFields()。说明:得到所有属性,无论是公有还是私有。

测试代码:

package reflectTest;

import java.lang.reflect.Field;

/**
 * @author:tengsen
 * @create: 2022-10-08 21:38
 * @Description:
 */
public class TestReflect2 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class cla = Class.forName("reflectTest.Student");

        //getFields()得到公有属性
        Field[] fields1 = cla.getFields();
        System.out.println("getFields()的效果:");
        for (Field field:fields1){
            System.out.println("属性名:"+field.getName());
            System.out.println("属性类型:"+field.getType());
            System.out.println();
        }
        
        System.out.println();
        
        //getDeclaredFields()得到所有属性,无论公有还是私有
        Field[] fields2 = cla.getDeclaredFields();
        System.out.println("getDeclareFields()的效果:");
        for(Field field:fields2){
            System.out.println("属性名:"+field.getName());
            System.out.println("属性类型:"+field.getType());
            System.out.println();
        }
    }
}

 ​​​​​​运行测试结果:

 java反射实操案例_第2张图片

 (3)得到类方法的方法:

 字节码对象.getMethods()。说明:得到该字节码对象对应类的所有方法。

测试代码:

package reflectTest;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author:tengsen
 * @create: 2022-10-09 12:07
 * @Description:
 */
public class TestReflect3 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class cla = Class.forName("reflectTest.Student");
        Method[] methods = cla.getMethods();//获取字节码对象对应类的所有方法,存于数组集合中
        for (Method method: methods){

            System.out.println("该方法对象详情为:");
            System.out.println(method);

            System.out.print("方法名为:");
            System.out.println(method.getName());

            Class[] parameterTypes = method.getParameterTypes();//获取该方法的所有参数类型的数组集合
            System.out.print("该方法的参数类型的数组集合为:");
            System.out.println(Arrays.toString(parameterTypes));

            System.out.println();
        }
    }
}

 运行结果截图:

java反射实操案例_第3张图片

 (4)通过获取字节码,进而创建对象:

1>字节码对象.newInstance()。说明:执行无参构造创建对象。
2>字节码对象.newInstance(实参列表)。说明:执行有参构造创建对象。

测试代码:

package reflectTest;

import java.lang.reflect.Constructor;

/**
 * @author:tengsen
 * @create: 2022-10-09 14:47
 * @Description:
 */
public class TestReflect4 {
    public static void main(String[] args) throws Exception {
        Class cla = Class.forName("reflectTest.Student");

        //如果已知构造器参数类型构成,可直接通过字节码对象获取对应构造器
        Constructor cons = cla.getConstructor(String.class,String.class,int.class,String.class);

        //有参构造
        Student student1 = (Student) cons.newInstance("006","古草",21,"男");
        System.out.println(student1);

        //通过字节码对象,直接反射获取无参构造的类实例
        Student student2 = (Student) cla.newInstance();
        System.out.println(student2);
    }
}

  运行结果截图:

java反射实操案例_第4张图片

 (5)通过字节码对象获取包名、类名:

1>字节码对象.getPackage().getName()。说明:获取包名。
2>字节码对象.getName()。说明:获取完整类名。
3>字节码对象.getSimpleName()。说明:获取类名。

测试代码:


package reflectTest;

/**
 * @author:tengsen
 * @create: 2022-10-09 15:01
 * @Description:
 */
public class TestReflect5 {
    public static void main(String[] args) throws ClassNotFoundException {
        Class cla = Class.forName("reflectTest.Student");

        //获取包名
        System.out.println("Student类的包名:"+cla.getPackage());

        //获取完整类名
        System.out.println("Student类的完整类名:"+cla.getName());

        //获取简洁类名
        System.out.println("Student类的简洁类名:"+cla.getSimpleName());
    }
}

   运行结果截图:

 java反射实操案例_第5张图片

你可能感兴趣的:(JAVA大类,java,开发语言,jvm)