java反射的原理,作用


 

什么是反射,反射原理

  java類的執行需要經歷以下過程

    編譯:.java文件編譯后生成.class字節碼文件
    加載:類加載器負責根據一個類的全限定名來讀取此類的二進制字節流到JVM內部,並存儲在運行時內存區的方法區,然后將其轉換為一個與目標類型對應的java.lang.Class對象實例
    連接:細分三步
        驗證:格式(class文件規范) 語義(final類是否有子類) 操作
        准備:靜態變量賦初值和內存空間,final修飾的內存空間直接賦原值,此處不是用戶指定的初值。
        解析:符號引用轉化為直接引用,分配地址
    初始化:有父類先初始化父類,然后初始化自己;將static修飾代碼執行一遍,如果是靜態變量,則用用戶指定值覆蓋原有初值;如果是代碼塊,則執行一遍操作。

什么是反射:

  Java的反射就是利用上面第二步加載到jvm中的.class文件來進行操作的。.class文件中包含java類的所有信息,當你不知道某個類具體信息時,可以使用反射獲取class,然后進行各種操作。

  Java反射就是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;並且能改變它的屬性

要想解剖一個類,必須先要獲取到該類的字節碼文件對象(class)。而解剖使用的就是Class類中的方法.所以先要獲取到每一個字節碼文件對應的Class類型的對象.)

 

關於class對象和這個Class類

  • Class對象的由來是將class文件讀入內存,並為之創建一個Class對象

    

 

 

 Class類

  class類 :代表一個類,是Java反射機制的起源和入口

  用於獲取與類相關的各種信息, 提供了獲取類信息的相關方法
  Class類繼承自Object類

  Class類是所有類的共同的圖紙

  每個類有自己的對象,同時每個類也看做是一個對象,有共同的圖紙Class,存放類的結構信息,能夠通過相應方法取出相應的信息:類的名字、屬性、方法、構造方法、父類和接口。

獲取class對象(反射入口)的三種方式

  要想操作反射,必須先拿到反射的入口

  1,通過通過Class.forName("全類名") 靜態方法來獲取,用的最多 

    Class c3 = Class.forName("reflect_fanshe.Person");
Class<?> perClazz = Class.forName("reflect_fanshe.Person");

  2,類名.class

    /2、類名.class 的方式得到,該方法最為安全可靠,程序性能更高
    //  這說明任何一個類都有一個隱含的靜態成員變量 class
    Class c2 = Person.class;

Class<?> perClazz2 = Person.class;

  3,對象.getClass()

Person person = new Person();
Class<?> perClazz3 = person.getClass();

Class具有的部分方法如下:     

     getName():獲得類的完整名字。
  getFields():獲得類的public類型的屬性
  getDeclaredFields():獲得類的所有屬性。包括private 聲明的和繼承類
  getMethods():獲得類的public類型的方法。
  getDeclaredMethods():獲得類的所有方法。包括private 聲明的和繼承類
  getMethod(String name, Class[] parameterTypes):獲得類的特定方法,name參數指定方法的名字,parameterTypes 參數指定方法的參數類型。
  getConstructors():獲得類的public類型的構造方法。
  getConstructor(Class[] parameterTypes):獲得類的特定構造方法,parameterTypes 參數指定構造方法的參數類型。
  newInstance():通過類的不帶參數的構造方法創建這個類的一個對象

通過反射獲取對象的實例,並操作對象

  1,class.newInstance() ,並強轉類型,然后就可以操作對象了,主要是調用方法。

    

 

   

  2,操作屬性,可以操作類里面的public屬性和private屬性  如果屬性是private,正常情況下是不允許外界操作屬性值,這里可以用Field類的setAccessible(true)方法,暫時打開操作的權限

       

 

反射方法的使用之---通過反射運行配置文件內容

  student類:

public class Student {
    public void show(){
        System.out.println("is show()");
    }
}

  配置文件以txt文件為例子(pro.txt):

className = cn.fanshe.Student
methodName = show

  測試類:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
 
/*
 * 我們利用反射和配置文件,可以使:應用程序更新時,對源碼無需進行任何修改
 * 我們只需要將新類發送給客戶端,並修改配置文件即可
 */
public class Demo {
    public static void main(String[] args) throws Exception {
        //通過反射獲取Class對象
        Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
        //2獲取show()方法
        Method m = stuClass.getMethod(getValue("methodName"));//show
        //3.調用show()方法
        m.invoke(stuClass.getConstructor().newInstance());
        
    }
    
    //此方法接收一個key,在配置文件中獲取相應的value
    public static String getValue(String key) throws IOException{
        Properties pro = new Properties();//獲取配置文件的對象
        FileReader in = new FileReader("pro.txt");//獲取輸入流
        pro.load(in);//將流加載到配置文件對象中
        in.close();
        return pro.getProperty(key);//返回根據key獲取的value值
    }
}
   控制台輸出:is show()
  

需求:

  當我們升級這個系統時,不要Student類而需要新寫一個Student2的類時,這時只需要更改pro.txt的文件內容就可以了。代碼就一點不用改動

  新寫一個student2的類:

public class Student2 {
    public void show2(){
        System.out.println("is show2()");
    }
}

  配置文件更改為:

className = cn.fanshe.Student2
methodName = show2

  控制台輸出:is show2()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM