您好,登錄后才能下訂單哦!
本篇文章為大家展示了一文帶你讀懂Java中的反射機制,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
什么是反射機制
反射是java語言的一個特性,它允程序在運行時(注意不是編譯的時候)來進行自我檢查并且對內部的成員進行操作。例如它允許一個java的類獲取他所有的成員變量和方法并且顯示出來。這個能特定我們不常看到,但是在其他的比如C或者C++語言中很不就存在這個特性。一個常見的例子是在JavaBean中,一些組件可以通過一個構造器來操作。這個構造器就是用的反射在動態加載的時候來獲取的java中類的屬性的。
主要的類
Class 類的實例表示正在運行的 Java 應用程序中的類和接口。Class沒有公共的構造方法,Class 對象是在加載類時由 Java 虛擬機以及通過調用類加載器中的 defineClass 方法自動構造的
Constructor 提供關于類的單個構造方法的信息以及對它的訪問權限(主要提供的是對構造方法使用)
Method 提供關于類或接口上單獨某個方法(以及如何訪問該方法)的信息。所反映的方法可能是類方法或實例方法(包括抽象方法)
Field 主要提供對類中的成員變量的訪問和使用
Class
Class類也使用了泛型,即是Class
常用的方法
getConstructor(Class[] params) 獲取公共的(public)的構造方法,并且限定其中的參數個數和類型可以獲得不同的公共構造方法
Constructor[] getConstructors() 返回所有的公共(public)的構造方法
getDeclaredConstructor(Class[] params) 獲取所有指定的構造方法,但是需要注意的是當獲取私有的構造方法的時候需要使用setAccessible設置訪問權限為true才能進行構造,否則出現異常
Constructor[] getDeclaredConstructors() 返所有的構造方法包括public和private,protected修飾的
T newInstance() 返回的是一個調用默認的構造方法(public class_name())實例化的一個Object對象,如果使用泛型那么就返回T類型的,反之返回的是Object需要強制轉換才能使用這個對象調用成員函數和成員變量
Class forName(String class_name) 返回class對象,每一個對都有一個方象法返回Class對象(test.class)
Package getPackage() 返回此類所在的包名(package demo) 當然也可以使用Package.getName()獲得包的名字(demo)比如constructor.getPackage().getName()
int getModifiers() 返回的是類的修飾符的整數 類型(修飾符的類型有public private protected)其中得到整數可以使用Modifier中toString(int num)得到public,private,protected的類型,比如Modifier.toString(class1.getModifiers())
*Method getMethod(String name, Class<?>... parameterTypes) 返回指定參數的方法Method對象,注意這里僅僅是返回的時公共的方法(public) 比如:Method method=class1.getMethod("display",new Class[]{int.class})這里的display是方法的名字,有一個參數,類型為int
Method[] getMethods() 獲取所有的公共的方法(public)返回的是一個數組(Method)
Method getDeclaredMethod(String name,Class<?>... parameterTypes)返回所有的指定的參數的方法(public,private,protected,但是不包括繼承的),其中參數可以為null(無參數)
Method[] getDeclaredMethods() 獲取所有的方法
Field getField(String name) 指定名字的公共成員變量(public)
Field[] getFields() 獲取所有的公共的成員變量
Field getDeclaredField(String name) 獲取所有的指定名稱的成員變量(public,protected,private),同樣在調用私有成員變量的時候需要先設置訪問的權限,field.setAccessible(true)
Field[] getDeclaredFields() 獲取所有的成員變量(public,protected,private)
getSuperclass() 返回表示此 Class 所表示的實體(類、接口、基本類型或 void)的超類的 Class。
URL getResource(String name) 查找指定名稱的資源(圖片,文件...)注意這個資源一定要和指定類在一個包中,否則返回null,比如查找Test類下的airplane.png圖片:Test.class.getResource("airplane.png")這里返回的將是絕對路徑
獲取Class的對象并且實例化
使用Class.forName(String className) 其中className一定是包含包的名字,下面的demo就是包的名字,Test是類的名字。這是最常用的方法,學過JDBC的都知道加載驅動的時候就是使用的Class.forName()
/* * 第一種使用forName(String className),其中className一定是包含包的名字,下面的demo就是包的名字,Test是類的名字 */ Class cls=Class.forName("demo.Test"); Test test=(Test)cls.newInstance(); //這里只是使用了默認的構造方法實例化對象
使用類名.class
Class cls=Test.class;
使用對象.getClass()
Test test=new Test(); Class cls=test.getClass();
Constructor
主要是用來對類的構造方法進行操作的,可以看出這個也使用了泛型,和上面的Class是一樣的,注意這里如果沒有使用泛型,那么原本放回T類型的現在都是返回Object
常用的方法
T newInstance(Object parms) 使用帶有參數的構造方法實例化對象,如果使用了泛型,那么返回的就是T類型的,反之返回的是Object類型的,需要強制轉換
getName() 以字符串的形式返回構造方法的名稱,具體的路徑包含包名(demo.Test)
int getModifiers() 和Class類中的方法一樣
Method
主要提供的是對類中的方法的操作
常用的方法
Object invoke(Object obj,object args) 使用得到的Method對象調用方法,obj是類的已經構造好的對象,如果是靜態方法直接寫null,因為靜態方法的調用不需要對象,返回值是Object類型的,如果接受返回值,需要使用強制轉換成相應的類型,args是傳入的參數,如果有多個參數,那么可以直接在后面用逗號添加或者直接創建數組new Object[]{22,"chenjiabing"}比如:method.invoke(test,22,"chenjiabing") method.invoke(test,new Object[]{22,"chenjiabing"})注意:如果調用的private類型的方法,那么需要在前面設置訪問的權限,method.setAccessible(true)
String getName() 返回此方法的名字(display)
Modifier getModifiers() 返回此方法的修飾符的類型表示的整數(public,private...),可以使用Modifier.toString()轉換成字符串形式
Class getReturnType() 返回這個方法的返回類型
String toString() 返回這個方法表示的字符串的形式
Field
主要提供對類的成員變量的操作
常用方法
String getName() 返回變量名字
Object get(Object obj) 返回此變量在指定對象中的值,因為在構造對象的時候每一個傳入的變量的值都不一樣,因此需要使用對象obj。obj表示傳入的對象,返回的Object類型,因此需要強制轉換
void set(Object obj,Object value) 改變obj對象上的變量的值為value
Modifier getModifiers() 返回整數表示修飾的類型
String getType() 獲取變量的類型(int,String,double float.....)
Modifier
Modifier 類提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。修飾符集被表示為整數,用不同的位位置 (bit position) 表示不同的修飾符。
常用的方法
static String toString(int mode) 將代表修飾符的整數形式轉換為字符串形式的修飾符,比如將1轉換成public
static isInterface(int mode) 如果整數參數包括 interface 修飾符,則返回 true,否則返回 false
static isStatic(int mode)
static isPrivate(int mode)
static isPublic(int mode)
static isAbstract(int mode)
實例
Modifier.toString(Test.class.getModifiers()) //得到Test類的修飾符
使用
有了上面的鋪墊,我們就可以使用上面的這些類進行操作了,在進行操作之前,我們需要先定義一個類Test,放在demo包下,內容如下
package demo; import java.util.jar.Attributes.Name; import javax.print.attribute.standard.MediaSize.NA; public class Test { public String name; private int age; public Test() { this.name = "陳加兵"; this.age = 23; } public Test(String name, int age) { this.name = name; this.age = age; } public void display() { System.out.println("name=" + this.name + "----age=" + this.age); } public void set(String name, int age) { this.name = name; this.age = age; } private int getAge() { return this.age; } }
實例化對象
使用Class默認的構造newInstance()
Class class1=Class.forName("demo.Test"); //靜態加載Class Test test=(Test)class1.newInstance(); //調用默認的構造方法(public Test())實例化對象,由于沒有使用泛型,因此需要強轉 test.display(); //調用display方法
使用Class中的getConstructor()方法構造對象,需要注意的使用private類型構造方法時一定要先設置訪問權限為true-constructor.setAccessible(true);
/* *調用public Test(String name,int age)得到Constructor的兩種形式 * 1.Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class}); * 2.Constructor constructor=class1.getConstructor(String.class,int.class);這個和上面的是一樣的,就是使用的參數形式不一樣 * * * * *使用newInstance()構造對象的兩種方式 * 1.Test test=(Test)constructor.newInstance(new Object[]{"chenjiabing",22}); * 2.Test test=(Test)constructor.newInstance("chenjiabing",22); 只是形式不同而已,不過我還是喜歡上面的形式 * */ /* * 調用public Test(String name,int age) * Class.getConstructor()得到的是公共的構造方法,如果有私有的構造方法,那么就會報錯,這時就要使用getDeclaredConstructor(Class<?>... parameterTypes) * Test test=(Test)constructor.newInstance("陳加兵",22); * * * 調用public Test() * Constructor constructor=class1.getConstructor(null); * Test test=(Test)constructor.newInstance(null); * * * 調用private Test(int age) * Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class}); constructor.setAccessible(true); //因為private類型是不可以直接訪問的,因此需要設置訪問權限為true Test test=(Test)constructor.newInstance(new Object[]{1000}); */ Class class1=Class.forName("demo.Test"); //訪問public Test(String name,int age) // Constructor constructor=class1.getConstructor(new Class[]{String.class,int.class}); // Test test=(Test)constructor.newInstance("陳加兵",22); //訪問默認的構造方法 // Constructor constructor=class1.getConstructor(null); // Test test=(Test)constructor.newInstance(null); //訪問private類型的構造方法 Constructor constructor=class1.getDeclaredConstructor(new Class[]{int.class}); constructor.setAccessible(true); Test test=(Test)constructor.newInstance(new Object[]{1000}); test.display();
成員方法的操作
使用Class.getMethod()和Class.getDeclaredMethod()方法獲取方法,這兩個方法的區別前面已經說過了,注意的是調用私有成員方法的之前一定要設置訪問權限(method.setAccessible(true))
Method類中的其他方法前面也已經說過了,詳細使用請自己嘗試
/* * 獲取Method對象的兩種方式: * 1.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); * 2.Method method_set=class1.getMethod("set", String.class,int.class); * * * 使用Method.invoke()調用方法的兩種方式 * 1.Object o=method_set.invoke(test, new Object[]{"陳加兵",200}); * 2.Object object=method_set.invoke(test, "陳加兵",2000); */ /* * 獲取公共方法(public): * 1.Method method=class1.getMethod("display",null); //public void display() * 2.Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); //獲取public void set(String name,int age) * * * 獲取私有方法(private,protected) * 1.Method method_getAge=class1.getDeclaredMethod("getAge", null); */ //使用構造方法構造一個Test對象 Class class1 =Class.forName("demo.Test"); Constructor<Test> constructor=class1.getDeclaredConstructor(new Class[]{String.class,int.class}); Test test=constructor.newInstance(new Object[]{"陳加兵",22}); Method method=class1.getMethod("display",null); //獲取public void display()方法的Method對象 Object obj=method.invoke(test, null); //調用方法display //獲取public void set(String name,int age) // Method method_set=class1.getMethod("set", new Class[]{String.class,int.class}); Method method_set=class1.getMethod("set", String.class,int.class); // Object o=method_set.invoke(test, new Object[]{"陳加兵",200}); Object object=method_set.invoke(test, "陳加兵",2000); test.display(); //獲取私有方法private int getAge() Method method_getAge=class1.getDeclaredMethod("getAge", null); method_getAge.setAccessible(true); //必須設置訪問權限為true //判斷返回值類型是否為int類型的 if("int".equals(method_getAge.getReturnType().toString())) { int ReturnData=(int) method_getAge.invoke(test, null); //調用并且獲取返回值 System.out.println(ReturnData); }
成員變量的操作
主要使用的Field類,前面已經詳細的說過了
/* * 獲取public修飾的成員變量: * 1.Field field=class1.getField("name"); //獲取public的成員變量name的Filed對象 * * 獲取private,protected修飾的成員變量: * 1. Field field2=class1.getDeclaredField("age"); */ Class class1=Class.forName("demo.Test"); Test test=new Test("陳加兵",1000); Field field=class1.getField("name"); //獲取public的成員變量name的Filed對象 System.out.println(field.get(test)); //獲得test對象中的name屬性的值 //獲取private int age的Field對象 Field field2=class1.getDeclaredField("age"); field2.setAccessible(true); //設置訪問權限 System.out.println(field2.get(test));
上述內容就是一文帶你讀懂Java中的反射機制,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。