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

news2024/11/16 15:56:24

Java基础学习

  • 一、反射
    • 1.1 什么是反射
    • 1.2 获取class对象
  • 二、综合练习
    • 2.1 保存信息
    • 2.2 文件的动态创建
  • 三、动态代理
    • 3.1 什么是动态代理
    • 3.2 创建代理

一、反射

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/547073.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JVM】5. 本地方法接口和本地方法栈

文章目录 5.1. 什么是本地方法&#xff1f;5.2. 为什么使用Native Method&#xff1f;5.3. 本地方法栈 5.1. 什么是本地方法&#xff1f; 简单地讲&#xff0c;一个Native Method是一个Java调用非Java代码的接囗。一个Native Method是这样一个Java方法&#xff1a;该方法的实现…

【007】C++数据类型之原码、补码、反码

C数据类型之原码、补码、反码 引言一、原码、补码、反码的概述二、为什么要使用补码&#xff1f;三、对数据的存四、对数据的取总结 引言 &#x1f4a1; 作者简介&#xff1a;专注于C/C高性能程序设计和开发&#xff0c;理论与代码实践结合&#xff0c;让世界没有难学的技术。包…

KingbaseES V8R3 集群运维案例--sys_rewind恢复备库节点

​ 案例说明&#xff1a; 在KingbaseES V8R3集群执行failover切换后&#xff0c;原主库被人为误(未配置recovery.conf)启动&#xff1b;或者人为promote备库为主库后。需要将操作节点再重新加入集群&#xff0c;此时节点与主库的timeline将出现分叉&#xff0c;导致节点直接加入…

ChatGLM-6B 本地部署指南!

Datawhale干货 作者&#xff1a;宋志学&#xff0c;Datawhale成员 注意事项-写在最前 显卡需要至少6GB的显存使用GPU部署模型需要自行安装torch和与自己显卡匹配的CUDA、cudnn 下载ChatGLM-6B 在GitHub上下载chatglm-6b的源码&#xff0c;地址如下 https://github.com/THUDM/C…

信息安全-应用安全-SCA技术:SBOM应用实践初探

目录 软件供应链安全治理 供应链安全概述 风险治理重点 何为SBOM SBOM的元素 SBOM的格式 SBOM使用场景 如何使用SBOM 选择SBOM工具 SBOM与风险情报关联 围绕SBOM建立管理流程 关于SBOM的思考 现代软件都是组装的而非纯自研。随着开源组件在数字化应用中的使用比例越…

【C++】运算符重载与赋值运算符重载(显式与默认)的特性与格式以及前置++,后置++重载

文章目录 前言一、运算符重载二、赋值运算符重载1. 赋值运算符重载格式&#xff1a;2. 用户没有显式实现时&#xff0c;编译器会生成一个默认赋值运算符重载&#xff0c;以值的方式逐字节拷贝。3. 赋值运算符只能重载成类的成员函数不能重载成全局函数 三、前置与后置 前言 C为…

【Linux】Linux小程序-进度条

目录 一、\r和\n的理解 二、行缓冲区概念 三、进度条源代码 一、\r和\n的理解 \r&#xff1a;回车&#xff1b; \n&#xff1a;换行&#xff1b; 那么请问这两个有什么区别呢&#xff1f; 比如&#xff1a;我们在编写内容的时候&#xff0c;一行没有写完的情况下&#xff0c;需…

【信息安全案例】——软件解密技术(以OllyDbg为例)

目录 &#x1f552; 1. 软件解密技术&#x1f558; 1.1 概述&#x1f558; 1.2 爆破&#x1f558; 1.3 跟踪注册&#x1f558; 1.4 写出注册 &#x1f552; 2. 破解相关问题&#x1f558; 2.1 破解程度&#x1f558; 2.2 破解线索 &#x1f552; 3. 实验&#xff1a;使用 OllyD…

分布式系统原理

高可用是指系统无中断的执行功能的能力&#xff0c;代表了系统的可用程度&#xff0c;是进行系统设计时必须要遵守的准则之一。 而高可用的实现方案&#xff0c;无外乎就是冗余&#xff0c;就存储的高可用而言&#xff0c;问题不在于如何进行数据备份&#xff0c;而在于如何规避…

MacOS Ventura 13.4 (22F66) 带 OC 引导双分区黑苹果镜像

苹果今日向 Mac 电脑用户推送了 macOS 13.4 更新&#xff08;内部版本号&#xff1a;22F66&#xff09;&#xff0c;本次更新距离上次发布隔了 41 天&#xff0c;主要解决了与Apple Watch自动解锁、蓝牙键盘、屏幕使用时间和VoiceOver相关的问题&#xff0c;推荐大家安装升级。…

Vue 级联组件添加按钮并添加点击事件加传参

我这里采用的是jqvue实现的此功能&#xff0c;首先是要把按钮追加进去&#xff0c;当然头开始写真实dom会导致页面上也追加显示&#xff0c;但是我想实现的是在级联组件上追加所以&#xff0c;选择创建虚拟dom&#xff0c;然后传参这点实在是研究试错了半天&#xff0c;最后选择…

聚观早报|ChatGPT 推出官方 iOS App;大疆称将接收OPPO哲库工程师

今日要闻&#xff1a;ChatGPT 推出官方 iOS App&#xff1b;大疆称将接收OPPO哲库工程师&#xff1b;菜鸟、盒马启动上市计划&#xff1b;苹果公司限制员工使用ChatGPT&#xff1b;张勇&#xff1a;阿里云将分拆上市 ChatGPT 推出官方 iOS App 北京时间 5 月 19 日&#xff0c…

苹果扩充AirTag应用场景,苹果Find My应用更加广泛

根据美国商标和专利局&#xff08;USPTO&#xff09;公示的清单&#xff0c;苹果近日获得了一项技术专利&#xff0c;将追踪器附着人体或者服装上&#xff0c;从而监测健康和活动数据。 AirTag 不仅可以追踪某件事物之外&#xff0c;还可以通过安装在人体的不同位置&#xff0c…

人工智能本来是个很简单的事,咋被人们整的这么神秘?

&#xff08;1&#xff09; 很多人以为大模型的参数量大是因为数据多。 其实大模型的参数量和超参数的配置相关。主要的超参数有下面几个&#xff1a; 词表大小&#xff1a;Vocab_Size最大位置编码大小&#xff1a;Max_Position_embeddings隐层节点数大小&#xff1a;Hidden_Si…

Linux - 第16节 - 网络基础(应用层二)

1.HTTP协议 我们在套接字部分编写的代码和应用层一中编写的网络计算器代码都是在应用层工作的&#xff0c;是应用层代码&#xff0c;因此应用层代码包括&#xff1a; &#xff08;1&#xff09;基本系统socket套接字系列接口的使用。 &#xff08;2&#xff09;定制协议&#x…

一个炎爆术分享给大家~

先来强势围观&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"https://cdnjs.cloudflare.com/ajax/libs/three.js/r120/…

23种设计模式之外观模式(Facade Pattern)

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;在一家满意的公司实习。本篇文章将23种设计模式中的外观模式&#xff0c;此篇文章为一天学习一个设计模式系列文章&#xff0c;后面会分享其他模式知识。 如果文章有什么需要改进的地方还请大佬不…

云从科技从容大模型:大模型和AI平台什么关系?为什么造行业大模型?

原创&#xff1a;亲爱的数据 2023年5月18日&#xff0c;坐标广州南沙&#xff0c;来自云从科技的“云从从容大模型”正式亮相。 自此&#xff0c;云从科技从CV四小龙“进阶”成为一家AI大模型公司&#xff0c;同时&#xff0c;别忘记云从还有一个身份常被人提起&#xff1a;首家…

纯虚函数与抽象类

纯虚函数与抽象类 虚析构函数状态转换的引入C中的状态转换C中的状态转换职责链模式 纯虚函数和虚基类使用规则实例接口继承和实现继承 虚析构函数 在上一次博客中写到了这么一段代码&#xff1a; class object { private: int value;public:object(int x 0) : value(x) {}~o…

嵌入式音视频开发过程中如何控制码率?

一、码率控制的意义&#xff1a; 在音视频领域&#xff0c;码率控制模式有着举足轻重的地位。那什么是码率控制&#xff1f;码率控制是指通过调节图像的压缩比例&#xff0c;从而决定输出编码码率的过程。 二、H264有多少种码率控制模式&#xff1a; H264码率控制模式分别有&am…