飞道的博客

J2SE基础_JAVA反射基础解析

363人阅读  评论(0)

很多优秀的开源框架基本原理就是反射,我认为自己不能不重视它 2020.04.18

一、简单了解Java.lang.reflect包

反射机制的相关类
Class类:代表类的实体,在运行的Java应用程序中表示类和接口
Field类:代表类的成员变量(成员变量也称为类的属性)
Method类:代表类的方法
Constructor类:代表类的构造方法
首先做了一个演示类,方便你下面测试

package bao.reflectDemo;

public class ReflectDemo {
	public String demoString = "希望";
	public int demoInt = 1314;
	private double demoDouble = 1314.00;
	
	public ReflectDemo(String demoString ,int demoInt,double demoDouble) {
		this.demoString = demoString;
		this.demoInt = demoInt;	
		this.demoDouble = demoDouble;
	}
	
	private ReflectDemo(double demoDouble) {
		this.demoDouble = demoDouble;
	}
	
	public ReflectDemo() {		
	}

	private void printDemoDouble(double demoDouble) {
		this.demoDouble = this.demoDouble + demoDouble;
		System.out.println(this.demoDouble);
	}
}

二、基本反射技术

我给分为三种,详情请看代码注解

package bao.reflectTest;

import org.junit.jupiter.api.Test;

public class ReflectTest {
	@Test
	public void test() {
		
		//1、根据字符串来创建一个类,由于字符串可能存在问题,所以要加捕获异常
		try {
			Class<?> testClass1 = Class.forName(new String("java.lang.String"));
			System.out.println(testClass1.getName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		//2、根据基本类型.TYPE
		Class<Boolean> testClass2 = Boolean.TYPE;
		System.out.println(testClass2.getName());
		
		//3、根据已创建的对象.getClass
		ReflectTest reflectTest = new ReflectTest();
		Class<? extends ReflectTest> testClass3 = reflectTest.getClass();
		System.out.println(testClass3.getName());	
	}
	
	@Test
	public void test2() {
		
	}
}

运行结果:

三、获取类的成员

正常情况下,我们无法使用其他类的私有方法和变量,但是反射却能帮我做到使用私有方法和变量。
这里开始我就开始引用零里写的类啦
1、我们用getDeclaredConstructors()方法,把类里的构造方法返回给一个Constructors()数组
2、getModifiers()返回了当前构造方法修饰符的特定的字节码,再通过Modifier.toString()来转换成人能读懂的字符串,哈哈
3、getParameterTypes()返回的是参数类型的数组,用Class数组接收
4、getName()获取Class的全类名

	@Test
	public void test2() {
		//获取类的构造方法列表
		ReflectDemo reflectTest = new ReflectDemo();
		Class<?> testClass1 = reflectTest.getClass();
		Constructor<?>[] constructors = testClass1.getDeclaredConstructors();
		
		//获取类的构造方法的参数
		for(int i = 0; i<constructors.length;i++) {
			System.out.println(Modifier.toString(constructors[i].getModifiers())+":");
			Class<?>[] para = constructors[i].getParameterTypes();
			for(int j = 0; j<para.length;j++) {
				System.out.print(para[j].getName()+" ; ");
			}
			System.out.println();
		}
	}

运行结果:

这样我们就得到了类中所有构造方法和构造方法中的参数,那么我们如何获取特定的构造方法呢?

	@Test
	public void test3() {
		// 获取类的特定构造方法
		ReflectDemo reflectTest = new ReflectDemo();
		Class<?> testClass1 = reflectTest.getClass();
		Constructor<?> constructor = null;
		try {
			constructor = testClass1.getDeclaredConstructor(String.class,int.class);
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}

		// 获取类的构造方法的参数
		System.out.println(Modifier.toString(constructor.getModifiers()) + ":");
		Class<?>[] para = constructor.getParameterTypes();
		for (int j = 0; j < para.length; j++) {
			System.out.print(para[j].getName() + " ; ");
		}
	}

运行结果:

我们现在要开始调用构造函数啦

	@Test
	public void test4() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<?> testClass1 = ReflectDemo.class;
		Constructor<?> constructor = testClass1.getDeclaredConstructor(double.class);
		constructor.setAccessible(true);
		constructor.newInstance(520.1314);
	}

运行时变量的变化:

调用私有的方法

	@Test
	public void test5() throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		Class<?> testClass1 = ReflectDemo.class;
		Object test = testClass1.newInstance();
		Method method =  testClass1.getDeclaredMethod("printDemoDouble", double.class);	
		method.setAccessible(true);
		method.invoke(test, 480.1314);
	}

运行结果:

获取类的私有字段并修改值

	@Test
	public void test6() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
		Class<?> testClass1 = ReflectDemo.class;
		Object test = testClass1.newInstance();
		Field field = testClass1.getDeclaredField("demoDouble");
		field.setAccessible(true);
		field.set(test,1.0);
		System.out.println(field.get(test).toString());
	}

这篇文章的意义仅仅是熟悉一下基础语法入门,抛砖引玉,未来还要不断思考
参考链接


转载:https://blog.csdn.net/loveloose/article/details/105593538
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场