類加載機制以及Java-Reflect(反射)

一、類加載過程

1、類的生命週期

指的是一個類被加載到JVM中運行到被卸載的過程,類的生命週期主要經過了類加載,驗證,準備,解析,初始化,使用和卸載7個步驟。

2、類加載

主要是把class文件加載到JVM中,同時生成該類所對應的Class對象,該class對象是Java反射的起源,通過該對象可以在類運行期間‘窺探’類的結構信息。


3、類的連接

   (1)驗證:JVM負責檢查被加載的類是否有正確的內部結構

   (2)準備:負責爲類變量分配內存

   (3)解析:將類在編譯期間的符號引用轉換爲直接引用

com.imooc.reflect.Foo@15db9742


4、類的初始化:JVM負責對類的靜態內容進行初始化,而非靜態內容則是等到實例化階段才初始化。

5、類的使用:類在JVM 中被使用,例如:實例化對象,讀取和設置變量等信息

6、類的卸載:主要是使用GC對實例進行回收,在方法區清空類的信息等

 

二、JVM將內存劃分區域:


1、棧內存:主要用來存儲局部變量,對象的引用,方法的入口等信息

2、堆內存:主要用來存儲通過new運算符創建的對象

3、方法區:主要用來存儲類的結構信息,靜態變量等內容

4、本地方法棧:用來在底層調用非Java語言編寫的應用程序。

5、程序計數器:用來存儲線程的指令地址




類加載器(ClassLoader)負責將.class文件加載到內存中,併爲之生成對應的Java.lang.Class對象,此外,其加載機制爲“非一次性加載,而是在需要的時候加載”

在JVM中,類從被加載到虛擬機內存中開始,到卸載出內存爲止,它的整個生命週期包括:加載、驗證、準備、解析、初始化、使用和卸載7個階段


在java中,一個java類將會編譯成一個class文件。在編譯時,java類並不知道引用類的實際內存地址,因此只能使用符號引用來代替。比如org.simple.People類引用org.simple.Tool類,在編譯時People類並不知道Tool類的實際內存地址,因此只能使用符號org.simple.Tool(假設)來表示Tool類的地址。而在類裝載器裝載People類時,此時可以通過虛擬機獲取Tool類 的實際內存地址,因此便可以既將符號org.simple.Tool替換爲Tool類的實際內存地址,及直接引用地址


反射機制指的是程序在運行時能夠獲取類的信息。在java中,只要給定類的名字,那麼就可以通過反射機制來獲得類的所有信息。

反射機制的優點就是可以實現動態創建對象和編譯,體現出很大的靈活性,特別是在J2EE的開發中,在編碼階段不知道那個類名,要在運行期從配置文件讀取類名, 這時候就沒有辦法硬編碼new ClassName(),而必須用到反射才能創建這個對象。



三、反射

1、反射是什麼

能夠分析類能力的程序成爲“反射”

2、反射機制作用

--在運行時分析類的能力
--在運行時查看類的對象(eg:編寫一個toString方法供所有類使用)
--實現通用的數組操作代碼
--利用Method對象

四、關於反射

一、Class類--可獲取類和類的成員信息


在面向對象的世界,萬事萬物皆對象

類是對象,類是java.lang.Class類的實例對象

There is a classnamed Class

 

在Java中每個類被加載之後,系統就會爲該類生成一個對應的

Class對象,通過該Class對象就可以訪問到JVM中的這個類了,繼而

獲取該類的相關信息。在Java程序中獲得 Class 對象有如下三種方式:

 

1、 使用Class類的forName(String clazzName)靜態方法。該方法需要傳入字符串參數,該字符串參數的值是某個類的全限定類名(即必須添加完整包名和類名)


Class c1 =Class.forName("com.ysit.reflect.Demo");

Class.forName(“類的全稱”)

A、不僅表示了類的類類型,還代表了動態加載類

B、區分編譯、運行

C、編譯時刻加載類是靜態加載類

運行時刻加載類是動態加載類

  *new創建對象 是靜態加載類,在編譯時刻就需要加載所有的可能使用到的類。

  *通過Class.forName(動態加載類),在運行時刻加載

 

2、 調用某個類的class屬性來獲取該類對應的Class對象。例如:person.class將會返回person類對應的Class對象。

 

//實際在告訴我們任何一個類都有一個隱含的靜態成員變量class

       Class c2 = Demo.class;

 

3、 調用某個對象的getClass()方法。該方法是Object類的一個方法,所以所有的Java對象都可以調用該方法,該方法將會返回該對象所屬類對應的class對象。

Eg:

    Demodemo = new Demo();

    //已經知道該類的對象通過grtClass方法

    Classc3 = demo.getClass();

 

System.out.println(c2== c3);  //true

System.out.println(c1== c2);  //true


二、Constructor類—可調用類的構造方法






// Class的newInstance()方法是實現"虛擬構造器"的一種途徑
//虛擬構造器允許你聲明:我不知道你的確切類型,但是無論如何要正確地創建你自己
//使用newInstance()來創建的類,必須帶有默認的構造器






如果類中有有參構造,那麼利用反射進行實例化對象時需要以下步驟:


1、  訪問該類的有參構造,同時傳入該有參構造類型對應的Class對象

2、  調用Constructor對象的newInstance()方法




三、Field類—可訪問類的屬性  






四、Method類—可調用類的方法 





五、注意:反射的操作都是編譯之後的操作


Java中集合的泛型,是防止錯誤輸入的,只在編譯階段有效,繞過編譯就無效了
驗證: 通過反射的反射繞過編譯來證明



總結一下:





發佈了51 篇原創文章 · 獲贊 45 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章