java 反射詳解


目錄

反射定義
反射實現
通過反射獲取對應類的Class對象
根據對應類的Class對象得到全限定名、類名、包名
獲取類的所有實現接口
獲取類的屬性(Filed 類)
通過Class對象構造對應的實例對象(不通過new)
修改或獲取指定對象的屬性
獲取類的方法 (Method 類)
構造方法相關操作

反射定義

反射式在java程序運行時,我還能動態的得到某個對象的所有屬性和方法信息。並且可以動態執行某個對象的指定方法,或修改指定屬性。這就是反射。

java反射實現

首先定義我們的操作類,Person

public class Person  implements Serializable{
	/**
	 * 序列化  序列化編號
	 */
	private static final long serialVersionUID = -5293639382415756109L;
	public int pid;
	private String pname;
	
	public Person() {
		
	}
	public Person(String name) {
		this.pname = name;
	}
	
	public Person(int pid, String pname) {
		this.pid = pid;
		this.pname = pname;
	}
	public String getPname() {
		return pname;
	}
	
	//getPid是一個私有的方法
	public int getPid() {
		return pid;
	}
	
	public void setPid(int pid) {
		this.pid = pid;
	}
	
	public void setPname(String pname) {
		this.pname = pname;
	}
	
	//add是一個私有的方法
	private String add(Integer i, Integer j) {
		return i + j + "";
	}
}

通過反射獲取對應類的Class對象

class對象在類加載時會由虛擬機內部產生,並且一個類有且只有一個對應的class對象。還有 基礎數據類型、數組、包括關鍵字 void (void.class)都有對應的class對象.下面我們看看如何獲取class對象

		//(1)類.class
		 Class c = Person.class;
		 
		// (2)對象名.getClass()
		 Person person = new Person();
		 Class c2 = person.getClass();
	
		// (3)Class.forName("全限定名")
		// 全限定名 一定是包含包名的 包名.類名
		 Class c3 = Class.forName("com.cpc.temp.Person");
	
		// (4)類.getClassLoader().loadClass("全限定名")
		 Class c4 = Person.class.getClassLoader().loadClass("com.cpc.temp.Person");

		// (5)子類.class.getSuperClass()
		// 這是等到父類class對象  (這返回的是Object的Class對象)
		Class c5 = Person.class.getSuperclass();
		
		// (6)包裝類.class
		Class c6 = Integer.class;

根據對應類的Class對象得到全限定名、類名、包名

		 Class c1 = Class.forName("com.cpc.temp.Person");
		 System.out.println("全限定名" + c1.getName());
		 System.out.println("類名" + c1.getSimpleName());
		 System.out.println("包名" + c1.getPackage());

執行結果

全限定名com.cpc.temp.Person
類名Person
報名package com.cpc.temp

獲取類的所有實現接口

		 Class c1 =  Person.class;
		 //這是所有接口對應的Class對象數組
		 Class[] classin = c1.getInterfaces();
		 //遍歷
		 for(int i = 0; i < classin.length; i ++) {
			 System.out.println(classin[i].getName());
		 }

執行結果

java.io.Serializable

獲取類的屬性(Filed 類)

獲取Class對象的屬性返回的就是Filed類實例

		// 4獲取類的屬性(Filed 類)
		Class c1 = Person.class;
		// getField("屬性名") 獲取公有屬性
		System.out.println("---------獲取公有屬性--------");
		Field pid = c1.getField("pid");
		// getName() 獲取屬性名
		System.out.println("pid的屬性名" + pid.getName());
		// getModifiers() 獲取訪問修改符
		System.out.println("pid的訪問修飾符" + pid.getModifiers());
		// 上面的getModifiers輸出結果是數字,對應的修飾符就是下面幾個常量值
		System.out.println("----屬性訪問修飾符------");
		System.out.println("public:" + Modifier.PUBLIC);
		System.out.println("private:" + Modifier.PRIVATE);
		System.out.println("protected:" + Modifier.PROTECTED);
		
		// getType() 獲取屬性的類型對應的Class對象
		System.out.println("----獲取屬性的類型對應的Class對象------");
		Class cla = pid.getType();
		System.out.println(cla.getName());
		
		// getDeclaredField("屬性名") 獲取私有屬性值
		Field pname = c1.getDeclaredField("pname");
		System.out.println("-----獲取私有屬性----");
		//輸出屬性名
		System.out.println(pname.getName());
		//輸出屬性的訪問修飾符
		System.out.println(pname.getModifiers());
		//setAccessible(true) 設置私有屬性可訪問
		pname.setAccessible(true);
		pname.set(person, "zs");
		System.out.println(person.getPname());
		
		// getDeclaredFields() 獲取所有的屬性(公有私有都能獲取到)
		Field[] fileds = c1.getDeclaredFields();
		System.out.println("------遍歷所有屬性,並輸出屬性名-----");
		for (Field field : fileds) {
			System.out.println(field.getName());
		}

執行結果

---------獲取公有屬性--------
pid的屬性名pid
pid的訪問修飾符1
----屬性訪問修飾符------
public:1
private:2
protected:4
----獲取屬性的類型對應的Class對象------
int
-----獲取私有屬性----
pname
2
zs
------遍歷所有屬性,並輸出屬性名-----
serialVersionUID
pid
pname

通過Class對象構造對應的實例對象(不通過new)

		Class c1 = Person.class;
		Person p = (Person)c1.newInstance();

修改或獲取指定對象的屬性

		Class c1 = Person.class;
		Field pid = c1.getField("pid");
		Person p = (Person) c1.newInstance();
		// 修改person的
		pid.set(person, 1);
		//// get(對象名)=對象名.get屬性名 獲取屬性值
		System.out.println(pid.get(person));

執行結果

1

獲取類的方法 (Method 類)

		Class c1 = Person.class;
		Object object = c1.newInstance();
		// getMethod(方法名,參數數據類型(無參數傳Null)) 獲取公共方法
		Method setPid = c1.getMethod("setPid", int.class);
		// invok (對象名, 參數列表)=對象名.方法名 執行方法
		setPid.invoke(object, 1);
		Method getPid = c1.getMethod("getPid", null);
		System.out.println("執行公共getPid返回結果:" + getPid.invoke(object, null));

		// getDeclaredMethod(方法名,參數數據類型(無參數傳null)) 獲取私有方法
		Method add = c1.getDeclaredMethod("add", Integer.class, Integer.class);
		add.setAccessible(true);
		System.out.println("執行私有add返回結果:" + add.invoke(object, 1, 2));
		// getReturnType() 得到返回值方法的數據類型的Class對象
		Class re = add.getReturnType();
		System.out.println("add方法的返回類型"+re.getName());

		// getParameterTypes() 得到方法參數列表()
		Class[] cal = add.getParameterTypes();
		System.out.println("----遍歷add的參數列表------開始");
		for (Class cc : cal) {
			System.out.println(cc.getName());
		}
		System.out.println("----遍歷add的參數列表------結束");
		// getDeclaredMethods() 得到類的所有方法
		Method[] methods = c1.getDeclaredMethods();
		System.out.println("-----遍歷所有方法----開始");
		for (Method method : methods) {
			System.out.println(method.getName());
		}
		System.out.println("-----遍歷所有方法-----結束");

執行結果

執行公共getPid返回結果:1
執行私有add方法:3
add方法的返回類型java.lang.String
----遍歷add的參數列表------開始
java.lang.Integer
java.lang.Integer
----遍歷add的參數列表------結束
-----遍歷所有方法----開始
add
setPid
getPname
getPid
setPname
-----遍歷所有方法-----結束

構造方法相關操作

		Class c1 = Person.class;
		// getConstructor 得到構造方法
		Constructor con = c1.getConstructor(int.class, String.class);
		// 通過指定構造方法構造對象
		Person p1 = (Person) con.newInstance(1, "張三");
		System.out.println("獲取通過指定構造方法構造出來的p1對象的屬性");
		System.out.println(p1.getPid());
		System.out.println(p1.getPname());
		// gitConstructors 獲取所有構造方法 並輸出構造方法的參數個數
		Constructor[] constructors = c1.getConstructors();
		System.out.println("------遍歷構造方法-----");
		for (Constructor constructor : constructors) {
			System.out.println(constructor.getParameterCount());
		}

執行結果

獲取通過指定構造方法構造出來的p1對象的屬性
1
張三
------遍歷構造方法-----
2
1
0

其余的操作和方法操作差不多,這里就不過的贅述了.

如果有不對的地方歡迎在留言區批評指正。如果覺得對請點個贊那是對我最大的支持~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM