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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mysql常见的索引模型

目录 有序数组哈希表二叉搜索树B-TreeBTree 有序数组 我们指定一个列为索引&#xff0c;然后按照这个列的值排序&#xff0c;以有序数据存放入数据表中&#xff0c;如下所示 这样&#xff0c;我们在查找数据的时候&#xff0c;就可以通过id这个列&#xff0c;在数据表中进行二…

坚持刷题2个月,终于......

最近一个读者和我反馈&#xff0c;他坚持刷题2个月&#xff0c;终于去了他梦寐以求的大厂&#xff0c;薪资涨幅非常可观&#xff0c;期间面字节跳动还遇到了原题…并表示目前国内的大厂和一些独角兽&#xff0c;已经越来越效仿硅谷公司的做法&#xff0c;通过面试给定题&#x…

zookeeper的安装使用

zookeeper的安装使用 一、下载安装 https://zookeeper.apache.org/ 点击 download 以我自己的安装为例,linux,3.8.0 准备3台linux服务器&#xff1a;192.168.10.128、192.168.10.129、192.168.10.130 1.上传解压 把apache-zookeeper-3.8.0-bin.tar.gz 上传到 /usr/local/zo…

耗时162天,从华为外包5k转岗正式员工15k,经历的心酸只有自己知道····

一提及外包测试&#xff0c;大部分人的第一印象就是&#xff1a;工作强度大&#xff0c;技术含量低&#xff0c;没有归属感&#xff01; 本人毕业于某普通二本院校非计算机专业&#xff0c;跨专业入行测试&#xff0c;至今有近 5年工作经验。 第一份测试工作是在华为做了两年外…

Github Copilot 的补强工具Github Copilot Labs的常用功能介绍

一、什么是Github Copilot Labs Github Copilot Labs是由GitHub推出的一款基于人工智能技术的代码协作工具&#xff0c;旨在协助开发者更加快速、高效地编写代码。该工具使用了机器学习技术&#xff0c;通过学习大量的开源代码和编写实践&#xff0c;提供了对于代码变量、函数…

多激光雷达手眼标定

手眼标定方法已经有很多博客进行解析&#xff0c;但是都是针对机器人的手&#xff08;夹爪&#xff09;眼睛&#xff08;相机&#xff09;进行标定。例如&#xff1a; 标定学习笔记&#xff08;四&#xff09;-- 手眼标定详解 手眼标定_全面细致的推导过程 本文主要描述多激光…

四、数据仓库详细介绍(规范)

大家好&#xff0c;这是数据仓库系列的第三个话题&#xff0c;排序在架构之后、建模之前。为什么会提的这么靠前呢&#xff1f; 因为规范约束的是数仓建设的全流程&#xff0c;以及后续的迭代和运维。事实上&#xff0c;数仓规范文档&#xff0c;应该随着架构设计文档&#xf…

Java 与排序算法(5):归并排序

一、归并排序 归并排序&#xff08;Merge Sort&#xff09;是一种基于分治思想的排序算法。它将待排序的数组分成两个长度相等的子数组&#xff0c;然后对这两个子数组分别进行归并排序&#xff0c;最后将两个排好序的子数组合并成一个有序的数组。 具体实现过程如下&#xf…

要做存储业务,我解析了一个项目的源码

最近在做存储相关的业务&#xff0c;更具体的来说是存储相关的研发&#xff0c;于是就上网查了一下相关的资料&#xff0c;思虑再三打算从最简单的 Json 数据交换格式开始研究。 JSON是独立于编程语言的数据交换格式&#xff0c;几乎所有与网络开发相关的语言都有JSON函数库&am…

基于Java+SpringMvc+vue+element实现高效学生社团平台管理

基于JavaSpringMvcvueelement实现高效学生社团平台管理 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式…

oracle数据库当中用户的创建,添加,授权,以及表的创建与表的简单介绍,以及在oracle数据库当中的约束以及约束条件的简单介绍

系列文章目录 (3条消息) oracle数据库简介 文章目录 系列文章目录 前言 一、用户的创建 1.1、创建命令 1.2、给予scott用户权限 1.3、以scott用户进行连接登录 二、表和表的设计原则 2.1、表的概念 2.1.1、表是从属于用户的 2.1.2、表是逻辑表(概念表)&#xff0c;不…

gpt.4.0-gpt 国内版

gpt 使用 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种预训练的语言模型&#xff0c;可用于多种自然语言处理任务&#xff0c;如情感分析、文本分类、文本生成等。下面是使用GPT的一些步骤和建议&#xff1a; 确定任务和数据集&#xff1a;首先&…

Hibernate 快速入门

Hibernate 快速入门 〇、前言一、搭建 Hibernate 项目步骤1:新建 Java 项目附录1:新建Java项目中的相关文件信息步骤2:添加 Hibernate 框架支持附录2:添加Hibernate框架支持后,Java项目中的相关文件信息步骤3:其他关键配置1、添加数据库驱动包(本文以MySQL为例)2、配置…

C++11 列表初始化initializer_list

引子 C11&#xff0c;是继C98后的一次有力更新&#xff0c;引进了很多好用的语法&#xff0c;STL也添加了几个新容器&#xff0c;也解决了很多的问题。本篇博客就学习一下C11列表初始化的新语法和 initializer_list 文章目录 引子一. 列表初始化二. initializer_list结束语 一…

计算机底层知识

汇编语言&#xff08;机器语言&#xff09;的执行过程 汇编语言的本质&#xff1a;机器语言的助记符 其实他就是机器语言 计算机通电->CPU读取内存中程序&#xff08;电信号输入&#xff09; ->时钟发生器不断震荡通电 ->推动CPU内部一步一步执行&#xff08;执行多…

安卓开发 | 将Vue项目打包为app

知识目录 一、写在前面✨二、Hbuilder X准备&#x1f495;2.1 Hbuilder X简介2.2 下载 三、打包&#x1f495;3.1 获取dist目录3.2 新建5app3.3 替换文件3.4 编写manifast.json文件3.5 app云打包 四、总结撒花&#x1f60a; 一、写在前面✨ 大家好&#xff01;我是初心&#xf…

OJ练习第107题——二叉搜索子树的最大键值和

二叉搜索子树的最大键值和 力扣链接&#xff1a;1373. 二叉搜索子树的最大键值和 题目描述 给你一棵以 root 为根的 二叉树 &#xff0c;请你返回 任意 二叉搜索子树的最大键值和。 二叉搜索树的定义如下&#xff1a; 任意节点的左子树中的键值都 小于 此节点的键值。 任意…

龙蜥白皮书精选:利用 io_uring 提升数据库系统性能

文/高性能存储 SIG 01 背景介绍 传统的 IO 软件栈已经无法完全释放出高性能存储设备的性能&#xff0c;高性能 IO 栈是当前存储领域重点研究的课题之一&#xff0c;代表性的如用户态方案 SPDK&#xff0c;以及标准的内核态方案 io_uring。 02 关键技术 Linux 社区从零开始设…

SeaweedFs使用-通过http接口实现文件操作

通过http接口实现文件操作 SeaweedFs可通过filer的http接口/master中的http接口来进行文件上传 1.通过master的接口进行上传文件 通过各种方式进行请求接口&#xff1a;http://localhost:9333/submit, ip和端口号是master服务的信息。此接口通过post请求方式将文件的二进制流…

esp32CAM环境安装教程---串口驱动安装

前言 &#xff08;1&#xff09;本人安装好arduino 的ESP32环境之后&#xff0c; 发现一直下载不进去程序。一直说Cannot configure port, something went wrong. Original message: PermissionError。 &#xff08;2&#xff09;查阅了很多资料&#xff0c;用了各种办法&#…