淺談Java反射

今天來學習一下Java的反射機制,若有不當請多指教!學習

概述

反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。code

Java中的反射主要和Class類有關。Class類沒有公共構造方法。Class 對象是在加載類時由 Java 虛擬機以及經過調用類加載器中的defineClass方法自動構造的。也就是說不須要咱們本身去處理建立,JVM已經幫咱們建立好了。對象

反射的使用

獲取Class對象

一、getClass()

getClass()是Object類中的方法,也就是說每一個類都有本身的Class對象。字符串

Student s1 = new Student();//這一new 產生一個Student對象,一個Class對象。
Class stuClass1 = s1.getClass();

二、.class

任何數據類型(包括基本數據類型)都有一個「靜態」的class屬性,好比String.Classget

Class stuClass2 = Student.class;

三、Class.forName(String className) —— 推薦

經過Class類的靜態方法forName獲取Class對象(經常使用)編譯器

Class stuClass3 = Class.forName("czy.Student");//注意此字符串必須是真實路徑→包名.類名

注意:在運行期間,一個類,只有一個Class對象產生。虛擬機

獲取構造方法

public class Constructors {
 
    public static void main(String[] args) throws Exception {
        //1.加載Class對象
        Class c = Class.forName("czy.Student");
        
        //2.獲取全部公有構造方法
        Constructor[] conArray = c.getConstructors();
    
        //三、獲取全部的構造方法(包括:私有、受保護、默認、公有)
        Constructor[] conArray = c.getDeclaredConstructors();
        
        //四、獲取公有、無參的構造方法
        Constructor con = c.getConstructor();
        //由於是無參的構造方法因此類型是一個null,不寫也能夠:這裏須要的是一個參數的類型,切記是類型
        //調用構造方法
        Object obj = con.newInstance();
        
        //五、獲取私有構造方法,並調用
        con = c.getDeclaredConstructor(char.class);
        //調用構造方法
        con.setAccessible(true);//暴力訪問(忽略掉訪問修飾符)
        obj = con.newInstance('男');
    }    
}

獲取成員變量

public class Fields {
 
        public static void main(String[] args) throws Exception {
            //一、獲取Class對象
            Class stuClass = Class.forName("czy.Student");
   
            //二、獲取全部公有的字段
            Field[] fieldArray = stuClass.getFields();
            
            //三、獲取全部的字段(包括私有、受保護、默認的)
            Field[] fieldArray = stuClass.getDeclaredFields();
            
            //四、獲取公有字段"name"並調用
            Field f = stuClass.getField("name");
             //獲取一個對象
            Object obj = stuClass.getConstructor().newInstance();//產生Student對象--》Student student = new Student();
             //爲字段設置值
            f.set(obj, "劉德華");//爲Student對象中的name屬性賦值--》student.name = "劉德華"
            
            //五、獲取私有字段"phone"並調用
            f = stuClass.getDeclaredField("phone");
            f.setAccessible(true);//暴力反射,解除私有限定
            f.set(obj, "13415038974");
        }
    }

獲取成員方法

public class MethodClass {
 
    public static void main(String[] args) throws Exception {
        //1.獲取Class對象
        Class stuClass = Class.forName("czy.Student");
  
        //2.獲取全部公有方法
        Method[] methodArray = stuClass.getMethods();
    
        //3.獲取全部的方法,包括私有的
        Method[] methodArray = stuClass.getDeclaredMethods();
        
        //4.獲取公有的show1()方法
        Method m = stuClass.getMethod("show1", String.class);
        //調用show1()方法
        Object obj = stuClass.getConstructor().newInstance();
        m.invoke(obj, "劉德華");
        
        //5.獲取私有的show4()方法
        m = stuClass.getDeclaredMethod("show4", int.class);
        m.setAccessible(true);//解除私有限定
        Object result = m.invoke(obj, 20);//須要兩個參數,一個是要調用的對象(由反射獲取),一個是實參
    }
}

反射的其它用法

經過反射越過泛型檢查

例如:有一個String泛型的集合,怎樣能向這個集合中添加一個Integer類型的值?io

public class Demo {
   public static void main(String[] args) throws Exception{
            ArrayList<String> strList = new ArrayList<>();
            strList.add("aaa");
            strList.add("bbb");
        
            //獲取ArrayList的Class對象,反向的調用add()方法,添加數據
        Class intClass = strList.getClass(); //獲得 strList 對象的字節碼 對象
        //獲取add()方法
        Method m = intClass.getMethod("add", Object.class);
        //調用add()方法
        m.invoke(strList, 100);
    }
}

固然這樣只能躲過編譯器檢查,去遍歷的話仍是會拋出異常的。編譯

相關文章
相關標籤/搜索