花一杯茶的時間,學會Java反射(基礎篇)
什麼是java反射
JAVA 反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為 java 語言的反射機制。
其實就是指我們可以在執行時載入、探知、使用編譯期間完全未知的 classes。
java反射的作用
1.反射可以更好的對程式碼進行自審。相當於程式設計師的一面鏡子;
2.反射可以解耦,提高程式碼的擴充套件性。如工廠模式。
3.為滿足需求,獲取某程式碼進行部分修改或者破解;
4.方便多人開發。
假如有多個程式設計師開發同個專案,A程式設計師需要用到B程式設計師所寫的類,若B程式設計師並沒有完成他所寫的類,那麼A程式設計師是不能通過編譯的。此時,反射就能很好的解決該問題;
學習反射
-
獲得完整的包名和類名
有三種方式。不過一般都是使用第一種,通過包名+類名獲取需要的類,擴充套件性好很多:
package com.demo;
public class ReflectionDemo {
public static void main(String[] args) {
try {
//第一種(推薦使用)
Class<?> cls1 = Class.forName("com.demo.Person");
System.out.println(cls1.getName());
// 第二種
Person per = new Person();
Class<?> cls2 = per.getClass();
System.out.println(cls2.getName());
// 第三種
Class<?> cls3 = Person.class;
System.out.println(cls3.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Person {}
列印結果
com.demo.Person
com.demo.Person
com.demo.Person
<br />
-
反射進行類的例項化並獲取構造方法
根據構造方法是否有引數,引數的型別有關。
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectionDemo {
public static void main(String[] args) {
try {
// 獲取類
Class<?> cls1 = Class.forName("com.demo.Person");
// 直接獲取例項(ps:需要獲取的類中有無參構造方法,並且該構造方法不能是private的)
Person person = (Person) cls1.newInstance();
System.out.println("[ 直接獲取例項 ]person.print() :" + person.print());
System.out.println("-----------------");
// 獲取全部構造方法
Constructor<?>[] con = cls1.getConstructors();
for (int i = 0; i < con.length; i++) {
System.out.println("[ 獲取全部構造方法 ]constructor[" + i + "] :" + con[i].toString());
}
System.out.println("-----------------");
// 通過帶引數的構造方法獲取例項(對應上面顯示的構造方法順序)
Person per1 = (Person) con[1].newInstance("maxchan");
System.out.println("[ 獲取帶引數的構造方法例項 ] : name:" + per1.getName());
Person per2 = (Person) con[2].newInstance("maxchan", "男");
System.out.println("[ 獲取帶引數的構造方法例項 ] : name:" + per2.getName() + " sex:" + per2.getSex());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
class Person {
private String name; // 姓名
private String sex; // 性別
public Person() {
}
public Person(String name) {
this.name = name;
}
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public String print() {
return "print";
}
}
執行結果:
[ 直接獲取例項 ]person.print() :print
-----------------
[ 獲取全部構造方法 ]constructor[0] :public com.demo.Person()
[ 獲取全部構造方法 ]constructor[1] :public com.demo.Person(java.lang.String)
[ 獲取全部構造方法 ]constructor[2] :public com.demo.Person(java.lang.String,java.lang.String)
-----------------
[ 獲取帶引數的構造方法例項 ] : name:maxchan
[ 獲取帶引數的構造方法例項 ] : name:maxchan sex:男
<br />
-
檢視類的方法
檢視類有什麼方法,可以使用getMethods()
和getDeclaredMethods()
。
不同的是getMethods()
只能獲取該類以及父類使用public修飾的方法;getDeclaredMethods()
獲取的是此類的所有方法,沒有獲取父類的方法。
若要檢視某個父類中的所有方法,可以通過類cls1.getSuperclass()
先獲取該父類,再呼叫getDeclaredMethods()
方法。
package com.demo;
import java.lang.reflect.Method;
public class ReflectionDemo {
public static void main(String[] args) {
try {
// 獲取類
Class<?> cls1 = Class.forName("com.demo.Person");
// 獲取方法(只有使用public修飾符的方法)
Method[] method = cls1.getMethods();
for (int i = 0; i < method.length; i++) {
System.out.println("method[" + i + "] :" + method[i]);
}
System.out.println("--------------------------");
//獲取全部方法(使用預設、pulbic、private、protected修飾的方法)
Method[] method_all = cls1.getDeclaredMethods();
for (int i = 0; i < method_all.length; i++) {
System.out.println("method_all[" + i + "] :" + method_all[i]);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Person {
String defaultString() {
return "defaultString";
}
private String privateString() {
return "privateString";
}
protected String protectedString() {
return "protectedString";
}
public String publicString() {
return "person";
}
}
列印結果
method[0] :public java.lang.String com.demo.Person.publicString()
method[1] :public final void java.lang.Object.wait() throws java.lang.InterruptedException
method[2] :public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method[3] :public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method[4] :public boolean java.lang.Object.equals(java.lang.Object)
method[5] :public java.lang.String java.lang.Object.toString()
method[6] :public native int java.lang.Object.hashCode()
method[7] :public final native java.lang.Class java.lang.Object.getClass()
method[8] :public final native void java.lang.Object.notify()
method[9] :public final native void java.lang.Object.notifyAll()
--------------------------
method_all[0] :java.lang.String com.demo.Person.defaultString()
method_all[1] :private java.lang.String com.demo.Person.privateString()
method_all[2] :protected java.lang.String com.demo.Person.protectedString()
method_all[3] :public java.lang.String com.demo.Person.publicString()
<br />
-
獲取類的某個具體方法
和上面相同,若只需獲取public
方法,用getMethod([具體的方法名],[引數型別])
;若需要獲取使用其它修飾符的方法,則需使用getDeclaredMethod([具體的方法名],[引數型別])
package com.demo;
import java.lang.reflect.Method;
public class ReflectionDemo {
public static void main(String[] args) {
try {
// 獲取類
Class<?> cls1 = Class.forName("com.demo.Person");
// 獲取類的某個具體的方法
Method method = cls1.getMethod("publicString");
System.out.println("method.getName() :" + method.getName());
System.out.println("--------------------------");
// 獲取類的某個具體的方法
Method declared_method = cls1.getDeclaredMethod("privateString");
System.out.println("declared_method.getName() :" + declared_method.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
class Person {
String defaultString() {
return "defaultString";
}
private String privateString() {
return "privateString";
}
protected String protectedString() {
return "protectedString";
}
public String publicString() {
return "person";
}
}
列印結果:
method.getName() :publicString
--------------------------
declared_method.getName() :privateString
<br />
-
呼叫類的方法
package com.demo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectionDemo {
public static void main(String[] args) {
try {
// 獲取類
Class<?> cls1 = Class.forName("com.demo.Person");
Person per = (Person) cls1.newInstance();
// 呼叫帶引數的方法(第一個引數使用方法名,後面的引數是對應的引數型別,若有多個引數則顯示多個引數型別,若無引數,則不顯示)
//invoke方法的第一個引數是類的例項
Method param_method = cls1.getMethod("setContent", String.class);
param_method.invoke(per, "content");
// 呼叫不帶引數的方法獲取資料
Method method = cls1.getMethod("getContent");
String result = (String) method.invoke(per);
System.out.println("[ 呼叫不帶引數的方法獲取資料 ] :" + result);
// 呼叫不帶引數的靜態方法獲取資料(只需將invoke方法的第一個引數改成null即可)
Method static_method = cls1.getMethod("getStaticContent");
String static_result = (String) static_method.invoke(null);
System.out.println("[ 呼叫不帶引數的靜態方法獲取資料 ] :" + static_result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
class Person {
public String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public static String getStaticContent() {
return "static content";
}
}
執行結果:
[ 呼叫不帶引數的方法獲取資料 ] :content
[ 呼叫不帶引數的靜態方法獲取資料 ] :static content
<br />
-
變數的獲取和變數值的設定
變數的獲取使用Field
,跟Method
的用法很像。有getFields()
以及getDeclaredFields()
。getDeclaredFields()
可以獲取全部變數,getFields()
只能獲取用public
修飾的變數。
package com.demo;
import java.lang.reflect.Field;
public class ReflectionDemo {
public static void main(String[] args) {
try {
// 獲取類
Class<?> cls1 = Class.forName("com.demo.Person");
// 獲取public修飾的變數
Field[] field = cls1.getFields();
for (Field f : field) {
System.out.println("[ 獲取public修飾的變數 ] (getFields):" + f.getName());
}
System.out.println("-----------------------------");
// 獲取全部的變數
Field[] declared_field = cls1.getDeclaredFields();
for (Field f : declared_field) {
System.out.println("[ 獲取全部的變數 ] (declared_field):" + f.getName());
}
System.out.println("-----------------------------");
// 通過變數名,設定或獲取變數值
Person person = (Person) cls1.newInstance();
Field field1 = cls1.getDeclaredField("sex");
System.out.println("[ 獲取變數名 ] :" + field1.get(person));
// 設定變數值
field1.set(person, "女");
System.out.println("[ 設定變數名 ] :" + field1.get(person));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
class Person {
private String name; // 姓名
public String sex = "男"; // 性別
}
執行結果:
[ 獲取public修飾的變數 ] (getFields):sex
-----------------------------
[ 獲取全部的變數 ] (declared_field):name
[ 獲取全部的變數 ] (declared_field):sex
-----------------------------
[ 獲取變數名 ] :男
[ 設定變數名 ] :女
這些是反射比較常用的方法。在花一杯茶的時間,學會Java反射(實用篇)中,我會寫出一些用到反射的例子。大家若有什麼疑問或意見,請在評論提出,謝謝。若有錯誤或者新的內容,我都會修改此貼。程式碼多了點,但是註釋寫的很清楚了。感謝大家的觀看。
相關文章
- JAVA基礎學習篇之反射Java反射
- 一杯茶的時間,上手 Express 框架開發Express框架
- 一杯茶的時間,上手 React 框架開發React框架
- 【Java 反射學習】Java 反射基礎Java反射
- [Java 反射學習] Java 反射基礎Java反射
- 一杯茶的時間,上手 Git 團隊協作開發Git
- 基礎篇:深入解析JAVA反射機制Java反射
- Java反射—初探反射基礎Java反射
- Java 反射基礎Java反射
- java基礎——反射Java反射
- [Java基礎]反射Java反射
- 震驚!喝個茶的時間就學會了vuexVue
- 泡一杯茶,學一學同非同步非同步
- Java基礎系列—Java反射Java反射
- Java基礎(十八)反射Java反射
- Java-基礎-反射Java反射
- Java基礎(十一)——反射Java反射
- 零基礎學Java需要多長時間?Java
- Java基礎篇(04):日期與時間API用法詳解JavaAPI
- 【Java反射】Java 泛型基礎Java反射泛型
- java基礎 -反射筆記Java反射筆記
- Java學習之反射篇Java反射
- 【Java基礎】RTTI與反射之JavaJava反射
- Java基礎——深入理解反射Java反射
- Java基礎--JDBC-反射等JavaJDBC反射
- 【Java基礎】反射和註解Java反射
- PHP DIY 系列------基礎篇:3. 反射PHP反射
- Java基礎篇Java
- 零基礎學Python-尹會生-極客時間Python
- Java基礎之反射機制(續)Java反射
- Java重點基礎:反射機制Java反射
- 反射基礎反射
- JAVA精髓(基礎篇)Java
- Java基礎對反射知識總結Java反射
- 零基礎學Java-基礎語法篇day1Java
- Java日期時間操作基礎——包含JDK1.8時間操作新特性JavaJDK
- 零基礎學Java-臧萌-極客時間-返現優惠Java
- [Java基礎]Java總結篇Java