Java中反射的概述以及基础用法

本文详细介绍了Java反射机制,包括如何通过反射获取类、构造器、成员变量和方法,并进行动态调用。示例代码展示了如何根据配置文件动态创建对象并执行方法,以及如何通过反射对成员变量赋值和获取值。此外,还讨论了反射在处理配置文件、对象创建和方法调用中的实用性。
摘要由CSDN通过智能技术生成

Java的反射机制
    是在运行状态中, 对于任意一个类, 能够知道这个类的所有属性和方法
    对于任意一个对象, 都能够调用它的任意属性和方法
    这种动态获取信息以及动态调用对象方法的功能, 称为Java语言的反射机制
     
简单理解
    利用反射可以无视修饰符, 获取类里面所有属性和方法
    动态获取配置文件中的信息, 然后创建对象, 调用方法

反射初体验案例场景?
        有多个类, 需要切换的创建不同类的对象, 并调用其中的方法
        提供配置文件, 只需要修改配置文件, 通过反射完成需求

下面是代码演示

    public class Test {
        public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
            /*
                提供配置文件prop.properties, 将配置文件的内容加载到Properties
             */
            InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("prop.properties");
            Properties prop = new Properties();
            prop.load(is);
            // 释放资源
            is.close();

            /*
                反射初体验
             */
            // 通过静态方法获取Class对象
            Class clazz = Class.forName(prop.getProperty("className"));
            // 通过反射获取构造器
            Constructor constructor = clazz.getConstructor();
            // 通过构造器创建对象
            Object o = constructor.newInstance();
            // 通过反射获取对象方法
            Method method = clazz.getMethod(prop.getProperty("methodName"));
            // 运行方法
            method.invoke(o);
        }
    }

相关文件:
    Person.java
    Studnet.java
    Teacher.java
    Worker.java
    prop.properties

反射_获取Class对象

之前如果调用类中的方法?
    new该类对象, 通过对象调用方法
    
反射调用类中的方法?
    是利用Class对象来获取对象, 并调用方法的

三种方式获取Class对象(三个阶段):
    1. 源代码阶段(还没有加载到内存中) -> Class类的静态方法 forName("全类名");
    2. Class对象阶段(已经加载到内存) -> 类名.class
    3. Runtime运行阶段(手动new对象时) -> 对象.getClass()

代码演示

    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            // 1.源代码阶段(还没有加载到内存中) -> Class类的静态方法 forName("全类名");
            Class clazz1 = Class.forName("com.itheima05_reflect_getClass.Student");
            System.out.println(clazz1); //class com.itheima05_reflect_getClass.Student

            // 2.Class对象阶段(已经加载到内存) -> 类名.class
            Class clazz2 = Student.class;
            System.out.println(clazz2); //class com.itheima05_reflect_getClass.Student

            // 3.Runtime运行阶段(手动new对象时) -> 对象.getClass()
            Student stu = new Student();
            Class clazz3 = stu.getClass();
            System.out.println(clazz3); //class com.itheima05_reflect_getClass.Student

            // 三种方式获取的Class对象是一个对象
            System.out.println(clazz1 == clazz2); //true
            System.out.println(clazz2 == clazz3); //true
        }
    }

    package com.itheima05_reflect_getClass;
    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 +
                    '}';
        }

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

在这里推荐使用第二种方式 更为简单 通过类名.class

反射获取构造方法

反射获取构造方法并利用构造方法创建对象

通过反射获取构造方法做什么? 
    创建对象
        
Constructor类中用于创建对象的方法?
    T newInstance(属性1.class,属性2.class..); 根据指定的构造方法创建对象

package 反射;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/* 1.Constructor<?>[] getConstructors(); 返回所有构造方法对象的数组(仅公共的)
    2.Constructor<?>[] getDeclaredConstructors(); 返回所有构造方法对象的数组(包含私有的)
    3.Constructor<T> getConstructor(属性1.class,属性2.class..); 返回单个构造方法对象(仅公共的)
    4.Constructor<T> getDeclaredConstructor(属性1.class,属性2.class..); 返回单个构造方法对象(包含私有的)*/
public class Test2 {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //创建类对象
        Class<Student2> clazz = Student2.class;
        //获取空参构造方法对象
        //因为Class类里面有newInstance方法 所以这里可以直接使用 不需要创建构造器对象
        Student2 student2 = clazz.newInstance();//空参构造创建对象
        System.out.println(student2);
        //获取公共或者私有的构造方法对象  ()里面写的是参数.class
        Constructor<Student2> declaredConstructor = clazz.getDeclaredConstructor(String.class);//返回单个构造方法对象(包含私有的)
        // 如果构造方法是私有的 就临时取消检查  暴力反射
        declaredConstructor.setAccessible(true);
        //创建对象并赋值
        Student2 stu = declaredConstructor.newInstance("白岳明");
        System.out.println(stu);

    }
}

这里选用了其中的两种方法 剩下两个返回数组的遍历数组进行操作就可以了  JavaBean在这里就不上传了

反射 获取Field赋值和获取值

反射对成员变量(Field对象)赋值和获取值
    void set(Object o,Object value); 赋值 -> 给指定对象的成员变量赋指
    Object get(Object o); 获取值 -> 获取指定对象的Field值    

package 反射;
/*反射获取成员变量(Field对象)
    1.Field[] getFields(); 获取所有成员变量对象数组(仅公共的)
    2.Field[] getDeclaredFields(); 获取所有成员变量对象数组(包含私有的)
    3.Field getField(真实存在的属性); 获取单个成员变量对象(仅公共的)
    4.Field getDeclaredField(真实存在的属性); 获取单个成员变量对象(私有的)*/
import java.lang.reflect.Field;

public class Test3 {
    public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        //创建类对象
        Class<Student3> clazz = Student3.class;
        //获取单个成员变量对象  ()里写变量的名字 不是类型
        Field nameField = clazz.getField("name");
        //空参构造创建对象
        Student3 student1 = clazz.newInstance();
        //设置成员变量的值  ()里面写给哪个对象设置  以及  设置的内容
        nameField.set(student1,"baiyueming");
        //打印成员变量的值
        System.out.println(nameField.get(student1));

        //获取单个成员变量对象 公有和私有的都可以
        //获得单个成员变量对象 ()里写变量的名字 不是类型
        Field moneyField = clazz.getDeclaredField("money");
        //由于是私有的 所以要取消临时检查
        moneyField.setAccessible(true);
        //设置成员变量的值  ()里面写给哪个对象设置  以及  设置的内容
        moneyField.set(student1,123);
        System.out.println(moneyField.get(student1));
    }
}

同理 JavaBean在这里就不写了

反射获取Method对象运行方法

package 反射;
/*反射获取成员方法(Method对象)
    1.Method[] getMethods(); 返回所有公共成员方法(不包含私有,包含继承的)
    2.Method[] getDeclaredMethods(); 返回所有成员方法(包含私有的,不含包继承的)
    3.Method getMethod("方法名",属性.class..); 返回指定公共成员方法
    4.Method getDeclaredMethod("方法名",属性.class..); 返回指定私有成员方法*/
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test4 {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //创建类对象
        Class<Student4> clazz = Student4.class;
        //获取指定所有成员方法对象  ()里面写方法名 以及方法需要的参数类型
        Method method = clazz.getDeclaredMethod("function4",String.class);
        //由于是私有的 所以要取消临时检验
        method.setAccessible(true);
        //通过空参构造创建对象
        Student4 student4 = clazz.newInstance();
        //由于有返回值所以需要接受一下
        Object name = method.invoke(student4, "白岳明");
        //打印结果
        System.out.println(name);
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值