反射阶段学习及结合案例

一、反射介绍

反射是在[运行过程]中,对于任意一个类,都能够动态的获取该类中的成员

问题1:为什么可以获取?

因为类的字节码文件中,包含类的所有信息,而且字节码文件内存中就一份

问题2:成员都包括什么?

包括成员变量、构造方法、成员方法(包含从父类继承的方法)

问题3:应用场景?

java框架底层原理

二、字节码对象的3种获取方式

1、类名.class属性

***.class是所有对象中的静态属性,作为锁对象使用比较多

每个对象都有对象锁,如果类中有方法是静态的且需要进行Synchronized修饰,那么该方法的锁对象就是该类的字节码文件***

2 、对象名.getClass()方法

对象创建好的情况下使用

3、Class.forName(参数:全名称限定类名)方法

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;
    }

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

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

public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.Class类中的静态方法forName("全类名")
            //全类名:包名 + 类名
        Class clazz = Class.forName("com.liogng.myreflect.Student");
        System.out.println(clazz);

        //2.通过class属性来获取
        Class clazz2 = Student.class;
        System.out.println(clazz2);

        //3.利用对象的getClass方法来获取class对象
        //getClass方法是定义在Object类中.
        Student s = new Student();
        Class clazz3 = s.getClass();
        System.out.println(clazz3);

        System.out.println(clazz == clazz2);//true
        System.out.println(clazz2 == clazz3);//true
        //字节码对象就一份,所以都为true
    }
}

三、反射操作构造方法

获取构造方法后:可以进行创建对象

1、获取构造方法

//返回所有公共构造方法对象的数组
Constructor<?>[] getConstructors()Constructor<?>[] 
//返回所有构造方法对象的数组
getDeclaredConstructors()
//返回单个公共构造方法对象Constructor<T> 
getConstructor(Class<?>...parameterTypes)
//返回单个构造方法对象
getDeclaredConstructor(Class<?>... parameterTypes)

2、通过构造方法创建对象

//根据指定的构造方法创建对象
T newInstance(Object...initargs)
//设置为true,表示取消访问检查,主要当通暴力反射获取属性名称对象时候,
//为该属性赋值之前需要取消权限
setAccessible(boolean flag)

示例代码:

package com.ligong.test;

import java.lang.reflect.Constructor;

public class ReflectTest1 {
    /*
        需求: 通过反射技术, 创建Student类的对象, 通过带参构造方法创建
     */
    public static void main(String[] args) throws Exception {

        // 1. 获取Student类的字节码对象
        Class clazz = Class.forName("com.itheima.domain.Student");

        // 2. 获取内部构造方法对象(带参构造方法)
        Constructor con = clazz.getConstructor(String.class, int.class);

        // 3. 根据构造方法对象, 创建实例(Student对象)
        Object o = con.newInstance("张三", 23);

        System.out.println(o);

    }
}

四、反射操作成员变量

成员变量可以进行赋值/获取操作

1、获取成员变量

返回所有公共成员变量对象的数组
Field[] getFields()

返回所有成员变量对象的数组
getDeclaredFields()

返回单个公共成员变量对象
Field getField(String name)

返回单个成员变量对象
Field getDeclaredField(String name)

2、通过属性名称对象调用以下方法

// 第一个参数,是要在哪个对象中设置,第二给该属性对象实参
void set(Object obj, Object value)赋值

Object get(Object obj)获取值
暴力反射
  • 暴力反射需要调用 setAccessible , 权限设置为 true, 才可以操作
  • 不建议的使用方式

五、反射操作成员方法

1、获取成员方法

//返回所有公共成员方法对象的数组,包括继承的
Method[] getMethods()
//返回所有成员方法对象的数组,不包括继承的
Method[] getDeclaredMethods()
//返回单个公共成员方法对象
Method getMethod(String name, Class<?>... parameterTypes)
//返回单个成员方法对象
Method getDeclaredMethod(String name, Class<?>...parameterTypes)

2、运行方法:方法对象调用

Object invoke(Object obj, Object... args)运行方法

参数一: 用obj对象调用该方法
参数二: 调用方法的传递的参数(如果没有就不写)
返回值: 方法的返回值(如果没有就不写)

3、案例:

需求 : 请向一个泛型为 Integer 的集合, 添加一个 String 字符串
思路 : Java 中的泛型是假的, 只在编译的时候有效

package com.ligong.test;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class ReflectTest4 {
    /*
        需求: 请向一个泛型为 Integer 的集合,  添加一个 String 字符串

               普及: Java中的泛型是假的, 只在编译期间有效, 运行的时候, 就没有泛型了.

                        运行的时候: 肯定过了编译阶段, 肯定有字节码对象.

               结论 : Java中的泛型, 到运行期间, 就会被擦除掉.
     */
    public static void main(String[] args) throws Exception {
        ArrayList<Integer> list = new ArrayList<>();

        Class listClass = list.getClass();

        // 集合中, add方法的, 成员方法对象
        Method addMethod = listClass.getMethod("add", Object.class);

        // 调用成员方法
        addMethod.invoke(list, "abc");

        System.out.println(list);

    }
}

六、反射使用场景:

1、制作框架
2、什么是框架?,通过框架可以快速开发

案例:

需求:
设计一个定时器框架, 用户只需要传入配置文件位置, 就可以开启定时任务。

任务一类

public class MondayTask implements Runnable {
    @Override
    public void run() {
        System.out.println("星期一, 加油!  在学习java o(╥﹏╥)o");
        
    }
}

任务二类

public class TuesdayTask implements Runnable{
    @Override
    public void run() {
        System.out.println("星期二, 学习计算机网络~~");
    }
}

任务三类

public class Wednesday implements Runnable{
    @Override
    public void run() {
        System.out.println("星期三,在学习mySQL.... o(╥﹏╥)o");
    }
}

线程池逻辑代码:

package com.ligong.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TaskUtils {
    public static void submitTask(String fileName) {
        try {
            ScheduledExecutorService pool = Executors.newScheduledThreadPool(10);

            Properties prop = new Properties();
            prop.load(new FileInputStream(fileName));

            String classname = prop.getProperty("classname");

            Class<?> clazz = Class.forName(classname);
            Runnable task = (Runnable) clazz.newInstance();

            pool.scheduleAtFixedRate(task,
                    2,
                    2,
                    TimeUnit.SECONDS);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("我的代码不可能有异常!!!");
        }
    }

}

程序入口:

public class Test {
    public static void main(String[] args) {
        TaskUtils.submitTask("AnLicode\\config.properties");
    }
}

config.properties文件中存储的就是任务类型的全名称限定名
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值