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);
}
相关推荐
码字哥7 分钟前
EasyExcel设置表头上面的那种大标题(前端传递来的大标题)
java·服务器·前端
雨中奔跑的小孩3 小时前
爬虫学习案例3
爬虫·python·学习
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS加油站管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·maven
Hello.Reader3 小时前
Spring Retry 与 Redis WATCH 结合实现高并发环境下的乐观锁
java·redis·spring
西岭千秋雪_3 小时前
设计模式の单例&工厂&原型模式
java·单例模式·设计模式·简单工厂模式·工厂方法模式·抽象工厂模式·原型模式
冷环渊3 小时前
React基础学习
前端·学习·react.js
fanchael_kui3 小时前
使用elasticsearch-java客户端API生成DSL语句
java·大数据·elasticsearch
m0_748256563 小时前
[CTF夺旗赛] CTFshow Web1-14 详细过程保姆级教程~
java
T.O.P114 小时前
Spring&SpringBoot常用注解
java·spring boot·spring
O(1)的boot4 小时前
微服务的问题
java·数据库·微服务