java反射学习(包含所有重点)

本文深入讲解Java反射机制,包括反射的概念、作用及如何使用。反射允许程序在运行时获取类的内部信息,如属性、方法等,从而实现代码的动态装配,降低耦合度。文章还介绍了获取字节码文件对象的三种方式,以及如何利用Class对象获取构造方法、成员变量和方法。

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

引言

反射这块内容在刚学习java之初并没有接触到,在工作以后发现有很多地方都用到了反射,比如代理模式。所以还是需要深入学习一下反射的知识。

什么是反射?

       Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。通俗的来说,我们可以通过反射获得一个类所有的东西。如果我们单单是new一个对象出来,是并不能得到一个类所有的东西的,并且我们必须提前知道需要new的是一个什么对象。

反射有什么用?

     反射能做的事情太多了,反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!

如何使用反射?

  • 获取字节码文件对象

      想要使用反射,必须先获得该类的字节码文件对象,也就是.class文件,然后通过Class对象,我们就可以获得我们想要的该类的所有信息。一个类只对应一个.class文件,不会出现另一个.class文件与之对应。
     获取字节码文件对象的方式有三种,分别是:

//通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。
1、Class clazz1 = Class.forName("全限定类名"); 
		
//当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。
2、Class clazz2  = Person.class;   
		
//通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段 
3、Class clazz3 = p.getClass();   

三种不同获取方式对应的类的阶段不同,所以我们可以根据阶段来选择创建的方式。

  • 使用字节码文件对象

     在得到了Class对象后,我们就可以通过Class对象来获取一个类的所有信息,我们可以获取该类的构造方法、成员对象、类方法、该类实现的所有接口等

1. 获取构造方法

获取构造方法主要有4种方式

方法用途
getConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructors()获得该类的所有公有构造方法
getDeclaredConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法

来看一个具体的例子:

public class User implements IUser{

	public User(){}
	
 	public User(int i){
		System.out.printlin("constructor public");	
	}

	
	private User(int i){
		System.out.printlin("constructor private");	
	}

	private int i;
	public String str;

	private int getInt(){
		return i;
	}

	public void set(int i,String s){
		this.i = i;
		str = s;
	}
	
	public void setStr(String s){
		str = s;
	}

}
//首先获取字节码文件对象
Class clazz = Class.forName(Reflect.User);
//获取所有公有构造方法
Constructor[] constructor1 = clazz.getConstrucors();
//获取与参数匹配的构造方法
Constructor constructor2 = clazz.getDeclaredConstructor(int.class);
//获取所有的构造方法
Constructor[] constructor3 = clazz.getDeclaredConstructors();

//通过有参构造函数创建对象
User user2 = (User) constructor2.newInstance(12);

在上面的例子里,获取了三个构造方法对象,获取到构造方法对象后,我们就可以通过constructor的newInstance()方法来创建对象。当然,我们也可以直接使用无参的构造方法来创建对象。

2.获取方法

同理,我们可以利用Class对象来获取该类的所有方法,Class获取对象方法的方法如下:

方法用途
getMethod(String name, Class…<?> parameterTypes)获得该类某个公有的方法
getMethods()获得该类所有公有的方法
getDeclaredMethod(String name, Class…<?> parameterTypes)获得该类某个方法
getDeclaredMethods()获得该类所有方法
//首先获取字节码文件对象
Class clazz = Class.forName(Reflect.User);
//获取所有公有方法
Method[] method1= clazz.getMethods();
//获取与参数匹配的方法
Method method2= clazz.getDeclaredMethod("set",int.class,String.class);
//获取所有的方法
Method [] method3 = clazz.getDeclaredConstructors();
//获取与参数匹配的某个公有方法
Method method2= clazz.getMethod("setStr",String.class);

获取到的Method对象可以实现很多功能,常用的Method类方法有:

静态方法名称说明
getName()获取该方法的名称
getParameterType()按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getRetumType()以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes()以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object…args)利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs()查看该方法是否允许带有可变数量的参数,如果允许返回 true,否 则返回 false
getModifiers()获得可以解析出该方法所采用修饰符的整数

3.获取成员变量

同理,我们可以利用Class对象来获取该类的所有成员对象,Class获取成员对象的方法如下:

方法用途
getField(String name)获得该类某个公有的属性对象
getFields()获得该类所有公有的属性对象
getDeclaredField(String name)获得该类某个属性对象
getDeclaredFields()获得该类所有属性对象

Field类中的主要方法有:

方法名称说明
get(Object obj)获取该方法的名称获得obj中对应的属性值
equals(Object obj)属性与obj相等则返回true
set(Object obj, Object value)设置obj中对应属性值

3.其他重要方法

方法名称说明
Class[] getInterfaces()确定此对象所表示的类或接口实现的接口返回值:接口的字节码文件对象的数组
isAnnotation()如果是注解类型则返回true
isAnnotationPresent(Class<? extends Annotation> annotationClass)如果是指定类型注解类型则返回true
isAnonymousClass()如果是匿名类则返回true
isArray()如果是一个数组类则返回true
isEnum()如果是枚举类则返回true
isInstance(Object obj)如果obj是该类的实例则返回true
isInterface()如果是接口类则返回true
isLocalClass()如果是局部类则返回true
isMemberClass()如果是内部类则返回true

反射在实际中的应用

java的反射机制就是增加程序的灵活性,避免将程序写死到代码里,
利用反射,在泛型为int的arryaList集合中存放一个String类型的对象
在这里插入图片描述
利用反射最常见的地方在代理模式,代理模式的使用这里就不再多写,有兴趣的可以继续关注我后面的博客~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值