Java的反射(reflection)機制是指在程序的運行狀態中,可以構造任意一個類的對象,可以了解任意一個對象所屬的類,可以了解任意一個類的成員變量和方法,可以調用任意一個對象的屬性和方法。這種動態獲取程序信息以及動態調用對象的功能稱為Java語言的反射機制。反射被視為動態語言的關鍵。
了解Java反射機制前先了解一下類加載器相關的知識。java文件 經過編譯 ->Class文件(字節碼文件) 最后虛擬機執行的就是字節碼文件, 但是字節碼文件又不會自己跑到虛擬機當中, 這時候就得需要一個”人“,把字節碼文件放到虛擬機當中,而這個人就是 類加載器。
類加載時機(何時加載字節碼文件):
總結:用到就加載,不用不加載
類加載過程
驗證
準備
解析
解析過程拆解:
name的類型是引用類型(String),String是其他的類的名字,最初加載String類的時候不知道String類在哪里,這時的String使用符號(ex:&&&)替代。在解析的過程中,就會找實際的String類在哪里,并把臨時的符號變成實際的String引用
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 獲取系統類加載器的父類加載器,平臺類加載器
ClassLoader clasLoader1 = systemClassLoader.getParent();
//獲取平臺類加載器的父類加載器, 啟動類加載器
ClassLoader classLoader2 = clasLoader1.getParent();
System.out.println("系統類加載器" + systemClassLoader);
System.out.println("平臺類加載器" + clasLoader1);
System.out.println("啟動類加載器" + classLoader2);
1.4 雙親委派模型方法名 | 說明 |
---|---|
public static ClassLoader getSystemClassLoader() | 獲取系統類加載器 |
public InputStream getResourceAsStream(String name) | 加載某一個資源文件 |
//獲得系統類加載器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 利用類加載器去加載一個指定的文件
// 參數:文件的路徑
// 返回值:字節流
// 這里直接填寫prop.properties,相對的在src下邊
InputStream resourceAsStream = systemClassLoader.getResourceAsStream("prop.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
System.out.println(properties);
resourceAsStream.close();
2. 反射
2.1 反射的概述Java反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類所有的屬性與方法;對于任意一個對象,都能夠調用它的任意屬性和方法(利用反射調用它類中的屬性和方法時,無視修飾符)。
這種動態獲取信息以及動態調用對象方法的功能稱為Java語言的反射機制(先獲取配置文件中的信息,動態獲取信息并創建對象和調用方法)
public class Student {private String name;
private int age;
public Student() {}
public Student(String name, int age) {this.name = name;
this.age = age;
}
public String getName() {return name;
}
public void setName(String name) {this.name = name;
}
public int getAge() {return age;
}
public void setAge(int age) {this.age = age;
}
public void study(){System.out.println("學生在學習");
}
@Override
public String toString() {return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Class>clazz = Class.forName("全類名");
Classclazz2 = Student.class;
Student s = new Student();
//每一個對象都對應著一個字節碼文件,所以getClass方法是定義在Object中的
Class clazz3 = s.getClass();
System.out.println(clazz == clazz2);//true
System.out.println(clazz3 == clazz2);//true
2.3 獲取Class類對象中的內容Java當中什么都可以看成一個對象,只要是對象,就可以用類去描述。從class類中獲取的成員變量就可以把它認為是成員變量對象(Field),以此類推…
如何學習?
大概步驟(以獲取構造方法為例)
-獲取class對象
-獲得Constructor對象
-創建對象
明白幾個問題
-獲取對象不就是為了創建對象么?
-獲取屬性不就是為了給他賦值和取值么?
-獲取方法不就是為了調用么?
學習
-把整個流程以及為什么用反射了解清楚,方法忘了就去api手冊查,重復多了自然也就記住了
總結
-先獲取整體(Class對象),在獲取部分(成員屬性,構造方法,成員男方法),然后操作部分
如圖所示:Class對象加載到內存當中,我們可以去獲取想要的信息
方法名 | 說明 |
---|---|
Constructor>[] getConstructors() | 返回所有公共構造方法對象的數組 |
Constructor>[] getDeclaredConstructors() | 返回所有構造方法對象的數組 |
Constructor getConstructor(Class>… parameterTypes) | 返回單個公共構造方法對象 |
Constructor getDeclaredConstructor(Class>… parameterTypes) | 返回單個構造方法對象 |
public class Student {private String name;
private int age;
public String getName() {return name;
}
public void setName(String name) {this.name = name;
}
public int getAge() {return age;
}
public void setAge(int age) {this.age = age;
}
public void study() {System.out.println("我的名字是:" + name);
System.out.println("學生在打籃球");
}
private Student(String name) {System.out.println("name的值為:" + name + "age的值為:" + age);
System.out.println("private ... student ... 有參構造方法");
}
public Student() {System.out.println("public ... student ... 無參構造方法");
}
public Student(String name, int age) {System.out.println("name的值為:" + name + "age的值為:" + age);
System.out.println("public ... student ... 有參構造方法");
}
@Override
public String toString() {return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
main
private static void method4() throws ClassNotFoundException, NoSuchMethodException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//小括號中一定要和構造方法的形參保持一致
Constructor>constructor = clazz.getConstructor();
System.out.println(constructor);
Constructor>constructor2 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor2);
//會報錯,沒有形參為int的構造方法
Constructor>constructor3 = clazz.getConstructor(int.class);
System.out.println(constructor3);
}
private static void method2() throws ClassNotFoundException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor>declaredConstructor : declaredConstructors) {System.out.println(declaredConstructor);
}
}
private static void method1() throws ClassNotFoundException {Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>[] constructors = clazz.getConstructors();
for (Constructor>constructor : constructors) {System.out.println(constructor);
}
}
2.4.2 通過Constructor對象中的方法創建對象方法名 | 說明 |
---|---|
T newInstance(Object…initargs) | 根據指定的構造方法創建對象 |
setAccessible(boolean flag) | 設置為true,表示取消訪問檢查 |
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {// method1();
// method2();
// method3();
//獲取一個私有的構造方法,并創建對象
//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//2.獲取一個私有化的構造方法
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//被private修飾的成員,不能直接使用
//如果使用反射前行獲取并使用,需要臨時取消訪問檢查
constructor.setAccessible(true);
//3.直接創建對象
Student student = (Student) constructor.newInstance("李白");
System.out.println(student);
}
private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException { //簡寫格式
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Student student = (Student) clazz.newInstance();//這個方法過時了
}
private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
Constructor>constructor = clazz.getConstructor();
Student student = (Student) constructor.newInstance();
System.out.println(student);
}
private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { // 獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Student");
//獲取構造方法對象
Constructor>constructor = clazz.getConstructor(String.class, int.class);
//利用newInstance方法,創建Student對象
Student student = (Student) constructor.newInstance("李白", 61);
System.out.println(student);
}
2.4.3 小結方法名 | 說明 |
---|---|
Field[] getFields() | 返回所有公共(public)成員變量對象的數組 |
Field[] getDeclaredFields() | 返回所有成員變量對象的數組 |
Field getField(String name) | 返回單個公共成員變量對象 |
Field getDeclaredField(String name) | 返回單個成員變量對象 |
private static void method4() throws ClassNotFoundException, NoSuchFieldException {//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取name這個成員變量
Field field = clazz.getDeclaredField("money");
//3.打印
System.out.println(field);
}
private static void method3() throws ClassNotFoundException, NoSuchFieldException {//想要獲取的成員變量必須是真是存在的,且是public的
//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取name這個成員變量
Field field = clazz.getField("money");
//3.打印
System.out.println(field);
}
private static void method2() throws ClassNotFoundException {//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取Field對象
Field[] fields = clazz.getDeclaredFields();
//3.遍歷
for (Field field : fields) {System.out.println(field);
}
}
private static void method1() throws ClassNotFoundException {//1.獲取class對象
Class>clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取Field對象
Field[] fields = clazz.getFields();
//3.遍歷
for (Field field : fields) {System.out.println(field);
}
}
2.5.2 給成員變量賦值方法名 | 說明 |
---|---|
void set(Object obj, Object value) | 賦值 |
Object get(Object obj) | 獲取值 |
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {// method1();
//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取成員變量的Field對象
Field field = clazz.getDeclaredField("money");
//3.取消訪問檢查
field.setAccessible(true);
//4.調用get方法來取值
//4.1創建一個對象
Person person = (Person) clazz.newInstance();
//4.2獲取指定對象的money的值
Object o = field.get(person);
//5.打印
System.out.println(o);
}
private static void method1() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
// 2.獲取name這個Field對象
Field field = clazz.getField("name");
//3.利用set方法進行賦值
//3.1先創建一個Student對象
Person person = (Person) clazz.newInstance();
//3.2有了對象才可以給指定對象賦值
field.set(person,"李白");
System.out.println(person);
}
2.6 反射獲取成員方法并使用
2.6.1 Class類獲取成員方法對象的方法方法名 | |
---|---|
Method[] getMethods() | 返回所有公共成員方法對象的數組,包括繼承的 |
Method[] getDeclaredMethods() | 返回所有成員方法對象的數組,不包括繼承的 |
Method getMethod(String name, Class>… parameterTypes) | 返回單個公共成員方法對象 |
Method getDeclaredMethod(String name, Class>… parameterTypes) | 返回單個成員方法對象 |
private static void method5() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取私有的方法
Method look = clazz.getDeclaredMethod("look");
System.out.println(look);
}
private static void method4() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取有形參的方法
Method method1 = clazz.getMethod("method2", String.class);
System.out.println(method1);
}
private static void method3() throws ClassNotFoundException, NoSuchMethodException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取無參數的方法
Method method1 = clazz.getMethod("method1");
System.out.println(method1);
}
private static void method2() throws ClassNotFoundException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取成員方法對象
Method[] methods = clazz.getDeclaredMethods();// 返回所有成員方法的數組,不包含繼承的
for (Method method : methods) {System.out.println(method);
}
}
private static void method1() throws ClassNotFoundException {//1.獲取class對象
Class clazz = Class.forName("com.gosling.reflect.Entity.Person");
//2.獲取成員方法對象
Method[] methods = clazz.getMethods();// 繼承父類的方法也在里邊
for (Method method : methods) {System.out.println(method);
}
}
以上就是今天要講的內容,本文僅僅簡單介紹了Java的反射機制,因為有關反射的方法眾多,本文只介紹了較為常用的一些去供大家學習和了解!
本文中的案例大家不要光看哦,試著放到程序中運行一下,對加深理解有很大的幫助的!
最后,創作不易,如果本文對您有一點幫助的話,就點贊、收藏、關注支持鼓勵一下吧,您的支持是我創作的動力!
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
本文題目:Java反射-創新互聯
轉載注明:http://vcdvsql.cn/article42/phchc.html
成都網站建設公司_創新互聯,為您提供網頁設計公司、外貿網站建設、網站改版、動態網站、網站排名、標簽優化
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯