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);
}
相关推荐
keke1029 分钟前
Java【14_2】接口(Comparable和Comparator)、内部类
java·开发语言
CN.LG39 分钟前
Java 乘号来重复字符串的功能
java·开发语言
lqjun082739 分钟前
Pytorch实现常用代码笔记
人工智能·pytorch·笔记
萌新下岸多多关照44 分钟前
Java中synchronized 关键字
java·开发语言
中国lanwp1 小时前
使用Maven部署WebLogic应用
java·maven
开开心心就好1 小时前
Word图片格式调整与转换工具
java·javascript·spring·eclipse·pdf·word·excel
云海听雷1 小时前
C语言中字符串函数的详细讲解
c语言·笔记·学习
CGG921 小时前
【单例模式】
android·java·单例模式
苦学编程的谢1 小时前
多线程代码案例-1 单例模式
java·开发语言·单例模式
wb1891 小时前
Linux远程连接服务
linux·运维·服务器·笔记