Java学习记录(二十二)反射,动态代理

news2025/1/11 17:13:55

反射获取class对象的三种方式

1、Class.forName(全类名)

2、类名.class

3、对象.getClass()

实现代码如下:

package com.itazhang.Demo1;

public class MyReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //第一种获取class对象的方法
        Class clazz1 = Class.forName("com.itazhang.Demo1.Student");
        //第二种直接用对象去调用getClass
        Student stu = new Student();
        Class clazz2 = stu.getClass();
        //第三种方法
        Class clazz3 = Student.class;
    }
}

反射获取构造方法

在利用class对象获取相关构造方法的步骤如下:先用Class.forname方法创建相应的class对象 ,再通过class对象调用相关的方法,有declared修饰的方法就能获取所有修饰符的构造方法,最后带s的是返回所有相关构造方法,而没有带s的只返回一个,例如:需要传递相应的类型参数得到相应参数的构造方法,如空参构造就不传递,两个的带参构造就传递这两个数据类型的字节码

Constructor constructor = clazz.getConstructor();
Constructor constructor1 = clazz.getConstructor(String.class, int.class);
package com.itazhang.Demo1;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class MyReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class clazz = Class.forName("com.itazhang.Demo1.Student");
        //获取所有public修饰的构造方法
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("----------------------------");
        //获取所有修饰符的构造方法
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("------------------------------");
        //获取单个public修饰的构造方法,传递相应的参数即可
        Constructor constructor = clazz.getConstructor();
        System.out.println(constructor);

        //创建public修饰的构造方法的对象
        Student stu1 = (Student) constructor.newInstance();
        System.out.println(stu1);

        System.out.println("-----------------1------------------");

        Constructor constructor1 = clazz.getConstructor(String.class, int.class);
        System.out.println(constructor1);
        //获取单个所有修饰符的构造方法
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor);

        //创建private修饰的对象
        declaredConstructor.setAccessible(true);
        Student stu =(Student) declaredConstructor.newInstance("张三");
        System.out.println(stu);
    }
}

获取了构造方法之后就能通过获取出来的对象调用newInstance方法创建相关构造方法的对象,但是要注意参数个数和类型得与构造方法中的一致,如下:这是一个public修饰的空参构造 ,所以创建出来的也是一个没有参数的对象

//获取单个public修饰的构造方法,传递相应的参数即可
        Constructor constructor = clazz.getConstructor();
        System.out.println(constructor);

        //创建public修饰的构造方法的对象
        Student stu1 = (Student) constructor.newInstance();
        System.out.println(stu1);

而如果获取了private等私有修饰符的构造方法,如果需要用该构造方法,需要在创建对象之前使用setAccessible方法给此方法传递true,然后才能使用私有修饰符修饰的构造方法创建对象,如下:

//创建private修饰的对象
        declaredConstructor.setAccessible(true);
        Student stu =(Student) declaredConstructor.newInstance("张三");
        System.out.println(stu);

利用反射获取成员变量 

获取成员方法大致与获取构造方法相同,也是先创建相关类的Class对象,利用Class.forName获取class对象,如果想获取一个public修饰的成员变量就用getField方法,如果想获取其他修饰符的成员方法就用getDeclaredField方法,同样的如果想使用私有修饰符修饰的成员变量的话得调用setAccecible方法且传递true之后才能使用私有的成员方法,如下:

package com.itazhang.Demo2;

import java.lang.reflect.Field;

public class MyReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class clazz = Class.forName("com.itazhang.Demo2.Student");
        //获取全部成员变量
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("-----------1-----------");
        //获取单个public修饰的成员变量
        Field gender = clazz.getField("gender");
        System.out.println(gender);
        System.out.println("------------2---------");
        //获取全部修饰符的成员变量
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("------------3-----------");
        //获取单个所有修饰符的成员变量
        Field age = clazz.getDeclaredField("age");
        System.out.println(age);

        System.out.println("------------4------------");
        //使用private修饰符的成员变量
        Student stu = new Student("azhang",22,"男");
        age.setAccessible(true);
        Object o = age.get(stu);
        System.out.println(o);
    }
}

反射获取成员方法

大致方法的使用与之前获取成员方法相同,但是如果要使用获取出的方法时,需要用获取出来的对象调用invoke方法,传入调用该获取出来方法的对象 ,和方法需要传递的参数,这样就能使用获取出的方法,代码如下:Student类中有一个private修饰的eat方法,该方法有一个返回值且是private修饰的方法,使用invoke方法会有一个返回值,该返回值就是使用的方法的返回值,如果没有返回值,默认返回null。

//获取方法
        Student s = new Student();
        Method eat = clazz.getDeclaredMethod("eat", String.class);
        eat.setAccessible(true);
        Object o1 = eat.invoke(s, "面条");
        System.out.println(o1);

反射练习(一)

通过反射获取到两个不同类里的相关属性,且将这两个类对象的属性值写入到本地文件中

学生Student类

package com.itazhang.Demo3;

public class Student {
    private String name;
    private int age;
    private String gender;
    private String address;

    public Student() {
    }

    public Student(String name, int age, String gender, String address) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.address = address;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

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

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

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

    /**
     * 获取
     * @return address
     */
    public String getAddress() {
        return address;
    }

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

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}";
    }
}

老师Teacher类

package com.itazhang.Demo3;

public class Teacher {
    private String name;
    private int salary;

    public Teacher() {
    }

    public Teacher(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

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

    /**
     * 获取
     * @return salary
     */
    public int getSalary() {
        return salary;
    }

    /**
     * 设置
     * @param salary
     */
    public void setSalary(int salary) {
        this.salary = salary;
    }

    public String toString() {
        return "Teacher{name = " + name + ", salary = " + salary + "}";
    }
}

反射代码执行类

package com.itazhang.Demo3;

import java.io.*;
import java.lang.reflect.Field;

public class MyReflectDemo3 {
    public static void main(String[] args) throws IllegalAccessException, IOException {

        Student stu = new Student("azhang",22,"男","chengdu");
        Teacher tch = new Teacher("ahuai",12000);
        saveObject(stu);
        saveObject(tch);
    }

    public static void saveObject(Object obj) throws IllegalAccessException, IOException {

        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\11Codingtext\\MyReflect\\a.txt",true));
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
            Object value = field.get(obj);
            System.out.println(name + "=" + value);
            bw.write(name+"="+value);
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}

反射总结:

动态代理 (初始了解)

能实现无侵入式的给代码增加额外的功能。

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

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

相关文章

Nacos源码流程图

1.Nacos1.x版本服务注册与发现源码 流程图地址:https://www.processon.com/view/link/634695eb260d7157a7bc6adb 2.Nacos2.x版本服务注册与发现源码 流程图地址:https://www.processon.com/view/link/634695fb260d7157a7bc6ae0 3.Nacos2.x版本GRPC…

【Linux进程信号】信号的发送与保存

【Linux进程信号】信号的发送与保存 目录 【Linux进程信号】信号的发送与保存阻塞信号1. 信号其他相关常见概念2. 在内核中的表示3. sigset_t4. 信号集操作函数sigprocmasksigpendingsignal测试这几个系统调用接口 进程地址空间第三讲捕捉信号1. 内核如何实现信号的捕捉2. siga…

Jenkins 面试题及答案整理,最新面试题

Jenkins中如何实现持续集成与持续部署? Jenkins通过自动化构建、测试和部署应用程序来实现持续集成与持续部署(CI/CD)。这个过程包括以下步骤: 1、源代码管理: Jenkins支持与多种版本控制系统集成,如Git、…

Java项目:55 springboot基于SpringBoot的在线视频教育平台的设计与实现015

作者主页:舒克日记 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 在线视频教育平台分为管理员和用户、教师三个角色的权限模块。 管理员所能使用的功能主要有:首页、个人中心、用户管理、教师管理、课程信…

绝赞春招拯救计划 -- 操作系统,组成原理,计网

进程和线程 进程 一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程 线程 进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以…

关于Apache

文章目录 一、httpd 安装组成1、常见http 服务器程序2、apache 介绍和特点2.1 关于apache2.1.1 apache 功能2.1.2 apache特性 2.2 MPM multi-processing module 工作模式2.2.1 prefork2.2.2 worker2.2.3 event 3、Httpd 安装和相关文件3.1 包安装httpd并启动httpd服务3.1.1 版本…

配置vscode环境极简版(C/C++)(图文)

前言 众所周知,vscode是一个代码编辑器,不能直接编译运行我们敲的代码,必须提前配置好环境,而这也是劝退一众小白的一大重要因素,下面我想以一种提纲挈领的方式带大家走一遍从配置环境到运行实操代码的全过程。 安装…

用户故事到需求实例化

用户故事 用户故事是敏捷开发方法中的核心概念之一,它提供了一种简洁的方式来描述软件功能需求,同时强调这些功能为用户或业务带来的价值。用户故事通常是由用户、产品经理或业务分析师编写的简短描述,用于与开发团队沟通需求,并…

面向对象(下)

目录 01、static1.1、static的使用1.2、static应用举例1.3、单例(Singleton)设计模式 02、main方法的语法03、类的成员之四:代码块04、关键字:final05、抽象类与抽象方法5.1、多态的应用:模板方法设计模式(TemplateMethod) 06、接口(interfac…

flink1.18.0 自定义函数 接收row类型的参数

比如sql中某字段类型 array<row<f1 string,f2 string,f3 string,f4 bigint>> 现在需要编写 tableFunction 需要接受的参数如上 解决方案 用户定义函数|阿帕奇弗林克 --- User-defined Functions | Apache Flink

C语言数据结构(7)——树、二叉树前言

欢迎来到博主的专栏——C语言数据结构 博主ID&#xff1a;代码小豪 文章目录 树二叉树特殊二叉树满二叉树完全二叉树 完全二叉树的存储结构 树 树是一个非线性的数据结构&#xff0c;由N个结点构成的集合。 树的各个结点由一个根结点联系起来&#xff0c;这个根节点没有前驱…

小球垂直跳动,C语言模拟重力加速度

位移公式 1、速度和时间关系&#xff1a; 2、位移和时间关系&#xff1a; 3、力和加速度关系&#xff1a; 4、空气阻力&#xff1a; 受理分析 以向下运动为正方向 1、向下运动整体受力&#xff0c;重力加空气阻力: 2、向上运动整理受力&#xff0c;重力减空气阻力&…

Apache zookeeper kafka 开启SASL安全认证

背景&#xff1a;我之前安装的kafka没有开启安全鉴权&#xff0c;在没有任何凭证的情况下都可以访问kafka。搜了一圈资料&#xff0c;发现有关于sasl、acl相关的&#xff0c;准备试试。 简介 Kafka是一个高吞吐量、分布式的发布-订阅消息系统。Kafka核心模块使用Scala语言开发…

MySQL基础架构

文章目录 MySQL基础架构一、连接器 - 建立连接&#xff0c;权限认证二、查缓存 - 提高效率三、分析器 - 做什么四、优化器 - 怎么做五、执行器 - 执行语句六、存储引擎1、存储引擎的概述2、存储引擎的对比3、存储引擎的命令4、存储引擎的选择 MySQL基础架构 大体来说&#xff…

力扣-20. 有效的括号(回顾知识哈希表,栈)

给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有…

HTML万字学习总结

html文本标签特殊符号图片音频与视频超链接表单列表表格语义标签(布局) html文本标签 标签简介<html></html>根目录<head></head>规定文档相关的配置信息&#xff08;元数据<body></body>元素表示文档的内容<meta></meta>表示…

“技多不压身”是什么意思?看完这篇文章你会明白:有了手艺,走遍天下都不怕!

“技多不压身”是什么意思&#xff1f;看完这篇文章你会明白&#xff1a;有了手艺&#xff0c;走遍天下都不怕&#xff01; 咱们的老祖宗流传一句话&#xff1a;“一招鲜&#xff0c;吃遍天。”这话说得直白&#xff0c;却道出了学一门手艺或技术对于人生的重要性。“李秘书讲…

Linux 学习笔记(16)

十六、 计划任务 在很多时候为了自动化管理系统&#xff0c;我们都会用到计划任务&#xff0c;比如关机&#xff0c;管理&#xff0c;备份之类的操作&#xff0c;我 们都可以使用计划任务来完成&#xff0c;这样可以是管理员的工作量大大降低&#xff0c;而且可靠度更好。 l…

电商经济和实体经济,哪个更有发展力?这篇文章讲的很详细!

我是电商珠珠 三年的冲击&#xff0c;使实体经济走向衰败&#xff0c;以至于到今天很多实体店仍无法正常营业&#xff0c;面临赔本的惨状。花大好几十万去做这件事&#xff0c;结果分币未挣。近年来&#xff0c;电商虽然发展的很快&#xff0c;但是平台众多&#xff0c;规则也…

“入站营销“VS“即时流量变现“客户该进谁家门?

在不断变化的市场环境下&#xff0c;两种主导战略“入站营销 ”和 “即时流量变现”决定了企业接触受众的方式。了解这些方法之间的根本区别对于企业制定有效的营销战略至关重要。 受众体的差别线索质量 “即时流量变现”&#xff0c;顾名思义&#xff0c;短时间&#xff0c;…