Java反射机制

什么是反射

**Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。**而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。

反射能做什么?

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

反射:一种计算机处理方式。是程序可以访问、检测和修改它本身状态或行为的一种能力。JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

反射的核心API:

在这里插入图片描述
在Class对象中可以获取:Constructor、Field、Method
反射的作用:我们知道反射是通过Class对象动态的获取某一个类的构造方法、成员变量、普通方法的方式。按照我们目前的能力,是无法通过私有的构造创建对象,无法给一个对象的私有的变量赋值、无法调用私有的方法。但是,通过反射就可以实现这种需求。

获取Class的三种方式,推荐第三种:

推荐参考:https://www.cnblogs.com/nullcodeworld/p/8878747.html

测试对象:

public class User {
	
	private String userName ;
	
	private String password;
	
	private String age;
	//public修饰的无参构造
	public User(){};
	//public修饰的三个参数构造
	public User(String userName,String password,String age){
		this.userName=userName;
		this.password=password;
		this.age=age;
	}
	//private修饰的两个参数构造
	private User(String userName,String password){
		this.userName=userName;
		this.password=password;
	}
	
	public String getName(User user){
		return user.getUserName();
	}
	
	private String showMethod(){
		return "私有方法被调用";
	}
	
	
	
	public String getUserName() {
		return userName;
	}


	public void setUserName(String userName) {
		this.userName = userName;
	}


	public String getPassword() {
		return password;
	}


	public void setPassword(String password) {
		this.password = password;
	}


	public String getAge() {
		return age;
	}


	public void setAge(String age) {
		this.age = age;
	}
}	

Constructor介绍

获取一个构造方法:
在这里插入图片描述
在这里插入图片描述
获取多个的构造方法:
在这里插入图片描述
在这里插入图片描述
总结:当获取一个构造方法时,调用不带s的方法;当获取私有的构造方法时,调用带Declared的方法。
通过Constructor对象创建类的实例
当通过Constructor对象类创建一个类的实例时,如果构造方法是非pubic修饰的,那么就需要调用Constructor父类 AccessibleObject的setAccessible(true)方法打破访问权限!!!

@Test
	public void getConstructor() throws NoSuchMethodException, SecurityException, InstantiationException,
			IllegalAccessException, IllegalArgumentException, Exception {
		// 获取User类的Class对象
		Class<User> userClass = (Class<User>) Class.forName("com.Lambda.test.User");
		// 通过无参构造方法,获取User类的Constructor(构造方法)对象
		Constructor<User> ConsUser1 = userClass.getConstructor();
		// 通过Constructor创建User实例对象
		User user1 = ConsUser1.newInstance();
		System.out.println("无参构造获取对象内存地址:" + user1 + "====用户名:" + user1.getUserName());

		System.out.println("----------------------------------------");
		// 通过有参构造方法,获取User类的Constructor(构造方法)对象
		Constructor<User> ConsUser2 = userClass.getConstructor(String.class, String.class, String.class);
		User user2 = ConsUser2.newInstance("张三", "123", "18");
		System.out.println("有参构造获取对象内存地址:" + user2 + "====用户名:" + user2.getUserName());
		System.out.println("----------------------------------------");
		// 获取非public修饰的构造方法对象,通过Constructor父类 AccessibleObject的setAccessible(true)方法打破访问权限
		Constructor<User> ConsUser3 = userClass.getDeclaredConstructor(String.class, String.class);
		// 是否越界访问(无视私有化)
		ConsUser3.setAccessible(true);
		User user3 = ConsUser3.newInstance("李四", "123");
		System.out.println("私有带参构造获取对象内存地址:" + user3 + "====用户名:" + user3.getUserName());
		System.out.println("----------------------------------------");
		// 获取
		Constructor<?>[] constructors = userClass.getConstructors();
		for (Constructor<?> constructor : constructors) {
			System.out.println("获取User类所有的公开构造方法:" + constructor);
		}
		System.out.println("----------------------------------------");

		Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
		for (Constructor<?> constructor : declaredConstructors) {
			System.out.println("获取User类所有的构造方法(包含非public修饰的):" + constructor);
		}

	}
运行结果:

在这里插入图片描述

Field介绍

获取一个Field对象的方法:
在这里插入图片描述
在这里插入图片描述
获取多个Field对象的方法:
在这里插入图片描述
在这里插入图片描述
给Field设置值以及获取Field的值:找Field的api
在这里插入图片描述
在这里插入图片描述

@Test
	public void getFiled() throws ClassNotFoundException, NoSuchFieldException, SecurityException,
			InstantiationException, IllegalAccessException {
		// 获取User类的class对象
		Class<?> userClass = Class.forName("com.Lambda.test.User");
		// 获取私有化修饰的成员变量对象
		Field field = userClass.getDeclaredField("userName");
		// 是否越界访问(无视私有化)
		field.setAccessible(true);
		// 通过class对象实例化user对象
		User user = (User) userClass.newInstance();
		// 参数赋值:参数1:实例化对象,参数2:值
		field.set(user, "王五");
		System.out.println("获取user成员变量:" + user.getUserName());
		System.out.println("----------------------------------------");
		//获取field属性值(userName)
		Object uname = field.get(user);
		System.out.println("获取userName的值"+uname);
	}
运行结果:

在这里插入图片描述
注:
获取对象的class类型,通过getDeclaredField(“id”)获取的是变量的对象,返回的Field就相当于是这个变量
field.set(user,“王五”):可以理解为设置user对象中field(“userName”)的值为"王五"
同理field.get(user):可以理解为获取user对象中field(“userName”)的值

Method获取介绍

获取一个Method对象的方法
在这里插入图片描述在这里插入图片描述
获取多个Method对象的方法:
在这里插入图片描述
在这里插入图片描述

@Test
	public void getMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
		// 获取User类的class对象
		Class<?> userClass = Class.forName("com.Lambda.test.User");
		// 通过class对象实例化user对象
		User user = (User) userClass.newInstance();
		user.setUserName("赵六");
		//获取方法的method对象,参数1:方法名,参数2:方法的参数类型
		Method method = userClass.getMethod("getName",userClass);
		//method代表方法对象;invoke方法参数1:执行方法的对象,参数2:方法的参数
		Object resule1 = method.invoke(user, user);
		System.out.println("public修饰的方法返回结果:"+resule1);
		
		System.out.println("-------------------------------------------");
		
		//获取非public方法的method对象,参数1:方法名,参数2:方法的参数类型
		Method showMethod = userClass.getDeclaredMethod("showMethod");
		//越界访问,无视私有化
		showMethod.setAccessible(true);
		//showMethod代表方法对象;invoke方法参数1:执行方法的对象,参数2:方法的参数
		Object result2 = showMethod.invoke(user);
		System.out.println("非public修饰的方法返回结果:"+result2);
	}
运行结果:

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章