目錄
一、反射的介紹
什麼是反射?
反射機制的作用
反射優缺點
二、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();
三、反射執行個體化
常用方法
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);
四、反射動态方法調用
常用方法
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);
五、反射讀寫屬性
常用方法
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);