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);
	}
運行結果:

在這裏插入圖片描述

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