前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

反射

作者头像
发布2022-05-10 09:47:21
2730
发布2022-05-10 09:47:21
举报
文章被收录于专栏:后端JavaEE

一、概述:什么是反射?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

.class字节码文件中,包含了Java文件的所有内容:

代码语言:javascript
复制
    在Java文件运行过程中,当前程序需要哪一个类参与代码执行,那么就需要加载这个类的.class字节码文件,该.class字
节码文件时在程序的加载阶段,存在于内存的【代码区】
	
	.class字节码文件既然加载到内存的【代码区】
	.class文件中包含对应Java程序的所有内容
	代码区存在一块空间 ==> .class ==> Java程序的所有内容

二、反射必会方法

2.1 Class涉及到的方法用来获取类对象

  1. Class Class.forName(String packageNameAndClassName);
  2. Class 类名.class;
  3. Class 类对象.getClass();
代码语言:javascript
复制
public class GetClassObject {
	public static void main(String[] args) throws ClassNotFoundException {
		System.out.println(123456);
		
		Class<?> forName = Class.forName("com.qfedu.a_reflect.Person");
		
		Class<com.qfedu.a_reflect.Person> cls = Person.class;
		
		Class<? extends Person> class1 = new Person().getClass();
		
		System.out.println(forName == cls);
		System.out.println(class1 == cls);
		System.out.println(class1 == forName);
	}
}

注: .class文件占用的空间独一份,不管通过哪一种方式获取对应的Class类对象都是同一个对象

2.2Constructor 构造方法类涉及到的方法

代码语言:javascript
复制
	1. public Constructor[] getConstructors();
		获取当前Class类对象对应Java文件中,所有【public修饰构造方法的类对象数组】
代码语言:javascript
复制
	2. public Constructor[] getDeclaredConstructors();
		【暴力反射】
		获取当前Class类对象对应Java文件中,所有【构造方法的类对象数组】,包括私有化构造方法。
代码演示
代码语言:javascript
复制
/*
 * 操作Constructor
 */
public class GetConstructorObject {
	public static void main(String[] args) 
			throws ClassNotFoundException, 
			NoSuchMethodException, SecurityException, 
			InstantiationException, IllegalAccessException, 
			IllegalArgumentException, InvocationTargetException {
		/*
		 * 根据指定的包名.类名,获取对应的Class对象
		 */
		Class<?> cls = Class.forName("com.qfedu.a_reflect.Person");
		
		/*
		 * 获取当前Person类内所有非私有化构造方法
		 */
		Constructor<?>[] constructors = cls.getConstructors();
		for (Constructor<?> constructor : constructors) {
			System.out.println(constructor);
		}
		
		System.out.println("----------------------------------------------------");
		System.out.println();
		
		/* 
		 * 暴力反射,获取Person类内所有的构造方法,包括私有化构造方法
		 */
		Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
		for (Constructor<?> constructor : declaredConstructors) {
			System.out.println(constructor);
		}
		
		System.out.println("----------------------------------------------------");
		System.out.println();
		
		/*
		 * 根据指定参数类型获取public修饰的构造方法对象
		 * 如果没有指定参数的构造方法,运行异常java.lang.NoSuchMethodException
		 */
		Constructor<?> constructor1 = cls.getConstructor();
		Constructor<?> constructor2 = cls.getConstructor(int.class);
		Constructor<?> constructor3 = cls.getConstructor(int.class, String.class);
		System.out.println(constructor1);
		System.out.println(constructor2);
		System.out.println(constructor3);
		
		// Constructor<?> constructor = cls.getConstructor(String.class);
		// System.out.println(constructor);
		System.out.println("----------------------------------------------------");
		System.out.println();
		
		/*
		 * 通过暴力反射可以获取任意权限修饰符,符合参数要求的构造方法对象
		 */
		Constructor<?> declaredConstructor1 = cls.getDeclaredConstructor();
		Constructor<?> declaredConstructor2 = cls.getDeclaredConstructor(String.class);
		System.out.println(declaredConstructor1);
		System.out.println(declaredConstructor2);
		
		System.out.println("----------------------------------------------------");
		System.out.println();
		
		/*
		 * 通过无参数Constructor对象执行newInstance方法
		 * 这里明确是一个Person类型,可以使用强制类型转换
		 * 这里使用的是public修饰的构造方法
		 */
		Person p1 = (Person) constructor1.newInstance();
		System.out.println(p1);
		System.out.println(new Person());
		System.out.println(constructor3.newInstance(1, "大明"));
		
		System.out.println("----------------------------------------------------");
		System.out.println();
		
		// 给予通过暴力反射获取到的非公开权限成员变量,成员方法,构造方法,操作权限
		// 暴力反射的为所欲为操作
		declaredConstructor2.setAccessible(true);
		Person p2 = (Person) declaredConstructor2.newInstance("大明");
		System.out.println(p2);
	}
}

2.3 Method成员方法涉及到的方法

代码语言:javascript
复制
1.Method[] getMethods();
	获取类内所有public修饰的成员方法,包括从父类继承而来的public修饰方法。
代码语言:javascript
复制
2.Method[] getDeclaredMethods();
	暴力反射
	获取类内所有成员方法,但是不包括从父类继承而来的方法。
代码语言:javascript
复制
3.Method getMethod(String methodName, Class... parameterTypes);
	根据指定的方法名和对应的参数类型,获取对应的public修饰的成员方法

	例如:cls.getMethod("setName", String.class);
代码语言:javascript
复制
4.Method getDeclaredMethod(String methodName, Class... parameterTypes);
	根据指定的方法名和对应的参数类型,获取对应的成员方法,包括私有化成员方法,但是不
	包括从父类继承而来的方法
	
	例如:cls.getMethod("setName", String.class);
代码演示
代码语言:javascript
复制
/*
 * Method成员方法涉及到的内容
 */
public class GetMethodObject {
	public static void main(String[] args) 
			throws ClassNotFoundException,
			NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		/*
		 * 根据指定的包名.类名,获取对应的Class对象
		 */
		Class<?> cls = Class.forName("com.qfedu.a_reflect.Person");
		
		/*
		 * 获取类内所有public修饰的成员方法,包括从父类继承而来的方法
		 */
		Method[] methods = cls.getMethods();
		for (Method method : methods) {
			System.out.println(method);
		}
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		/*
		 * 获取类内所有成员方法,包括私有化成员方法,但是不包括父类继承而来的方法
		 */
		Method[] declaredMethods = cls.getDeclaredMethods();
		
		for (Method method : declaredMethods) {
			System.out.println(method);
		}
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		/*
		 * 根据指定的方法名和参数类型,获取类内public修饰的成员方法
		 */
		Method game1 = cls.getMethod("game");
		Method game2 = cls.getMethod("game", String.class);
		// Method game3 = cls.getMethod("game", int.class);
		
		System.out.println(game1);
		System.out.println(game2);
		// System.out.println(game3);
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		/*
		 * 根据指定的方法名和参数类型,获取类内private修饰的成员方法
		 * 暴力反射
		 */
		Method declaredMethod1 = cls.getDeclaredMethod("testPrivate");
		Method declaredMethod2 = cls.getDeclaredMethod("testPrivate",String.class);
		
		System.out.println(declaredMethod1);
		System.out.println(declaredMethod2);

		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		Object obj = cls.getConstructor().newInstance();
		/*
		 * 执行public修饰的成员方法
		 */
		game1.invoke(obj);
		game2.invoke(obj, "WOT");
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		/*
		 * 给予暴力反射操作权限的情况下,执行私有化成员方法
		 */
		declaredMethod1.setAccessible(true);
		declaredMethod1.invoke(obj);
		
		declaredMethod2.setAccessible(true);
		declaredMethod2.invoke(obj, "烤羊排");
	}
}

2.4 Field成员变量涉及到方法

代码语言:javascript
复制
1.Field[] getFields();
	获取类内所有public修饰的成员变量
代码语言:javascript
复制
2.Field[] getDeclaredFields();
	获取类内所有成员变量,包括私有化成员方法
代码语言:javascript
复制
3.Field getField(String fieldName);
	获取指定变量名的成员变量对象,要求是public修饰的成员变量
代码语言:javascript
复制
4.Field getDeclaredField(String fieldName);
	获取指定变量名的成员变量对象,包括private私有化修饰的成员变量
代码演示
代码语言:javascript
复制
/*
 * 获取成员变量Field对象
 */
public class GetFieldObject {
	public static void main(String[] args) 
			throws ClassNotFoundException, 
			NoSuchFieldException, SecurityException, 
			InstantiationException, IllegalAccessException, 
			IllegalArgumentException, InvocationTargetException, 
			NoSuchMethodException {
		/*
		 * 根据指定的包名.类名,获取对应的Class对象
		 */
		Class<?> cls = Class.forName("com.qfedu.a_reflect.Person");
		
		Field[] fields = cls.getFields();
		for (Field field : fields) {
			System.out.println(field);
		}
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		Field[] declaredFields = cls.getDeclaredFields();
		for (Field field : declaredFields) {
			System.out.println(field);
		}
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		Field field = cls.getField("test");
		System.out.println(field);
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		Field id = cls.getDeclaredField("id");
		Field name = cls.getDeclaredField("name");
		
		System.out.println(id);
		System.out.println(name);
		
		System.out.println("-------------------------------------------------------");
		System.out.println();
		
		Object obj = cls.getConstructor().newInstance();
		System.out.println(obj);
		
		field.set(obj, 20);
		System.out.println(obj);
		
		id.setAccessible(true);
		name.setAccessible(true);
		
		id.set(obj, 1);
		name.set(obj, "大明");
		
		System.out.println(obj);
		
		System.out.println(field.get(obj));
		System.out.println(id.get(obj));
		System.out.println(name.get(obj));
	}
}

也要记住给予暴力反射的私有化权限

代码语言:javascript
复制
setAccessible(boolean flag);
给予Constructor,Method, Field对象,私有化内容,操作权限设置
true表示可以操作
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、概述:什么是反射?
  • 二、反射必会方法
    • 2.1 Class涉及到的方法用来获取类对象
      • 2.2Constructor 构造方法类涉及到的方法
        • 2.3 Method成员方法涉及到的方法
          • 2.4 Field成员变量涉及到方法
            • 也要记住给予暴力反射的私有化权限
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档