天天看點

Java的反射機制一、反射的介紹二、Class類三、反射執行個體化四、反射動态方法調用 五、反射讀寫屬性

目錄

一、反射的介紹

什麼是反射?

反射機制的作用 

反射優缺點

二、Class類

概念 

學生類:Student 

擷取Class對象的方法 

三、反射執行個體化

常用方法

執行個體 

四、反射動态方法調用

常用方法

 執行個體

 五、反射讀寫屬性

常用方法

執行個體

一、反射的介紹

什麼是反射?

反射就是Java語言中的一種機制,它可以動态的去調用我們的執行個體化對象,讀寫屬性和調用方法。

反射機制的作用 

通過Java的反射機制我們可以擷取我們Class檔案加載後的Class對象的是以資訊,就比如public修飾的方法屬性還有對象,還有我們的private修飾的方法屬性和對象,也就是說我們的類變成了透明的,所有的細節都可以擷取到。

反射優缺點

優點:

能夠運作時動态擷取類的執行個體,提高靈活性;

與動态編譯結合;

缺點:

使用反射性能較低,需要解析位元組碼(.class檔案),将記憶體中的對象進行解析;

相對不安全,破壞了封裝性(因為通過反射可以獲得私有方法和屬性);

解決方案:

1、通過setAccessible(true)關閉JDK的安全檢查來提升反射速度;

2、多次建立一個類的執行個體時,有緩存會快很多;

3、ReflectASM工具類,通過位元組碼生成的方式加快反射速度 ;

二、Class類

概念 

Java中,每個class都有一個相應的Class對象

也就是說,當我們編寫一個類,編譯完成後,在生成的.class檔案中,就會産生一個Class對象,用于表示這個類的類型資訊

學生類:Student 

後面的執行個體都是圍繞以下學生類進行操作

package com.xyz.mvcdemo.reflect;

public class Student {
	private String sid;

	private String sname;

	public Integer age;
	
	static{
		System.out.println("加載進jvm中!");
	}

	public Student() {
		super();
		System.out.println("調用無參構造方法建立了一個學生對象");
	}

	public Student(String sid) {
		super();
		this.sid = sid;
		System.out.println("調用帶一個參數的構造方法建立了一個學生對象");
	}

	public Student(String sid, String sname) {
		super();
		this.sid = sid;
		this.sname = sname;
		System.out.println("調用帶二個參數的構造方法建立了一個學生對象");
	}

	@SuppressWarnings("unused")
	private Student(Integer age) {
		System.out.println("調用Student類私有的構造方法建立一個學生對象");
		this.age = age;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public void hello() {
		System.out.println("你好!我是" + this.sname);
	}

	public void hello(String name) {
		System.out.println(name + "你好!我是" + this.sname);
	}

	@SuppressWarnings("unused")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}

	@Override
	public String toString() {
		return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
	}
	
	
}
           

擷取Class對象的方法 

Class.forName(完整類名)

類名.class

對象.getClass()

//1.通過Class.forName()擷取Class
Class<Student> clazz = (Class<Student>)Class.forName("com.xyz.mvcdemo.reflect.Student");
		
//2.通過 類.class

Class clazz02=Student.class;
		
//3.通過 對象.getClass()
Student stu = new Student();
Class clazz03 = stu.getClass();
           
Java的反射機制一、反射的介紹二、Class類三、反射執行個體化四、反射動态方法調用 五、反射讀寫屬性

三、反射執行個體化

常用方法

getConstructor 獲得構造器對象
getDeclaredConstructor 獲得私有的構造器對象
newInstance 反射執行個體化
setAccessible(true) 将私有設定可通路

執行個體 

/**
		 * 公共的構造方法執行個體對象
		 */
		//通過反射擷取對象(無參)
		Constructor<Student> c1 = clazz.getConstructor();
		//通過反射進行執行個體化對象
		Student stu01 = c1.newInstance();
		//設定屬性
		stu01.setSname("小黑");
		System.out.println("stu01="+stu01);
		
		//通過反射擷取對象(有參-id)
		Constructor<Student> c2 = clazz.getConstructor(String.class);
		//通過反射進行執行個體化對象
		Student stu02 = c2.newInstance("111");
		//設定屬性
		stu02.setSname("小白");
		System.out.println("stu02="+stu02);
		
		//通過反射擷取對象(有參-id,name)
		Constructor<Student> c3 = clazz.getConstructor(String.class,String.class);
		//通過反射進行執行個體化對象
		Student stu03 = c3.newInstance("121","小藍");
		System.out.println("stu03="+stu03);
		
		/**
		 * 私有的構造方法執行個體對象
		 */
		//通過反射擷取對象(有參-age)
		Constructor<Student> c4 = clazz.getDeclaredConstructor(Integer.class);
		//設定可以通路該方法
		c4.setAccessible(true);
		//通過反射進行執行個體化對象
		Student stu04 = c4.newInstance(18);
		System.out.println("stu04="+stu04);
           
Java的反射機制一、反射的介紹二、Class類三、反射執行個體化四、反射動态方法調用 五、反射讀寫屬性

四、反射動态方法調用

常用方法

getMethod 通過方法名稱擷取到方法對象
getDeclaredMethod 通過方法名稱擷取到私有的方法對象
invoke 調用方法

 執行個體

/**
		 * 調用公共的方法
		 */
		//通過反射擷取方法(無參)
		Method method = clazz.getMethod("hello");
		//設定屬性
		stu04.setSname("小灰灰");
		//調用方法
		method.invoke(stu04);
		
		//通過反射擷取方法(有參)
		Method method02 = clazz.getMethod("hello",String.class);
		//調用方法
		method02.invoke(stu01,"小綠");
		
		/**
		 * 調用私有的方法
		 */
		Method method03 = clazz.getDeclaredMethod("add", Integer.class,Integer.class);
		//設定可以通路該方法
		method03.setAccessible(true);
		//調用方法
		int in = (int)method03.invoke(stu04, 500,20);
		System.out.println(in);
           
Java的反射機制一、反射的介紹二、Class類三、反射執行個體化四、反射動态方法調用 五、反射讀寫屬性

 五、反射讀寫屬性

常用方法

getField 獲得公開的屬性
getDeclaredField 既可以獲得公開的屬性又可以獲得私有屬性
getDeclaredFields 獲得全部

執行個體

/**
		 * 擷取公共的屬性
		 */
		Field f = clazz.getField("age");
		//設定屬性
		f.set(stu04, 29);
		System.out.println("stu04="+stu04);
		System.out.println("age="+f.get(stu04));
		
		/**
		 * 擷取私有的屬性
		 */
		Field f01 = clazz.getDeclaredField("sname");
		//設定可以通路該屬性
		f01.setAccessible(true);
		//設定屬性
		f01.set(stu04, "哈哈");
		System.out.println(stu04);
           
Java的反射機制一、反射的介紹二、Class類三、反射執行個體化四、反射動态方法調用 五、反射讀寫屬性