java反射机制的基础应用讲解

Java反射API实例解析:创建对象、调用方法与访问成员变量,
该文通过一个Java代码示例详细解释了如何使用反射API来获取类信息、创建对象、调用方法以及访问和修改成员变量。文中还包含了对关键代码段的注解,展示了如何利用反射调用构造函数、方法以及访问私有成员。此外,还提供了几个基础实例,演示了获取类对象、成员变量、成员方法和构造方法的不同方法。

综合实例 

下面是一个使用Java反射的示例代码,该代码演示了如何使用反射API获取一个类的信息、创建对象、调用方法和访问成员变量等:

// 定义一个Person类
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

// 使用反射API获取Person类的信息、创建对象、调用方法和访问成员变量等
public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // 获取Person类的Class对象
        Class<Person> clazz = Person.class;

        // 创建Person对象
        Constructor<Person> constructor = clazz.getConstructor(String.class, int.class);
        Person person = constructor.newInstance("张三", 18);

        // 调用getName方法获取姓名
        Method getNameMethod = clazz.getMethod("getName");
        String name = (String) getNameMethod.invoke(person);
        System.out.println("姓名:" + name);

        // 访问age成员变量并修改其值
        Field ageField = clazz.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.setInt(person, 20);

        // 调用getAge方法获取年龄
        Method getAgeMethod = clazz.getMethod("getAge");
        int age = (int) getAgeMethod.invoke(person);
        System.out.println("年龄:" + age);
    }
}

在该示例代码中,我们首先定义了一个Person类,然后使用反射API获取该类的Class对象,并通过该对象创建了一个Person对象。接着,我们使用反射API获取Person类的getName方法和getAge方法,并通过这些方法获取了该对象的姓名和年龄信息。最后,我们使用反射API获取Person类的age成员变量,并修改了其值。

注解1:

// 创建Person对象
Constructor<Person> constructor = clazz.getConstructor(String.class, int.class);
Person person = constructor.newInstance("张三", 18);

这段代码演示了如何使用Java反射机制来调用类的构造方法创建对象。

首先,代码获取了Person类的Class对象,即Class<Person> clazz = Person.class;

接着,代码使用getConstructor()方法获取Person类的指定构造方法,即constructor = clazz.getConstructor(String.class, int.class);。这个构造方法接收两个参数,一个String类型的name和一个int类型的age。

然后,代码使用构造方法对象的newInstance()方法创建Person对象,并传入name和age参数,即Person person = constructor.newInstance("张三", 18);

最终,代码得到了一个Person对象,可以对其进行操作。

注解2:

 // 调用getName方法获取姓名
 Method getNameMethod = clazz.getMethod("getName");
 String name = (String) getNameMethod.invoke(person);
 System.out.println("姓名:" + name);

这段代码演示了如何使用Java反射机制来调用类的方法。

首先,代码获取了Person类的Class对象,即Class<Person> clazz = Person.class;

接着,代码使用getMethod()方法获取Person类的指定方法对象,即getNameMethod = clazz.getMethod("getName");。这个方法不需要传入参数,返回类型为String。

然后,代码使用invoke()方法调用Person对象的getName方法,即String name = (String) getNameMethod.invoke(person);invoke()方法的第一个参数为要调用方法的对象,这里是person对象;第二个参数为可选参数,如果getName方法需要传入参数,则可以在这里传入。

最后,代码将获取到的name值输出到控制台,即System.out.println("姓名:" + name);

注解3:

// 访问age成员变量并修改其值
Field ageField = clazz.getDeclaredField("age");
ageField.setAccessible(true);
ageField.setInt(person, 20);

这段代码演示了如何使用Java反射机制来访问和修改类的成员变量。

首先,代码获取了Person类的Class对象,即Class<Person> clazz = Person.class;

接着,代码使用getDeclaredField()方法获取Person类的指定成员变量对象,即Field ageField = clazz.getDeclaredField("age");。这个方法需要传入一个字符串参数,即成员变量的名称。

然后,代码调用setAccessible()方法将成员变量的访问权限设为可访问,即ageField.setAccessible(true);。这是因为age是一个private成员变量,必须设置为可访问才能修改它的值。

接下来,代码使用setInt()方法修改person对象的age成员变量的值,即ageField.setInt(person, 20);setInt()方法的第一个参数为要修改的对象,这里是person对象;第二个参数为要设置的值,这里是20。

最后,代码修改后的person对象的age值就被成功地设置为了20。

注解4:

// 调用getAge方法获取年龄
Method getAgeMethod = clazz.getMethod("getAge");
int age = (int) getAgeMethod.invoke(person);
System.out.println("年龄:" + age);

这段代码演示了如何使用Java反射机制来调用类的方法。

首先,代码获取了Person类的Class对象,即Class<Person> clazz = Person.class;

接着,代码使用getMethod()方法获取Person类的指定方法对象,即Method getAgeMethod = clazz.getMethod("getAge");。这个方法需要传入一个字符串参数,即要调用的方法的名称。

然后,代码使用invoke()方法调用getAge方法,即int age = (int) getAgeMethod.invoke(person);invoke()方法的第一个参数为要调用的对象,这里是person对象;如果被调用的方法有参数,则后续参数需要按照方法参数列表传入。invoke()方法的返回值为被调用方法的返回值,需要进行强制类型转换。

最后,代码调用getAge方法获取到了person对象的年龄,并将其输出。

 基础实例1 获取类对象(三种方式)

/*本类用于反射的测试*/
public class TestReflect {
    //1.可以创建程序的入口函数main()--此处不用
    //2.通过单元测试方法,获取目标类Student对应的字节码对象
    @Test
    public void getClazz() throws ClassNotFoundException {
        //练习获取字节码对象的3种方式
        Class<?> clazz1 = Class.forName("com.review.Student");
        Class<?> clazz2 = Student.class;
        Class<?> clazz3 = new Student().getClass();
 
        //打印的是Student类对应的字节码对象
        System.out.println(clazz1);//class com.reflection.Student
        //获取Student类对应的字节码对象clazz1的名字
        System.out.println(clazz1.getName());//com.reflection.Student
        //通过Student类对应的字节码对象,获取Student类的类名
        System.out.println(clazz1.getSimpleName());
        //通过Student类对应的字节码对象,获取Student类对应的包对象
        System.out.println(clazz1.getPackage());
        //通过Student类对应的字节码对象,先获取Student类对应的包对象,再获取这个包对象的名字
        System.out.println(clazz1.getPackage().getName());
    }
}

基础实例2 获取成员变量(Class.forName)

/**本类用来测试反射*/
public class TestReflect {
	//3.通过单元测试方法练习引用类型数组的定义与遍历
    @Test
    public void getStu() {
        //1.创建Student类的3个对象
        Student s1 = new Student("张三", 3);
        Student s2 = new Student("李四", 4);
        Student s3 = new Student("王五", 5);
        //2.创建数组将刚刚的3个对象存入数组中
        Student[] s = {s1, s2, s3};
        //3.直接打印数组,查看数组中的元素
        System.out.println(Arrays.toString(s));
        //4.遍历学生数组,拿到每一个学生对象,做进一步的操作
        for (Student stu : s) {
            //System.out.println(stu);
            stu.play();//通过遍历到的对象,执行play()
            System.out.println(stu.age);//通过遍历到的对象,打印age属性
        }
    }
 
	//4.通过单元测试方法,获取Student类中的成员变量
    @Test
    public void getFie() throws ClassNotFoundException {
        //1.获取Student类对应的字节码对象
        Class<?> clazz = Class.forName("com.review.Student");
        //2.通过Student类对应的字节码对象获取Student类中的成员变量们
        Field[] fs = clazz.getFields();
        //3.遍历数组,获取Student类中的每个成员变量的具体信息
        /*注意!目前成员变量的修饰符必须是public的才能获取到*/
        for(Field f : fs){
            System.out.println(f.getName());//通过本轮循环到的字段对象获取字段名
            System.out.println(f.getType());//通过本轮循环到的字段对象获取字段的类型
        }
 
    }
}

基础实例3  通过字节码对象获取类的成员方法(Class.forName)

/**本类用来测试反射*/
public class TestReflect {
    //5.通过单元测试方法,获取Student类中的成员方法
    @Test
    public void getFunction() {
        //1.获取Student类对应的字节码对象
        Class<?> clazz = Class.forName("com.review.Student");
        //2.通过Student类对应的字节码对象获取Student类中的成员方法们
        Method[] ms = clazz.getMethods();
        //3.通过高效for循环遍历数组,拿到每一个方法对象
        for (Method m : ms) {
            System.out.println(m);//直接打印遍历到的方法对象
            System.out.println(m.getName());//通过方法对象获取方法名
            Class<?>[] pt = m.getParameterTypes();//通过方法对象获取方法所有参数的数组
            System.out.println(Arrays.toString(pt));//打印方法参数的数组
        }
 
    }
}

基础实例4   通过字节码对象获取类的构造方法(Class.forName) 

/**本类用来测试反射*/
public class TestReflect {
    //6.通过单元测试方法,获取Student类中的构造方法
    @Test
    public void getCons() {
        //1.获取字节码对象
        Class<?> clazz = Class.forName("com.review.Student");
        //2.通过字节码对象获取目标类Student的构造方法们
        Constructor<?>[] cs = clazz.getConstructors();
        //3.通过高效for循环遍历数组
        for(Constructor c : cs){
            System.out.println(c.getName());//打印本轮遍历到的构造方法的名字
            Class[] pt = c.getParameterTypes();//通过本轮遍历到的构造函数对象获取构造函数的参数类型
            System.out.println(Arrays.toString(pt));//打印参数类型
        }
    }
}

基础实例5  创建对象(Class.forName) 

/**本类用来测试反射*/
public class TestReflect {
//7.通过单元测试方法,创建Student目标类的对象
    @Test
    public void getObject() throws Exception {
        //1.获取字节码对象
        Class<?> clazz = Class.forName("com.review.Student");
        
        //2.通过反射技术创建目标类的对象,注意抛出异常
        /*反射创建对象方案1:
            使用 目标类 的 无参构造 创建对象
        */
        Object o = clazz.newInstance();
        System.out.println(o);//这一步已经获取到了对象Student{name='null', age=0}
 
        /*反射创建对象方案2:
            使用 目标类 的 全参构造 创建对象
        * 思路:
        * 1.先获取指定的构造函数对象,注意需要指定构造函数的参数,传入的是.class字节码对象
        * 2.通过刚刚获取到的构造函数对象创建Student目标类的对象,并且给对象的属性赋值
        * */
 
        //3.获取目标类中指定的全参构造
        Constructor<?> c = clazz.getConstructor(String.class, int.class);
        //System.out.println(c);
 
        //4.通过获取到的构造函数:创建对象 + 给对象的属性赋值
        Object o2 = c.newInstance("赵六", 6);
        System.out.println(o2);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值