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

news2024/10/6 4:12:37

目录

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/

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

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

相关文章

【计算机毕业设计】基于微信小程序文章管理系统

随着 计算机技术的成熟&#xff0c;互联网的建立&#xff0c;如今&#xff0c;PC平台上有许多关于文章管理方面的应用程序&#xff0c;但由于使用时间和地点上的限制&#xff0c;用户在使用上存在着种种不方便&#xff0c;而开发一款基于微信小程序的文章管理系统&#xff0c;能…

基于机器学习的网络流量识别分类(完整资源收米)NetFlow-Sentry

项目介绍 这是一个名为NetFlow-Sentry的项目&#xff0c;项目实现了对网络流量的实时检测&#xff0c;特征抓取&#xff0c;内置了基于Pytorch的深度学习模型来进行流量分类。该项目除可以进行实时特征提取&#xff0c;还提供了网络流量数据的输入口&#xff0c;可以直接识别分…

并发——进程

1. 程序 程序&#xff08;program&#xff09;是什么&#xff1f; 计算机程序&#xff08;computer program&#xff09;一般是指以某些程序设计语言编程&#xff0c;能够运行于某种目标体系结构上 程序 数据结构 算法 数据结构&#xff1a;用来表示人们思维对象的抽…

mysql的存储结构

一个表就是一个ibd文件 .ibd文件大小取决于数据和索引&#xff0c;在5.7之后才会为每个表生成一个独立表空间即一个ibd文件&#xff0c;在此之前&#xff0c;所有表默认下都会存储在“系统表空间”&#xff08;共享表空间&#xff09;&#xff0c;所有表都在一个ibd文件。 inn…

我的全新官网

科技语者-探索未来的语言和沟通 (chgskj.cn) 另外我还开放了一个网站科技语者-介绍页 (null.fit)

Verilog复习(四)| 组合逻辑

一位全加器结构描述&#xff1a; 数据流描述&#xff1a; 行为描述&#xff1a; 只要有事件发生&#xff08;列表中任何 信号有变化&#xff09;&#xff0c;就执行begin…end 的语句 。 always的事件控制方式 边沿触发 always (posedge clk) // clk从低电平->高&#x…

使用Flask构建POST请求的Web应用

文章目录 准备工作创建路由处理POST请求创建表单页面运行应用结论 在Web开发中&#xff0c;处理POST请求是一项常见任务&#xff0c;特别是在构建表单提交、用户注册和数据提交等功能时。Flask是一个简单而强大的Python Web框架&#xff0c;它提供了方便的工具来处理HTTP请求&a…

答辩PPT自述稿如何与幻灯片同步?笔灵AI一键生成功能解析

在我原本的认知里面&#xff0c;答辩PPT是要包含论文各个章节的&#xff0c;在答辩时需要方方面面都讲到的&#xff0c;什么摘要、文献综述、实证分析、研究结果样样不落。但是&#xff0c;这大错特错&#xff01; 答辩PPT环节时长一般不超过5分钟&#xff0c;老师想要的答辩P…

Postman工具介绍与安装

一、Postman介绍 Postman 乃是一款对 HTTP 协议予以支持的接口调试及测试工具&#xff0c;其突出特性在于功能强大&#xff0c;并且使用简便、易用性良好。不管是开发人员开展接口调试工作&#xff0c;还是测试人员进行接口测试任务&#xff0c;Postman 均属于首选工具之一。 接…

面试八股之Redis篇2——redis分布式锁

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…

图书馆APP开发解决方案

uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 框架支持:springboot/Ssm/thinkphp/django/flask/express均支持 前端开发:vue.js 可选语言&#xff1a;pythonjavanode.jsphp均支持 运行软件…

blender 为世界环境添加纹理图像

1、打开世界环境配置项 2、点击颜色右侧的黄色小圆&#xff0c;选择环境纹理 3、打开一张天空图像 4、可以通过调整强度/力度&#xff0c;调整世界环境的亮度

ambari-server高可用配置方案

制品 https://kdocs.cn/l/cie4hSgvUunX 前置条件 环境需要支持VRRP协议 环境需要配置好yum源 变更影响面 变更不会影响其他组件 配置lb(需要客户侧配置并提供LB地址) 转发方式选择 主备 监听端口为8080、8440、8441 协议为tcp 后端监听选择kde-offline1为主 后端监听选择kde-…

QT-小项目:连接MY SQL数据库实现登录(下一章实现登录注册账号和忘记密码功能)

一、环境准备 1、下载MYSQL 64位&#xff0c;安装完成&#xff0c;制作简易数据库教程如下&#xff1a; MY SQL安装 2、QT 编译器使用 二、实现工程目录&#xff08;基于上一章基础上&#xff09; 三、源程序增加内容如下&#xff1a; login.cpp 增加头文件&#xff1a; #in…

MES系统与WMS集成方法(满分100学习资料)

导语 大家好&#xff0c;我是智能仓储物流技术研习社的社长&#xff0c;老K。专注分享智能仓储物流技术、智能制造等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料&#xff0c;请球友到知识星球【智能仓储物流技术研习社】自行下载 这份文件是关于MES系…

头歌C语言数据结构(队列的应用)

第1关&#xff1a;循环队列 任务描述 本关任务&#xff1a;编写一个循环队列&#xff0c;实现入队、出队操作&#xff0c;判断队空、队满等特殊情况。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.循环队列定义&#xff0c;2.入队、出队的定义&#xff…

别的项目都有 awesome 仓库,RT-Thread 也要有!

awesome 仓库是 GitHub 上用于收集某个项目或者某个语言相关的优质内容的仓库&#xff0c;例如中间件、新闻资讯、网站等。 作为 RT-Thread 开发者&#xff0c;看到别的项目都有 awesome 仓库&#xff0c;我想 RT-Thread 也应该有&#xff01; 于是&#xff0c;我创建一个 aw…

pyqt5将ui文件转为python文件

在pyqt5中使用 pyuic将ui文件转为py文件&#xff1a; 例如&#xff1a;将home.ui文件转为vio_detect.py文件&#xff0c;所需命令如下&#xff1a; pyuic5 -x home.ui -o vio_detect.py

Python彻底解决TypeError的问题

今天看到一个问题&#xff1a; TypeError: int() argument must be a string, a bytes-like object or a number, not list 代码是这样的&#xff1a; id int(os.path.split(imagePath)[1].split(.)[0]) 其实这个提示已经非常明显了&#xff0c;百度翻译过来就是&#xff1a…

废品回收微信小程序基于FastAdmin+ThinkPHP+UniApp(源码搭建/上线/运营/售后/更新)

一款基于FastAdminThinkPHPUniApp开发的废品回收系统&#xff0c;适用废品回收站、再生资源回收公司上门回收使用的小程序。 一、FastAdmin框架特色功能及优势 模块化开发&#xff1a;控制器、模型、视图、JS一一对应&#xff0c;使用RequireJS进行插件机制&#xff0c;支持插…