Java反射(含静态代理模式、动态代理模式、类加载器以及JavaBean相关内容)

目录

1、什么是反射

2、Class类

3、通过Class类取得类信息/调用属性或方法

4、静态代理和动态代理

5.类加载器原理分析

6、JavaBean


1、什么是反射

Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
一张图来表示:
如果编译不知道类或对象的具体信息,此时应该如何做呢?这时就要用到反射来实现。
Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

2Class

在Java中,java.lang.Class 提供了在运行时访问对象的属性和类型信息的能力,可以说它是反射的入口。
Class 类可以理解为包含了很多类的类,其中它包括类名,构造方法,属性,方法。
得到Class类的对象有三种方式:
第一种形式:Object类中的getClass()方法
第二种形式:类.class
第三种形式:通过Class类的forName方法

用法示例:

public class Demo {
        private static Object Demo;

        public static void main(String[] args) throws ClassNotFoundException {
        person p1=new person();
        Class c=p1.getClass();//第一种形式:Object类中的getClass()方法
            System.out.println(c);
            System.out.println(person.class);//第二种形式:类.class
            Class aclass=Class.forName("person");//第三种形式:通过Class类的forName方法,需要抛出异常throws ClassNotFoundException

        }
}

使用Class类进行对象的实例化操作
调用无参构造进行实例化
public T newInstance() throws InstantiationException,IllegalAccessException

(JAVA 9 之后弃用 newInstance() 方法解决办法)
调用有参构造进行实例化
public Constructor<?>[] getConstructors() throws SecurityException

3、通过Class类取得类信息/调用属性或方法

取得类所在的包
public Package getPackage() //得到一个类所在的包
public String getName() //得到名字
取得一个类中的全部方法
public Method[] getMethods()
public int getModifiers() //Modifier.toString(mod); // 还原修饰符
public Class<?> getReturnType()
public Class<?>[] getParameterTypes()
public Class<?>[] getExceptionTypes()
public static String toString(int mod)
取得一个类中的全部属性
public Field[] getFields()
public Field[] getDeclaredFields()
public Class<?> getType()
public int getModifiers()
public String getName()
调用类中的方法
调用类中的方法,传入实例化对象,以及具体的参数内容
public Object invoke(Object obj,Object... args)
直接调用属性
取得属性
public Object get(Object obj)
// 设置属性,等同于使用“ = ”完成操作
public void set(Object obj,Object value)
// 让属性对外部可见
public void setAccessible(boolean flag)
(其中,带Declared的方法可以获取到私有属性或方法,不带Declared的只能获取公有属性或方法)

用法示例:

public class Demo {
        private static Object Demo;
        public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
            Class p1=person.class;
            Field[] fields=p1.getDeclaredFields();//获取私有属性和公有属性,下同
            Field[] fields1=p1.getFields();//仅获取公有属性,下同
            for (Field f:fields)
            {
                System.out.println(f);
            }
            System.out.println("-----------");
            for (Field f1:fields1)
            {
                System.out.println(f1);
            }
            System.out.println("-----------");
            Method[] methods=p1.getDeclaredMethods();
            for (Method m1:methods) {
                System.out.println(m1);
            }
            System.out.println("-----------");
            Constructor[] constructor=p1.getDeclaredConstructors();
            for (Constructor c:constructor) {
                System.out.println(c);
                System.out.println(c.getName());
                System.out.println(c.getParameterCount());
            }
            System.out.println("-----------");
            Package p=p1.getPackage();
            System.out.println(p);
            for (int i = 0; i < fields.length; i++) {
                int mm=fields[i].getModifiers();
                System.out.println(mm+Modifier.toString(mm)+"/ /"+fields[i].getType()+"/ /"+fields[i].getName());
            }
            System.out.println("-----------");

            Constructor<?> constructor1=p1.getDeclaredConstructor();
            constructor1.setAccessible(true);
           person pp= (person) constructor1.newInstance();
            Method m3=p1.getMethod("run",String.class);
            m3.invoke(p1,"111");
        }

}

4、静态代理和动态代理

代理模式(Proxy ):为其他对象提供一种代理以控制对这个对象的访问。
代理模式说白了就是“真实对象”的代表,在访问对象时引入一定程度的间接性,因为这
种间接性可以附加多种用途
静态代理:代理对象与目标对象一起实现相同的接口或者继承相同父类
动态代理:

 所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而
可以在运行期(Runtime)实现动态关联。
java动态代理主要是使用java.lang.reflect包中的两个类。
InvocationHandler类
public Object invoke(Object obj,Method method,Object[] obs)
其中第一个参数 obj 指的是代理类,method是被代理的方法,obs是指被代理的方法的参
数组。此方法由代理类来实现。
Proxy类
protected Proxy(InvocationHandler h);
static Class getProxyClass(ClassLoader loader,Class[] interfaces);
static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler
h);
动态代理其实是在运行时生成class,所以,我们必须提供一组interface,然后告诉他class
已经实现了这些interface,而且在生成Proxy的时候,必须给他提供一个handler,让他
来接管实际的工作。

(静态代理)用法演示:

定义一个接口:

package com.company;

public interface Action {
    public void doAction();
}

定义类:

package com.company;

public class employee implements Action{

    @Override
    public void doAction() {
        System.out.println("正在工作中...");
    }
}

定义静态代理类:

package com.company;

public class Staticproxy {

    private Action target;

    public Staticproxy(Action target)
    {
        this.target = target;
    }
        public void work()
        {
            System.out.println("开始上班");
            target.doAction();
            System.out.println("下班啦");
        }

}

测试类:

package com.company;

public class Main {

    public static void main(String[] args) {
        Action userAction = new employee();
        Staticproxy proxy = new Staticproxy(userAction);
        proxy.work();
    }
}

​​​​​​​
(动态代理)用法演示:

先定义两个接口:

package com.company;

public interface Buytickets {
    public void buytickets();
}
package com.company;

public interface Bookahotel {
    public void bookahotel();
}

 定义用户类:

package com.company;

public class User implements Buytickets,Bookahotel{

    @Override
    public void bookahotel() {
        System.out.println("开始预定酒店...");
        System.out.println("预定成功!");
    }

    @Override
    public void buytickets() {
        System.out.println("开始买票...");
        System.out.println("购票成功!");
    }
}

定义代理类:

package com.company;

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

public class CreatProxy implements InvocationHandler {
    private Object target;
    public Object creat(Object target)
    {
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);

    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("现在开始你的业务...");
        method.invoke(target,args);
        System.out.println("完成本次业务!");
        return null;
    }
}

测试类:

package com.company;

public class Main {

    public static void main(String[] args) {
            CreatProxy proxy=new CreatProxy();
            User user=new User();
            Bookahotel a= (Bookahotel) proxy.creat(user);
            a.bookahotel();
    }
}

 运行结果:

现在开始你的业务...
开始预定酒店...
预定成功!
完成本次业务!

5.类加载器原理分析

1、类的加载过程
JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)链接又分为三个步骤,如下图所示:
1) 装载:查找并加载类的二进制数据;
2)链接:
验证:确保被加载类的正确性;
准备:为类的静态变量分配内存,并将其初始化为默认值;
解析:把类中的符号引用转换为直接引用;



3)初始化:为类的静态变量赋予正确的初始值;
类加载器原理分析
2、类的初始化,类什么时候才被初始化:
1)创建类的实例,也就是new一个对象
2)访问某个类或接口的静态变量,或者对该静态变量赋值
3)调用类的静态方法
4)反射(Class.forName("com.vince.Dog"))
5)初始化一个类的子类(会首先初始化子类的父类)
6)JVM启动时标明的启动类,即文件名和类名相同的那个类
3、类的加载:
指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的Java.lang.Class对象,用来封装类在方法区类的对象。


6、JavaBean


什么是 JavaBean?
Bean理解为组件意思, JavaBean就是Java组件,在广泛的理解就是一个类,对于组件来
说,关键在于要具有“能够被IDE构建工具侦测其属性和事件”的能力。
一个JavaBean要具备这样的命名规则:
1、对于一个名称为xxx的属性,通常你要写两个方法:getXxx()和setXxx()。任何浏览这些
方法的工具,都会把get或set后面的第一个字母自动转换为小写。
2、对于布尔型属性,可以使用以上get和set的方式,不过也可以把get替换成is。
3、Bean的普通方法不必遵循以上的命名规则,不过它们必须是public的。
4、对于事件,要使用Swing中处理监听器的方式。如addWindowListener,
removeWindowListener
BeanUtils工具类:http://apache.org/

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

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

相关文章

c++:刷题必备 容器map的使用

文章目录 map的概念map的使用构造![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/30e9a697b50d47a591af6e9ae2bbb7d7.png)insert迭代器遍历 findoperator[]举例 map的概念 map是一个关联容器,里面的每一个位置pair,会存储两个值,一个是key,另一个是value. 我们可以…

【MySQL数据库开发设计规范】之表设计规范

欢迎点开这篇文章&#xff0c;自我介绍一下哈&#xff0c;本人姑苏老陈 &#xff0c;是一名JAVA开发老兵。 本文收录于 《MySQL数据库开发设计规范》专栏中&#xff0c;该专栏主要分享一些关于MySQL数据库开发设计相关的技术规范文章&#xff0c;定期更新&#xff0c;欢迎关注&…

使用 Docker 部署 VS Code in The Browser

1&#xff09;介绍 GitHub&#xff1a;https://github.com/coder/code-server 在日常学习工作中&#xff0c;Vscode 已成为我们首选的代码编辑器。然而&#xff0c;其局限性在于当我们从家到公司移动时&#xff0c;难以保持连续的编码体验。针对这一痛点&#xff0c;虽然市面上…

只需三步将Kimi接入微信公众号

今天我将手把手交大家如何把Kimi大模型接入微信公众号&#xff0c;创建属于你自己的公众号智能助理&#xff0c;让你的公众号具备智能对话、文件阅读、信息搜索等强大功能&#xff0c;同时提高用户互动率、减少人工客服压力等。 废话不多说&#xff0c;先来看看实际效果吧~ 一…

16 华三数据中心最流行的技术 M-LAG

STP和MTP&#xff08;第二十二课&#xff09;-CSDN博客 VRRP技术和浮动路由(第二十六课)_vrrp 浮动路由-CSDN博客 VRRP DHCP ACL NAT 网络核心路由技术综述 (第十课)-CSDN博客 04 交换机的IRF的配置-CSDN博客 1 M-LAG AI介绍 M-LAG&#xff08;Multi-Chassis Link Aggrega…

Electron学习笔记(一)

文章目录 相关笔记笔记说明 一、轻松入门 1、搭建开发环境2、创建窗口界面3、调试主进程 二、主进程和渲染进程1、进程互访2、渲染进程访问主进程类型3、渲染进程访问主进程自定义内容4、渲染进程向主进程发送消息5、主进程向渲染进程发送消息6、多个窗口的渲染进程接收主进程发…

【python】python淘宝交易数据分析可视化(源码+数据集)

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

模型推导:BG/NBD(预测用户生命周期(CLV)模型)

CLV&#xff08;Customer Lifetime Value&#xff09;指的是客户生命周期价值&#xff0c;用以衡量客户在一段时间内对企业有多大的价值。企业对每个用户的流失与否、在未来时间是否会再次购买&#xff0c;还会再购买多少次才会流失等问题感兴趣&#xff0c;本文中的BG/NBD模型…

PostgreSQL数据库创建只读用户的权限安全隐患

PostgreSQL数据库模拟备库创建只读用户存在的权限安全隐患 default_transaction_read_only权限授权版本变更说明 看腻了就来听听视频演示吧&#xff1a;https://www.bilibili.com/video/BV1ZJ4m1578H/ default_transaction_read_only 创建只读用户&#xff0c;参照备库只读模…

第三步->手撕spring源码之基于Cglib实现实例化策略

为什么深入研究spring源码&#xff1f; 其实每一个程序员每天的工作都是一贯的CRUD 实现业务和需求完成的操作。几年这样的操作让我感觉在这方面要提神能力 光靠CRUD是绝对不可能的事情 CRUD只是满足你作为一个搬砖人而已。编程能力提升&#xff1f;其实更多的编程能力的提升是…

用 Supabase CLI 进行本地开发环境搭建

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;Supabase CLI&#xff08;1.1&#xff09;安装 Scoop&#xff08;1.2&#xff09;用 Scoop 安装 Supabase CLI &#xff08;二&#xff09;本地项目环境&#xff08;2.1&#xff09;初始化项目&#xff08;2…

Promise.all和 race

Promise.all() all方法可以完成并行任务&#xff0c; 它接收一个数组&#xff0c;数组的每一项都是一个promise对象。返回值&#xff1a; 成功时&#xff1a;当数组中所有的promise的状态都达到resolved的时候&#xff0c;就返回包含所有 Promise 结果的数组&#xff0c;并且…

【C++】————类与对象(上)-基础知识

目录 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 类的两种定义方式&#xff1a; 成员变量命名规则的建议&#xff1a; 4.类的访问限定符及封装 4.1 访问限定符 ​编辑 【面试题】问题&#xff1a;C中struct和class的区别是什么&#xff1f; 4.2 封装 【面试…

数据分析中大数据和云计算

大数据和云计算 前言一、大数据二、大数据定义三、数据存储单位四、大数据存储技术五、大数据应用技术六、大数据特征七、数据容量八、数据类型的多样性结构化数据半结构化数据非结构化数据 九、获取数据的速度十、可变性十一、真实性十二、复杂性十三、价值十四、云计算十五、…

小白有什么副业可以做?

对于小白来说&#xff0c;以下是一些适合做副业的选择 1. 网络销售 可以在电商平台上开设小店&#xff0c;销售自己感兴趣的产品&#xff0c;如手工制品、二手物品、个人设计的商品等。 2. 做任务 目前网上最流行的就是做任务&#xff0c;因为简单无门槛&#xff0c;我推荐百…

partially initialized module ‘replicate‘ has no attribute ‘run‘

partially initialized module replicate has no attribute run(most likely due to a circular import) 在包名上停留查看impot 包的地址。 报错原因&#xff1a; 文件重名了&#xff0c;导入了 当前文件 。 修改文件名 即可。

分布式版本控制工具 - Git

文章目录 1. 概念介绍2. 客户端2.1 介绍2.2 仓库操作2.3 文件操作2.4 分支原理与操作2.5 标签2.6 远程仓库2.7 README与IGNORE 3. IDEA集成4. 版本号4.1 介绍4.2 文件操作4.2 分支操作 5. 命令5.1 介绍5.2 仓库操作5.3 文件操作5.4 分支操作5.5 标签操作5.6 远程仓库 1. 概念介…

【WebGPU】WebGPU 中的反应扩散计算着色器

在本教程中&#xff0c;我们将使用 WebGPU 技术中的计算着色器实现图像效果。更多精彩内容尽在数字孪生平台。 程序结构 主要构建两个 WebGPU 管道&#xff1a; 运行反应扩散算法多次迭代的计算管道&#xff08;js/rd-compute.js 和 js/shader/rd-compute-shader.js&#xff…

Linux学习之路 -- 文件系统 -- 缓冲区

前面介绍了文件描述符的相关知识&#xff0c;下面我们将介绍缓冲区的相关知识。 本质上来说&#xff0c;缓冲区就是一块内存区域&#xff0c;因为内核上的缓冲区较复杂&#xff0c;所以本文主要介绍C语言的缓冲区。 目录 1.为什么要有缓冲区 2.应用层缓冲区的默认刷新策略 …

【C++】STL — map和set的使用详细介绍

前言 本章将继续学习STL中的两个很重要的容器map和set&#xff0c;其底层实现是封装了一个红黑树&#xff0c;我们通过本节来学习和深入了解一下这两大容器。。。 序列式容器&#xff1a; string 、Vector、List 、dequeue 关联式容器&#xff1a;MAP 、SET、nordered_map、uno…