关于反射

本文深入讲解Java反射机制,包括Class类的使用,如何获取类的方法、成员变量、构造函数信息,以及如何通过反射调用方法和操作集合泛型,绕过编译限制。

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

一、Class类

  • 在面对对象编程中,万事万物皆对象,但是类本身又是谁的对象呢? 他是java.lang.Class的对象
  • 获取类类型的3种方法
  1. 通过对象类的对象获取
Foo foo = new Foo();
Class class1 = foo.getClass();
  1. 通过类名获取
Class class2 = Foo.class;
  1. 还是通过类名获取,但是要try catch, 并且要转换类型
try {
	Class class3 = (Class) Class.forName("Foo");
} catch (ClassNotFoundException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}

二、获取类的方法信息

  • 一个成员方法就是Method类的对象
  • getMethods()是获得该类的所有public方法,包括从父类继承来的方法
Method[] methods1 = class1.getMethods();
  • getDeclaredMethods()是获取当前类自己声明的成员方法,不包含父类继承来的,但是不问访问权限
Method[] methods2 = class1.getDeclaredMethods();
  • 得到返回值类型,先得到返回值类型的类类型,再获得名字
Class returnType = methods1[i].getReturnType();
String returnTypeName = returnType.getName();

  • 得到方法名
for (int i = 0; i < methods1.length; i++) {
	System.out.println(methods1[i].getName());
}
  • 得到参数类型,因为参数可能有多个,所以先得到参数列表,再遍历它得到参数类型的名字
Class[] paramTypes = methods1[i].getParameterTypes();
	for (Class paramType : paramTypes) {
		String paramTypeName = paramType.getName();
}

三、获取成员变量的信息

  • 成员变量是java.lang.reflect.Field类的对象
  • getFields()获得的是所有public的成员变量
Field[] fields1 = class1.getFields();
  • getDeclaredFields()获得的是自己声明的所有的成员变量
Field[] fields2 = class1.getDeclaredFields();
  • 获得成员变量类型的名称
for (Field field : fields2) {
	Class fieldType = field.getType();
	String fieldTypeName = fieldType.getName();
}
  • 获得成员变量名称
String fieldName = field.getName();

四、获取构造函数的信息

  • 构造函数是java.lang.reflect.Constructor的对象
  • 获得构造函数,方法基本同上
Constructor[] constructors1 = class1.getConstructors();
Constructor[] constructors2 = class1.getDeclaredConstructors();
  • 获得构造参数类型
for (Constructor constructor : constructors2) {
	Class[] paramTypes = constructor.getParameterTypes();
	for (Class paramType : paramTypes) {
		String paramTypeName = paramType.getName();
	}
}
  • 获得构造方法名称
String csName = constructor.getName();

五、 反射调用方法

public class A {
	public void print(int a, int b) {
		System.out.println(a + b);
	}
	
	public void print(String a, String b) {
		System.out.println(a.toUpperCase() + b.toLowerCase());
	}
}
  • 获取方法对象,先获得类类型,再操作
A a1 = new A();
Class clazz = a1.getClass();
// 这里第一个参数表示方法名,后面的是参数的类类型,如果没参数,就不传
// 要唯一确定一个方法,就得确定他的方法名和参数类型
Method m = clazz.getMethod("print", int.class, int.class);
  • 反射调用方法
// 这里是方法对象调用invoke方法,第一个参数是对象,后面的是参数,没参数就不写
//普通调用方法为:a1.print(10,20);
m.invoke(a1, 10, 20);

六、通过反射操作绕过编译,以集合泛型为例

public class MethodDemo1 {
	public static void main(String[] args) {
		ArrayList list1 = new ArrayList();
		ArrayList<String> list2 = new ArrayList<String>();
		Class c1 = list1.getClass();
		Class c2 = list2.getClass();
		/**
		 * 反射的操作都是在编译之后进行的
		 * c1 == c2 返回ture 说明编译之后集合的泛型是去泛型话的
		 * java种集合的泛型,是防止错误输入的,只再编译阶段有效,绕过编译就无效了
		 */
		// list2.add(29); 错误
		System.out.println(c1 == c2); // true
		
		/**
		 * 通过方法的反射操作来绕过编译
		 * c1 == c2 所有下面用c1还是c2都一样
		 */
		try {
			Method m = c2.getMethod("add", Object.class);
			// 绕过编译操作就绕过了泛型
			m.invoke(list2, 100);
			System.out.println(list2);
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
	}
}

转载于:https://www.cnblogs.com/xgzzzy16/p/9808965.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值