Java基础学习(18)反射、动态代理

一、反射

1.1 什么是反射

反射允许对封装类的字段,方法和构造函数的信息进行编程访问

个人理解:

  1. 就是把一个类当中的所有有关的数据全部拿出来,获取到,便于后面的学习
  2. 利用反射可以获取到类当中的所有信息

在这里插入图片描述

1.2 获取class对象

  • class.forName("全类名")
    常用于源代码阶段
  • 类名.class
    常用于加载阶段
  • 对象.class
    常用于运行阶段

在这里插入图片描述

package Myflect1;

public class flect1Dom {
    public static void main(String[] args) throws ClassNotFoundException {
        /*
        * 获取class的三种方式
        * */

        //第一种 全类名:包名 + 类名 Myflect1.Student1
        Class f1 = Class.forName("Myflect1.Student1");

        //第二种:
        Class f2 = Student1.class;

        //第三种
        Student1 s1 = new Student1();
        Class f3 = s1.getClass();

        System.out.println(f1 == f2);//true
        System.out.println(f2 == f3);//true
    }
}


class类中用于获取构造方法的方法

方法名称说明
Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredCohstructors():返回所有构造方法对象的数组
ConstructorgetConstructor(Class<?>… parameterTypes):返回单个公共构造方法对象
ConstructorgetDeclaredConstructor(Class<?>… parameterTypes):返回单个构造方法对象

Constructor类中用于创建对象的方法:

方法名称说明
TnewInstance(Object…initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为true,表示取消访问检查

返回权限修饰符对应数值的对象:
在这里插入图片描述

但是如果是私有的构造方法,是需要暴力反射来解决的

暴力反射:就是临时取消权限校验

package MyReflect2;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
import java.sql.SQLOutput;

public class reflect2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //首先获取到class对象
        Class clzz = Class.forName("MyReflect2.Student2");

        //获取到公有的构造方法
        Constructor[] con1 = clzz.getConstructors();
        for (Constructor constructor : con1) {
            System.out.println(constructor);
        }
        System.out.println("_____________");
        //获取到所有的构造方法
        Constructor[] con2 = clzz.getDeclaredConstructors();
        for (Constructor constructor : con2) {
            System.out.println(constructor);
        }
        System.out.println("_____________");

        //获取到某个构造方法
        Constructor con3 = clzz.getDeclaredConstructor(String.class);
        System.out.println(con3);
        System.out.println("_____________________");

        //获取到构造方法的权限修饰符对应的数值
        Constructor con4 = clzz.getDeclaredConstructor(String.class, int.class);
        int modifiers = con4.getModifiers();
        System.out.println(modifiers);
        System.out.println("_______________");

        //获取构造方法当中的参数
        Parameter[] parameters = con4.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }
        System.out.println("_____________");

        //还可以利用这个创建对象
        //但是如果是私有的构造方法,是需要暴力反射来解决的
        //暴力反射:就是临时取消权限校验
        con4.setAccessible(true);
        Student2 student = (Student2) con4.newInstance("zhangsan", 23);
        System.out.println(student);
    }

}

利用反射获取成员变量:
class类中用于获取成员变量的方法

方法名称说明
FieldilgetFields():返回所有公共成员变量对象的数组
FieldilgetDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象

Field类中用于创建对象的方法

方法说明
void set(Object obj,Obiect value):赋值Object get(Obiect obi) 获取值。
package MyReflect3;

import java.lang.reflect.Field;

/*
* 创建成员变量的反射
* */
public class reflect3 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        //首先创建class对象
        Class  clzz = Class.forName("MyReflect3.Student3");

        //获取到当中公有的成员变量
        Field[] f1 = clzz.getFields();
        for (Field field : f1) {
            System.out.println(field);
        }
        System.out.println("___________");

        //获取所有的成员变量
        Field[] f2 = clzz.getDeclaredFields();
        for (Field field : f2) {
            System.out.println(field);
        }
        System.out.println("________________");

        //获取单个成员变量
        Field name = clzz.getDeclaredField("name");
        System.out.println(name);
        System.out.println("______");

        //获取到权限修饰符
        int modifiers = name.getModifiers();
        System.out.println(modifiers);
        System.out.println("_____________");

        //获取到变量当中的名字
        String n = name.getName();
        System.out.println(n);
        //数据类型
        Class type = name.getType();
        System.out.println(type);
        System.out.println("___________");

        //获取到成员变量当中的值
        Student3 s1 = new Student3("zhahngsan", 23,89);
        name.setAccessible(true);
        String s = (String) name.get(s1);
        System.out.println(s);

        //修改成员变量的值
        name.set(s1,"lisi");
        System.out.println(s1);
    }
}

利用反射获取成员方法:
Class类中用于获取成员方法的方法

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

Method类中用于创建对象的方法

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

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

package MyReflect4;

import MyReflect3.Student3;

import javax.xml.transform.Source;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/*
* 创建成员方法中的反射
* */
public class reflect4 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //创建class对象
        Class<?> clzz = Class.forName("MyReflect4.Student4");

        //获取到公有的成员方法(包含父类的公有方法)
        Method[] con1 = clzz.getMethods();
        for (Method constructor : con1) {
            System.out.println(constructor);
        }
        System.out.println("________");

        //获取到所有的成员方法(不包括父类的方法)
        Method[] con2 = clzz.getDeclaredMethods();
        for (Method constructor : con2) {
            System.out.println(constructor);
        }
        System.out.println("______________");

        //获取单个的成员
        Method eat = clzz.getDeclaredMethod("eat", String.class);
        System.out.println(eat);
        System.out.println("_______");
        //获取到方法的修饰符
        int modifiers = eat.getModifiers();
        System.out.println(modifiers);

        //获取到方法的名字
        String name = eat.getName();
        System.out.println(name);

        //获取到方法的形参
        int parameterCount = eat.getParameterCount();
        System.out.println(parameterCount);

        //获取到方法抛出的异常
        Class<?>[] exceptionTypes = eat.getExceptionTypes();
        for (Class<?> exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }

        //运行方法
        Student4 s = new Student4("haisdh", 23);
        eat.setAccessible(true);
        //参数1:表示方法的调用者
        //参数二:传输过去的实际参数
        String invoke = (String) eat.invoke(s, "蜜汁汉堡");
        System.out.println(invoke);
    }
}

二、综合练习

2.1 保存信息

在这里插入图片描述

package ReflectExercises;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;

/*
* 对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
* */
public class exercise1 {
    public static void main(String[] args) throws IOException, IllegalAccessException {
        //首先创建对象
        Student stu = new Student("张三", 23, "男");
        GirlFriend girlFriend = new GirlFriend("阿瓜", 18, "好吃的", "成都");

        //创建一个方法进行去实现消息的打印效果
        shouinfo(stu);
        shouinfo(girlFriend);
    }

    private static void shouinfo(Object obj) throws IOException, IllegalAccessException {
        //首先获取class对象
        Class  clzz = obj.getClass();

        //创建输出流写入对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt",true));
        //获取到所有的消息
        Field[] declaredFields = clzz.getDeclaredFields();
        for (Field str : declaredFields) {
            //首先临时取消权限限制,以便进行访问其名字
            str.setAccessible(true);
        //获取到名字
            String name = str.getName();
        //得到其数据
            Object value = str.get(obj);
            //写入数据
            bw.write(name + "=" + value);
            bw.newLine();
        }
        bw.close();

    }
}

2.2 文件的动态创建

在这里插入图片描述

package ReflectExercises.exercise2;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLOutput;
import java.util.Properties;

/*
* 反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
* */
public class exercise2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // 1/读取配置文件的信息
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream("E:\\Java文件夹\\Myflects\\src\\ReflectExercises\\exercise2\\prop.properties");
        prop.load(fis);
        fis.close();

        // 2. 获取全类名和方法名
        String  className = (String) prop.get("classname");
        String  methodName = (String) prop.get("method");


        //创建class对象
        Class clzz = Class.forName(className);

        //获取到构造方法
        Constructor con = clzz.getDeclaredConstructor();
        //利用空参创建对象
        Object o = con.newInstance();
        System.out.println(o);
        //获取成员方法并且运行
        Method method = clzz.getDeclaredMethod(methodName);
        method.setAccessible(true);
        method.invoke(o);
    }
}

常见方法:

get获取
Constructor构造方法
Field成员变量
Method方法
set设置
Parameter参数
Modifiers修饰符
Declared私有的

三、动态代理

3.1 什么是动态代理

想象图
在这里插入图片描述
简单理解就是通过代理去添加其他想要添加的功能,还不用去修改原先的代码,以防出错

通过接口的方式把所有的方法进行传输代理

总结:

  1. 为什么需要代理?
    代理可以无侵入式的给对象增强其他的功能
    调用者------>代理--------->对象
  2. 代理长什么样?
    代理里面就是对象要被代理的方法
  3. Java通过什么来保证代理的样子?
    实现同一个接口通过接口保证,后面的对象和代理需要接口中就是被代理的所有方法

3.2 创建代理

方法说明
public static Obiect newProxyInstance(Classloader loader, Class<?>i intenfaces, InvocationHandler h)提供为对象产生代理对象的方法

参数一用于指定用哪个类加载器,去加载生成的代理类
参数二指定接口,这些接口用于指定生成的代理长什么,也就是有哪些方法
参数三用来指定生成的代理对象要干什么事情

创建的代理:

package ReflectExercises.exercise3;
/*
* 创建代理
* */


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyUtil {
    /*
    * 方法作用:给明星对象,创建一个代理
    *
    *形参:被代理的对象
    *
    * 返回值:给明星创建的代理
    *
    *
    * 需求:
                外面的人想要大明星唱一首歌
                1。获取代理的对象
                代理对象 = ProxyUti.createProxy(大明星的对象);
                * 2。再调用代理的唱歌方法
                代理对象.唱歌的方法("只因你太美");
    * */

    public static Star createProxy(Star 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 {
                        /*
                        * 参数一:表示需要代理的对象
                        * 参数二:表示执行的方法
                        * 参数三:表示当中的参数
                        * */
                        if ("sing".equals(method.getName())){
                            System.out.println("准备话筒,收钱");
                        } else if ("dance".equals(method.getName())) {
                            System.out.println("准备舞台,收钱");
                        }
                        return method.invoke(bigstar,args);
                    }
                }
        );
        return star;
    }
}

接口:

package ReflectExercises.exercise3;

public interface Star   {
    public abstract String sing(String name);
    public abstract void dance();
}

大明星对象:

package ReflectExercises.exercise3;

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(getName()+"正在唱"+name);
        return "谢谢";
    }
    @Override
    public void dance(){
        System.out.println(getName()+"正在跳舞");
    }
    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

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

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

测试类:

package ReflectExercises.exercise3;

public class Test {
    public static void main(String[] args) {
            //创建打明星对象
        BigStar bigStar = new BigStar("小鸡哥");

        //创建代理
        Star proxy = ProxyUtil.createProxy(bigStar);

        //调用方法
        String str = proxy.sing("阿里嘎多");
        System.out.println(str);
        proxy.dance();
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无论是工作学习,不断的总结是必不可少的。只有不断的总结,发现问题,弥补不足,才能长久的进步!!Java学习更是如此,知识点总结目录如下: 目录 一、 Java概述 3 二、 Java语法基础 5 数据类型 5 运算符号 14 语句 15 函数 15 方法重载(Overloadjing)与重写(Overriding) 16 数组 17 总结 18 三、 常见关键字 20 四、 面向对象★★★★★ 21 五、 封装(面向对象特征之一)★★★★ 23 六、 继承(面向对象特征之一)★★★★ 25 七、 接口(面向对象特征之一)★★★★ 28 八、 多态(面向对象特征之一)★★★★ 30 九、 java.lang.Object 31 十、 异常★★★★ 34 十一、 包(package) 37 十二、 多线程★★★★ 39 为什么要使用多线程 39 创建线程和启动 39 线程的生命周期 44 线程管理 45 线程同步 49 线程通信 52 线程池 58 死锁 64 线程相关类 65 十三、 同步★★★★★ 67 十四、 Lock接口 70 十五、 API 71 String字符串:★★★☆ 71 StringBuffer字符串缓冲区:★★★☆ 73 StringBuilder字符串缓冲区:★★★☆ 74 基本数据类型对象包装类★★★☆ 75 集合框架:★★★★★,用于存储数据的容器。 76 Collection接口 77 Iterator接口 78 List接口 78 Set接口 80 Map接口 81 把map集合转成set的方法 82 使用集合的技巧 83 Collections--集合工具类 83 Arrays—数组对象工具类 84 增强for循环 85 可变参数(...) 86 枚举:关键字 enum 86 自动拆装箱 86 泛型 87 System 89 Runtime 90 Math 90 .Date:日期类,月份从0—11 92 Calendar:日历类 93 十六、 IO流:用于处理设备上数据 ★★★★★ 94 IO流的概念 95 字符流与字节流 98 流对象 101 File类 102 Java.util.Properties 103 介绍IO包中扩展功能的流对象 103 十七、 网络编程 110 网络基础之网络协议篇 111 UDP传输 124 TCP传输 126 十八、 反射技术 127 十九、 Ajax原理及实现步骤★★★★★ 130 Ajax概述 130 Ajax工作原理 130 Ajax实现步骤 130 详解区分请求类型: GET或POST 131 $.ajax标准写法 134 二十、 正则表达式:其实是用来操作字符串的一些规则★★★☆ 135 二十一、 设计模式★★★★★ 136 设计模式简介 136 单例设计模式:★★★★★ 156 工厂模式★★★★★ 159 抽象工厂模式★★★★★ 163 建造者模式 170 原型模式 177 适配器模式 182 桥接模式 188 过滤器模式 192 组合模式 193 装饰器模式★★★★★ 196 外观模式 201 享元模式 204 代理模式★★★★★ 208 责任链模式 212 命令模式 216 解释器模式 219 迭代器模式 222 中介者模式 224 备忘录模式 226 观察者模式 230 状态模式 233 空对象模式 236 策略模式★★★★★ 238 模板模式 240 访问者模式 244 设计模式总结★★★★★ 247 二十二、 Java其他总结 248 Java JVM知识点总结 248 equals()方法和hashCode()方法 270 数据结构 273 Array方法类汇总 304 Java数组与集合小结 305 递归 309 对象的序列化 310 Java两种线程类:Thread和Runnable 315 Java锁小结 321 java.util.concurrent.locks包下常用的类 326 NIO(New IO) 327 volatile详解 337 Java 8新特性 347 Java 性能优化 362
Java动态代理反射Java语言中的两个重要概念。 反射机制允许程序在执行期间获取任何类的内部信息,并能直接操作任意对象的内部属性和方法。通过反射,我们可以在运行时动态地获取类的结构信息,例如类的字段、方法、构造函数等。反射机制在一些框架和工具中被广泛使用,例如Spring框架的依赖注入和AOP(面向切面编程)。 动态代理是一种设计模式,它允许在运行时创建一个代理对象,该代理对象可以替代原始对象执行相同的操作。动态代理通常用于在不修改原始类的情况下,为原始类添加额外的功能或行为。在Java中,动态代理是通过反射机制实现的。 Java动态代理是通过Proxy类和InvocationHandler接口实现的。Proxy类用于创建代理对象,InvocationHandler接口定义了代理对象的方法调用处理逻辑。通过传入不同的InvocationHandler实现类,可以在运行时生成不同的代理类。 总结起来,反射机制允许程序在运行时获取类的结构信息并操作对象的属性和方法,而动态代理则是通过反射机制在运行时生成代理对象,实现对原始对象的代理操作。这两个概念在Java中都具有重要的应用价值。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [Java学习路线:day28 反射](https://blog.csdn.net/m0_46153949/article/details/106192238)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [java中的动态代理反射](https://blog.csdn.net/xunbaobao123/article/details/115180522)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值