目錄
反射定義
反射實現
通過反射獲取對應類的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
其余的操作和方法操作差不多,這里就不過的贅述了.
如果有不對的地方歡迎在留言區批評指正。如果覺得對請點個贊那是對我最大的支持~~