Java反射机制【看这一篇就够啦!!!】

文章详细介绍了Java反射机制,包括其概念、为何使用以及如何使用。通过Class类,可以动态获取类信息、创建对象、调用方法和修改属性。示例代码展示了反射实例化、动态方法调用和读写属性的操作。反射在依赖注入框架、ORM、动态代理和自动化测试等方面有广泛应用。
摘要由CSDN通过智能技术生成

🥳🥳Welcome Huihui's Code World ! !🥳🥳

接下来看看由辉辉所写的关于反射机制的相关操作吧

目录

🥳🥳Welcome Huihui's Code World ! !🥳🥳

一.是什么

二.为什么要使用

三.怎么使用

💡辉辉小贴士:什么是Class类呢?

1.反射实例化 

2.反射动态方法调用

3.反射读写属性

💡辉辉小贴士:反射有这么多优点,那么我们什么时候可以使用反射呢?


一.是什么

反射机制是Java语言中的一种高级特性,它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式

二.为什么要使用

反射机制在Java中十分重要,因为它提供了很多优秀的功能和特性

  • 1. 动态地获取和使用类的信息
    • 反射机制可以在程序运行时动态地获取类的信息,例如类的名称、字段、方法、注解等信息,从而进行一些动态操作,例如在JUnit中实现自动化测试时,通过反射获取类的所有测试方法,然后自动进行测试。
  • 2. 动态地创建和使用类的实例对象
    • 通过反射机制,我们可以动态地在程序运行时创建类的实例对象,这种方式使得代码更加灵活,可以根据业务需求动态地创建对象。例如在Spring框架中,就通过反射机制实现了依赖注入,并动态创建Bean实例。
  • 3. 动态地调用和修改类的方法和字段
    • 反射机制也可以处理类的方法和字段,通过反射机制,我们可以动态地调用和修改类的方法和字段,这种方式使得代码更加灵活和扩展性更强。例如在使用AOP技术时,就可以通过反射机制动态地调用目标方法,并实现一些统一的处理。
  • 4. 实现更加灵活的框架和工具
    • 反射机制可以为框架和工具提供更加灵活、可扩展和易用的接口,从而实现更加高效和智能的应用程序。例如在ORM框架中,通过反射机制可以将数据库中的表映射成Java类,从而实现快速地对表进行操作。

总而言之,反射机制可以为Java应用程序提供更加灵活、高效和智能的开发方式,通过反射机制,我们可以在程序运行时动态地调用和使用类的信息、方法和字段,从而实现更加高效和智能的应用程序

三.怎么使用

在学习怎么使用反射机制之前,我们需要知道Java反射机制的核心是Class类

💡辉辉小贴士:什么是Class类呢?

  • 在Java的反射机制中,"类类"通常指Class类。Class类是Java中用来表示一个类的类
  • 在Java程序运行时,每个类都会对于一个Class对象,Class对象包含了该类的各种元信息,例如类的名称、字段、方法等
  • 借助Class对象,Java程序可以在运行时动态地创建类的实例、调用类的方法等操作,这就是反射机制的基本功能之一
  • Class类中定义了很多方法,包括获取类的基本信息、实例化对象、获取字段和方法、修改字段和调用方法等,是Java反射机制的重要组成部分

上述描述还是太过于抽象,下面我们将通过代码更清晰的了解到什么是类类

package com.wh.reflect;

public class Demo1 {
	/**
	 * 什么是类类
	 */

	// ①🐱猫类🐱里面会有很多的小猫,例如咪咪,加菲猫...
	// ②🐕狗类🐕里面也会有很多小狗,例如旺财,来福...
	// ③人类里面也会有很多小人,例如夏威大傻逼,王辉大美女

	// 咪咪,加菲猫是猫类的实例
	// 旺财,来福是狗类的实例
	// 夏威大傻逼,王辉大美女是人类的实例

	// 那么人类,狗类,猫类又是谁的实例呢?
	// 在这里我们就可以引入Class类的概念了:Class类是Java中用来表示一个类的类
	// 所以人类,狗类,猫类都是Class类的实例!!!!

	/**
	 * 1.2为什么要学习类类
	 * @throws Exception 
	 */
	// 因为Class类是Java反射机制的基础之一

	public static void main(String[] args) throws Exception {
		/**
		 * 1.3怎么获取类类
		 */
		 Student stu = new Student();
		
		 //1.对象.getclass
		  Class c1 = stu.getClass();
		  System.out.println(c1);
		
		//2.类名.class
		 Class c2 = Student.class;
		 System.out.println(c2);// class com.wh.reflect.Student
		
		//3.Class.forName("全路径名");
		 Class c3=Class.forName("com.wh.reflect.Student");
		 System.out.println(c3);
	}

}

相信通过以上代码,我们已经能够了解到什么是类类了,那么接下来我们就看看反射机制到底怎么使用吧!!

对于反射机制的使用操作,全部以Student类作为实例👇👇

package com.wh.reflect;

public class Student {
	private String sid;

	private String sname;

	public Integer age;
	
	static{
		System.out.println("加载进jvm中!");
	}

	public Student() {
		super();
		System.out.println("调用无参构造方法创建了一个学生对象");
	}

	public Student(String sid) {
		super();
		this.sid = sid;
		System.out.println("调用带一个参数的构造方法创建了一个学生对象");
	}

	public Student(String sid, String sname) {
		super();
		this.sid = sid;
		this.sname = sname;
		System.out.println("调用带二个参数的构造方法创建了一个学生对象");
	}

	@SuppressWarnings("unused")
	private Student(Integer age) {
		System.out.println("调用Student类私有的构造方法创建一个学生对象");
		this.age = age;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public void hello() {
		System.out.println("你好!我是" + this.sname);
	}

	public void hello(String name) {
		System.out.println(name + "你好!我是" + this.sname);
	}

	@SuppressWarnings("unused")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}
}

1.反射实例化 

 反射实例化的方法
newInstance()来创建指定类的实例对象
getConstructor(Class)调用公共的有参构造器,括号中的参数是构造器中的参数类型的类类
getDeclaredConstructor(Class)调用私有的有参构造器,括号中的参数是构造器中的参数类型的类类
setAccessible(Boolean)该方法用于设置方法、字段或者构造方法在访问时,是否需要在访问时取消Java语言访问修饰符的限制。也就是说,如果设置为 true,那么反射对象在使用时就不再需要考虑它的访问修饰符的限制。简而言之就是,可以调用到私有的方法、字段或者构造方法
package com.wh.reflect;

import java.lang.reflect.Constructor;

/**
 * 什么是反射?
	 * 反射机制是Java语言中的一种高级特性,
	 * 它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。
	 * 与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式
	 * 
 * 反射实例化 
 * 
 * @author W
 *
 */
public class Demo2 {
public static void main(String[] args) throws Exception {
	//一切反射从类类开始
	Class cla =Class.forName("com.wh.reflect.Student");
	
	//1.调用无参构造器【如果写了有参构造器,那么一定要记得补一个无参构造器】
	Student stu1 = (Student) cla.newInstance();//调用无参构造方法创建了一个学生对象
	System.out.println(stu1);//com.wh.reflect.Student@7852e922
	
	//2.调用有一个参构造器
	Constructor constructor1=cla.getConstructor(String.class);
	Student stu2 = (Student)constructor1.newInstance("wh1");//调用带一个参数的构造方法创建了一个学生对象
	System.out.println(stu2);//com.wh.reflect.Student@4e25154f
	
	//3.调用带两个/多个参数的构造器
	Constructor constructor2=cla.getConstructor(String.class,String.class);
	Student stu3 = (Student)constructor2.newInstance("wh1","王辉");//调用带二个参数的构造方法创建了一个学生对象
	System.out.println(stu3);//com.wh.reflect.Student@70dea4e
	
	//4.调用私有的有一个参构造器的方法
	Constructor constructor3=cla.getDeclaredConstructor(Integer.class);
	constructor3.setAccessible(true);
	Student stu4 = (Student) constructor3.newInstance(11);//调用Student类私有的构造方法创建一个学生对象
	System.out.println(stu4);//	com.wh.reflect.Student@5c647e05
	
}
}

注意1:在我们使用newInstance()方法,去调用特定对象的无参构造器时,我们一定要保证其里面有无参构造器【如果写了有参构造器,那我们需要补一个无参构造器】

如果没有写无参构造器的话,那么将会抛出一个异常

 注意2:在我们调用私有的方法、字段或者构造方法时,如果没有在调用之前使用setAccessible这个方法,则无法调用到私有的方法、字段或者构造方法,并且还会抛出一个异常

2.反射动态方法调用

反射动态方法调用中的方法
newInstance()来创建指定类的实例对象
getMethod(String, Class...)获取到特定对象中的共有的方法,第一个参数是方法的名字,第二个是一个可变参数,是该方法中的参数类型的类类
getDeclaredMethod(String, Class)获取到特定对象中的私有的方法,第一个参数是方法的名字,第二个是一个可变参数,是该方法中的参数类型的类类
 invoke(Object,Object... args) 根据传入的对象和参数,动态地在运行时调用指定对象的指定方法,返回的值是该方法的返回值,如果没有返回值,则该值为null
setAccessible(Boolean)该方法用于设置方法、字段或者构造方法在访问时,是否需要在访问时取消Java语言访问修饰符的限制。也就是说,如果设置为 true,那么反射对象在使用时就不再需要考虑它的访问修饰符的限制。简而言之就是,可以调用到私有的方法、字段或者构造方法
package com.wh.reflect;

import java.lang.reflect.Method;

/**
 * 什么是反射?
	 * 反射机制是Java语言中的一种高级特性,
	 * 它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。
	 * 与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式
	 * 
 * 反射动态方法调用
 * @author W
 *
 */
public class Demo3 {
public static void main(String[] args) throws Exception {
		// 一切反射从类类开始
		Class cla = Class.forName("com.wh.reflect.Student");
		Student stu = (Student) cla.newInstance();

		// 1.调用无参方法
		Method m1 = cla.getMethod("hello");
		System.out.println(m1);// public void com.wh.reflect.Student.hello()
		Object invoke1 = m1.invoke(stu);// 你好!我是null
		System.out.println(invoke1);// null

		// 2.调用有参的方法
		Method m2 = cla.getMethod("hello", String.class);
		System.out.println(m2);// public void com.wh.reflect.Student.hello(java.lang.String)
		Object invoke2 = m2.invoke(stu, "傻逼");// 傻逼你好!我是null
		System.out.println(invoke2);// null

		// 3.调用私有的有参方法
		Method m3 = cla.getDeclaredMethod("add", Integer.class, Integer.class);
		System.out.println(m3);// private java.lang.Integer
								// com.wh.reflect.Student.add(java.lang.Integer,java.lang.Integer)
		m3.setAccessible(true);
		Object invoke3 = m3.invoke(stu, 1, 1);
		System.out.println(invoke3);// 2
				
}
}

3.反射读写属性

反射读写属性所用到的方法
getDeclaredField(String)拿到特定对象中特定的属性
getDeclaredFields()拿到特定对象中所有的属性
getName()拿到特定对象中所有的属性的属性名
get(Object)拿到特定对象中所有的属性的属性值,传入的参数为特定对象的对象名
set(Object ,Object)为指定对象修改指定的属性值
setAccessible(Boolean)该方法用于设置方法、字段或者构造方法在访问时,是否需要在访问时取消Java语言访问修饰符的限制。也就是说,如果设置为 true,那么反射对象在使用时就不再需要考虑它的访问修饰符的限制。简而言之就是,可以调用到私有的方法、字段或者构造方法
package com.wh.reflect;

import java.lang.reflect.Field;

/**
 * 什么是反射?
	 * 反射机制是Java语言中的一种高级特性,
	 * 它可以在程序运行时动态获取类的信息、实例化对象、调用方法、访问和修改属性等。
	 * 与之相对的是静态编译时期的程序设计方式,也是Java最初的设计方式
	 * 
 * 反射读写属性
 * @author W
 *
 */
public class Demo4 {
	public static void main(String[] args) throws Exception {
		// 一切反射从类类开始
		Class cla = Class.forName("com.wh.reflect.Student");
		Student stu = new Student("wh2", "小王辉");
		stu.age=22;
		
		
		/**
		 * 修改对象中的属性
		 */
		 Field ageField = cla.getDeclaredField("age");
		 ageField.setAccessible(true);
		 ageField.set(stu, 18);
		 
		 
		 
		/**
		 * 老版本:拿到student类的所有属性【也就是拿到某一个特定对象的所有的属性】
		 */
		//以前用的方式
		String sid = stu.getSid();
		System.out.println(sid);//wh2
		String sname = stu.getSname();
		System.out.println(sname);//小王辉
		
		

		/**
		 * 新版本:拿到student类的所有属性【也就是拿到某一个特定对象的所有的属性】
		 */
		Field[] declaredFields = cla.getDeclaredFields();
		for (Field field : declaredFields) {
			field.setAccessible(true);
			System.out.println(field.getName()+":"+field.get(stu));//sid:wh2  sname:小王辉  	age:22
		}
		
		
		
	}
}

💡辉辉小贴士:反射有这么多优点,那么我们什么时候可以使用反射呢?

那就让我们来看看它的应用场景吧!!

  • 1. 依赖注入框架
    • 依赖注入(DI)框架可以通过反射机制来创建实例对象,并通过注解或XML配置来设置对象的属性和方法。例如Spring框架中的@Autowired注解就是通过反射机制来实现依赖注入。
  • 2. ORM框架
    • 对象关系映射(ORM)框架可以通过反射机制来将数据库中的表映射成Java类,并进行相关的增删改查操作。例如Hibernate框架就是使用反射机制来将数据库表映射为Java对象。
  • 3. 实现动态代理
    • 动态代理技术可以通过反射机制动态生成代理对象,并进行相关的操作。例如在AOP编程中,就可以通过动态代理技术实现统一的日志、事务等操作。
  • 4. 实现自动化测试
    • 通过反射机制,可以在运行时获取类的信息和方法信息,从而实现自动化测试的功能。例如JUnit框架就是通过反射机制来获取测试类和测试方法的信息,并进行测试操作。
  • 5. 实现插件化
    • 通过反射机制,可以实现插件化的功能。例如在Eclipse IDE中,就可以通过定义扩展点和插件来实现插件化的功能。

               好啦,今天的分享就到这了,希望能够帮到你呢!😊😊              

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是辉辉啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值