JAVA基础学习笔记_反射+动态代理

文章目录

反射

允许对成员变量\成员方法\构造方法的信息进行编程访问

把类内的信息扒的干干净净,获取+解剖

获取从class字节码文件中获取

获取class对象的三种方式

复制代码
public static void main(String[] args) throws ClassNotFoundException {
	//第一种
	//最为常用
	Class<?> aClass = Class.forName("com.itheima.stream.Student");
	System.out.println(aClass);
	//第二种
	//更多是作为参数进行传递
	Class<Student> studentClass = Student.class;
	System.out.println(studentClass);
	//第三种
	//有了这个类的对象,才可以使用
	Student student = new Student();
	Class<? extends Student> aClass1 = student.getClass();
	System.out.println(aClass1);
}

获取构造方法

复制代码
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
	Class<?> aClass = Class.forName("com.itheima.stream.Student");
//        aClass.getConstructors();//返回所有的公共构造方法
//        aClass.getDeclaredConstructors();//返回所有的构造方法
//        aClass.getConstructor();//返回单个公共的构造方法
//        aClass.getDeclaredConstructor();//返回单个的构造方法
	Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
	//获取构造中的参数
	Parameter[] parameters = declaredConstructor.getParameters();
	for (Parameter parameter : parameters) {
		System.out.println(parameter);
	}
	//用反射创建对象
	//如果是私有的构造方法,需要设置 accessible 为 true,暴力反射访问
	declaredConstructor.setAccessible(true);
	Student student = (Student) declaredConstructor.newInstance("张三", 23);
	System.out.println(student);
}

获取成员变量

复制代码
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
	Class<?> aClass = Class.forName("com.itheima.stream.Student");
//        aClass.getFields();
//        aClass.getDeclaredFields();
//        aClass.getField();
//        aClass.getDeclaredField();
	Field[] declaredFields = aClass.getDeclaredFields();
	for (Field declaredField : declaredFields) {
		System.out.println(declaredField);
	}

	Field name = aClass.getField("name");
	//获取权限修饰符
	System.out.println(name.getModifiers());
	//获取成员变量类型
	System.out.println(name.getType());
}

获取成员方法

复制代码
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
	Class<?> aClass = Class.forName("com.itheima.stream.Student");
//        aClass.getMethods();//获取所有的方法(包含父类)
//        aClass.getDeclaredMethods();//获取本类所有的方法(不包含父类)
	Method method = aClass.getMethod("toString");
//        aClass.getDeclaredMethod();
	//获取抛出的异常
	Class<?>[] exceptionTypes = method.getExceptionTypes();
	for (Class<?> exceptionType : exceptionTypes) {
		System.out.println(exceptionType.getName());
	}

	Method eat = aClass.getMethod("eat", String.class);
	Student student = new Student();
	Object out = eat.invoke(student, "汉堡");
	System.out.println(out);
}

这里的invoke是重点,苍穹外卖的代理有用到

反射的作用

  • 获取一个类里面所有的信息,获取到之后,再执行其他的业务逻辑

  • 结合配置文件,动态的创建对象并调用方法
    确实,我也想不出来怎么从配置文件中获取或修改方法类

    public static void saveObject(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Class clazz = object.getClass();
    //获取所有的成员变量
    Field[] declaredFields = clazz.getDeclaredFields();
    for (Field declaredField : declaredFields) {
    declaredField.setAccessible(true);
    String name = declaredField.getName();
    Object o = declaredField.get(object);
    System.out.println(name + ":" + o);
    }
    }

动态代理

无侵入式的给对象增强其他的功能

代理工具类

复制代码
public class ProxyUtil {
    public static Star createProxy(BigStar bigStar){
        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),//指定用哪个类加载器,去加载生成的代理
                new Class[]{Star.class},//指定代理类需要实现的接口
                new InvocationHandler() {//指定生成的代理要干什么
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //参数1,代理对象
                        //参数2,要调用的方法
                        //参数3,调用方法时,传递的参数
                        if ("sing".equals(method.getName())){
                            System.out.println("准备话筒,收钱");
                        } else if ("dance".equals(method.getName())) {
                            System.out.println("准备场地,收钱");
                        }
                        return method.invoke(bigStar,args);
                    }
                });
        return star;
    }

代理对象

复制代码
public class BigStar implements Star{
    private String name;

    public BigStar() {
    }

    public BigStar(String name) {
        this.name = name;
    }

    @Override
    public String sing(String name){
        System.out.println(this.name+"正在唱歌"+name);
        return "谢谢";
    }
    @Override
    public void dance(){
        System.out.println(this.name+"正在跳舞");
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "BigStar{name = " + name + "}";
    }
}

代理对象对应准备的接口,用接口代理对象实现附加功能

复制代码
public interface Star {
    void dance();
    String sing(String name);
}

测试

复制代码
public static void main(String[] args) {
	Star proxy = ProxyUtil.createProxy(new BigStar("王宝强"));
	String result = proxy.sing("某某");
	System.out.println(result);
}
相关推荐
MarkHD2 分钟前
智能体在车联网中的应用:第5天 车联网导论与体系认知:驶向智能出行的未来
学习
Alsn865 分钟前
27.IDEA 专业版创建与打包 Java 命令行程序
java·ide·intellij-idea
d111111111d6 分钟前
编码器测速详情解释:PID闭环控制
笔记·stm32·单片机·嵌入式硬件·学习·算法
毕设源码-郭学长8 分钟前
【开题答辩全过程】以 基于JAVA的车辆违章信息管理系统设计及实现为例,包含答辩的问题和答案
java·开发语言
while(1){yan}8 分钟前
UDP和TCP的核心
java·开发语言·网络·网络协议·tcp/ip·udp
我想我不够好。9 分钟前
电工学习 实操考点及打分项
学习
麒qiqi12 分钟前
【Linux 进程间通信】信号通信与共享内存核心解析
java·linux·算法
风123456789~13 分钟前
【健康管理】第8章 身体活动基本知识 1/2
笔记·考证·健康管理
后端小张13 分钟前
【Java 进阶】深入理解Redis:从基础应用到进阶实践全解析
java·开发语言·数据库·spring boot·redis·spring·缓存
柯南二号13 分钟前
【后端】【Java】RabbitMQ / RocketMQ / Kafka / Redis 消息队列深度对比与选型指南
java·java-rocketmq·java-rabbitmq