反射机制与动态代理

本文深入解析Java反射机制的基础概念与应用,包括如何在运行时动态调用类的属性与方法,以及通过三种方式获取字节码文件对象。同时,文章详细介绍了动态代理的设计模式,展示了如何使用JDK提供的Proxy类和InvocationHandler接口创建动态代理对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以前学习基础的时候不知道哪些是重点,也不会注意,自己动手少,用的少,自然也不会知道,就落下了知识点,当被问反射机制起来时,听过,但怎么说,到底是怎么一回事,脑子一片空白,答不上来,也觉得惭愧。

 

一.什么是反射机制?

 

在运行期中,对于任意一个类,都能够调用某一个类的属性与方法,或者对与一个对象,任意的对象都能调用这个对象的属性和方法,这个类或对象相对其他类或对象像是透明的。这种动态的调用其他类或者对象的属性和方法就叫做反射机制,JAVA反射机制:"程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言",这样说你可能会感觉模模糊糊的,不太懂。

反射机制通过或者某个类或对象的字节码文件对象(.class),这是必须的,通过字节码对象就能获取该类的属性和方法,

 

获取字节码文件对象的三种方式,针对不同情况下选择合理的使用

 

1、

源码阶段,并没有变成字节码文件

//创建源码期的字节码文件对象,参数为类的路径即包名+类名,相对路径即类名

Class a = Class.forName("A");

//创建实例对象

A a1 = (A)a.newInstance();

2、

编译期后字节码阶段

//创建编译期的字节码文件对象

Class a = A.class;

3、

创建对象阶段

//创建对象

A as = new A();

//创建对象期的字节码文件对象

Class a = as.getClass();

通过反射机制过去的字节码文件对象能干嘛?

 

假设已存在A类

1.创建实际对象

//创建编译期的字节码文件对象

Class a = A.class;

//创建实例对象

A a1 = (A)a.newInstance();

 

2.获取该类的构造器

//创建编译期的字节码文件对象

Class a = A.class;

//通过字节码对象获取无参构造器,通过构造器创建实例对象

Constructor constructor = a.getConstructor();

A a2 =(A)constructor.newInstance();

//带参构造器

Constructor constructor1 = a.getConstructor(String.class);

System.out.println("初始化带参构造器");

A a3 = (A)constructor1.newInstance("削功名");

 

3.获取该类的属性并输出


 

//创建实例对象

Class a = A.class;

A a1 = (A)a.newInstance();

//调用该类的属性,形参传入属性名

Field field = a.getDeclaredField("name");

//及那个私有的属性打开权限

field.setAccessible(true);

//get方法参数传入该类的实例对象

System.out.println(field.get(a1));

4.获取该类的方法并执行

//创建编译期的字节码文件对象

Class a = A.class;

//创建实例对象

A a1 = (A)a.newInstance();

//调用该类方法(参数为该类的方法名)

Method method = a.getMethod("hello");

//参数传入一个实例参数

method.invoke(a1);

 

 

二.动态代理

 

1.什么是动态代理?

动态代理是一种设计模式,可以这么理解,比如自己需要买一瓶水,自己不想动,叫人帮买一瓶水。这个代理对象是在程序运行过程中创建的,这个我们反射机制一样在程序运行过程中来实例化对象、调用方法等操作。

 

创建代理对象需要使用 ava.lang.reflect下的 Proxy 类 和 InvocationHandler 接口; JDK提供的代理只能针对接口做代理,这意味着我们返回的必须是一个接口对象。更强的代理通过Proxy的newProxyInstance()方法创建动态代理对象。

1、创建一个接口,在接口中写个方法


 

public interface A {

void buy();

}

2.创建一个InvocationHandle 代理对象

public class B implements InvocationHandler {

private Object target;



public B(Object a){

this.target = a;

}



@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

method.invoke(target,args);

System.out.print("代理对象: 某某");

return null;

}

}

 

3.创建一个实例类,并通过代理执行

public class C implements A {



@Override

public void buy() {

System.out.println("买水");

}



public static void main(String[] args) {

C a = new C() ;

//本身来做

a.buy();

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

//传入一个实例对象

B b = new B(a);

/**

* JDK提供的接口只能针对接口做代理。因此返回必须是个接口

* 参数为 实例对象的类加载器,类实现的所有接口的对象,代理对象

*/

A aa = (A)Proxy.newProxyInstance(a.getClass().getClassLoader(),a.getClass().getInterfaces(),b);

//代理来做

aa.buy();

}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值