要想在IT領域站得住腳,必須得不斷地學習來強化本身,可是學過的技術不實踐很容易便被遺忘,因此一直都打算開個博客,來記錄本身學的知識,另外也能夠分享給有須要的人!java
最近在學習反射,爲了更好地理解反射,就去查各類資料學習了java類型信息。程序員
目錄數組
1、前言框架
在瞭解java類型信息前,須要先了解咱們編寫的類在Java中是如何加載的,以及Class類的基本概念和做用,以方便咱們更好理解Java類型信息。學習
2、類的加載和初始化 this
2.1 類的加載編碼
當程序要使用某個類時,若是該類還未被加載到內存中,則系統會經過加載,鏈接,初始化三步來實現對這個類的初始化。spa
2.2 類的加載時機翻譯
2.3類加載器代理
2.4 雙親委派模型
類加載器Java類如同其餘的Java類同樣,也是要由類加載器來加載的。除了啓動類根類加載器每一個類都有其父類加載器(父子關係有組合(不是繼承)來實現)。
所謂雙親委派模型是指每次收到類加載請求時,先將請求委派給父類加載器完成(全部加載請求最終會委派到頂層的Bootstrap Class Loader加載器中),若是父類加載器沒法完成這個加載(該加載器的搜索範圍沒有找到對應的類),子類嘗試本身加載。
雙親委派好處
3、Class類
Class類封裝一個對象和接口的運行時的狀態(即在這個類的對象中記錄每一個對象所屬的類,保存類的類型信息)。操做類對象在使用前會經歷上文所說的加載過程(加載、裂解和初始化),併爲之建立一個Class類的對象---Class對象,存放在操做類的.class文件中。這個Class類對象與操做類class是一一對應的,即當一個操做類被加載後,就不會重複加載。而經過該class對象,就能夠訪問對應的class。咱們能夠把Class理解爲一個類的標識對象,它至關因而一個類的銘牌。拿到一個Class,咱們就能夠找到對應的類。
注意,Class類沒有公有(public)構造方法,所以不能顯式地聲明一個Class對象,只在類加載時建立。
從Class對象中能夠得到的信息:
另外,網上不少帖子說,一旦某個操做類的Class對象被載入內存,就用它來產生該操做類的全部對象!
獲取Class對象的三種方式:
1 Dog dog; 2 Class class = dog.getClass();
1 Class class = Class.forName("Dog");
1 Class class = Dog.class;
Class類經常使用的方法:
4、Java類型信息
咱們知道,咱們的程序在運行時,某一個操做類能夠回被實例化多個對象,一個程序也可能擁有若干個不一樣操做類的多個對象,那麼Java如何在運行時識別對象所屬和類的信息的呢?答案是運行時類型信息(Run-Time Type Identification),RTTI使得你能夠在程序運行時發現和使用類型信息。
1、RTTI概要
2、RTTI的實現方式
3、傳統RTTI的使用
1 abstract class Shapes{ 2 void draw(){ 3 System.out.println(this+".draw()"); 4 } 5 abstract public String toString(); 6 } 7 8 class Circle extends Shapes{ 9 public String toString(){ 10 return "Circle"; 11 } 12 } 13 class Triangle extends Shapes{ 14 public String toString(){ 15 return "Triangle"; 16 } 17 } 18 class Square extends Shapes{ 19 public String toString(){ 20 return "Square"; 21 } 22 } 23 class Test{ 24 public static List<Shapes>getList(){ 25 List<Shapes> list_aShapes = Arrays.asList(new Circle,new Square,new Triangle); 26 } 27 } 28 29 public class Shape{ 30 public static void main(String args[]){ 31 List<Shapes> list_aShapes = Test.getList(); 32 for(Shapes shape:list_aShapes){ 33 shape.draw(); 34 } 35 } 36 }
運行結果:Circle.draw()
Square.draw()
Triangle.draw()
結果分析:
上面代碼中,shape對象只是一個泛化引用,顯然一開始系統並不知道泛華引用的確切類型,咱們但願使用的是shape對象對應的確切類型,這是,就須要系統使用RTTI。上例,只是打印出泛化引用的全部類型。進一步解析,Circle,Square,Triangle三個類都繼承了抽象類Shape,現有一個List<Shape>的數組,存的是Circle,Square.Triangle的對象,當你拿出一個對象時,你只知道她是Shape類,但不知道它的具體類型。使用RTTI,能夠查詢到某個shape引用所指向對象的具體類型。
4、反射機制
java反射的官方介紹是 反射機制是在運行中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性。
反射機制能作什麼?
其實,咱們在學習框架時可以發現反射的普遍應用,經過反射和一個未知類型的對象打交道,Class類和java.lang.reflection類庫一塊兒對反射做技術支撐,該類庫包含Field,Method和Constructor類,這些類的對象由JVM啓動時建立,用以表示未知類裏對應的成員。
關於反射的詳細內容以後的文章會介紹!
5、傳統RTTI和反射的共同點和區別
區別:
1、若是該類在編譯前就已知。也就是該類在classPath路徑下。這就是傳統RTTI。
2、若是該類編譯器未知,也就是在程序運行時才知道的。這就是反射
因此RTTI和反射的本質區別只是檢查一個類的.class文件的時機不一樣,反射:.class 文件是在編譯時不可得到的,因此在運行時打開和檢查未知類的.class文件從而變已知。RTTI: .class 文件是在編譯時打開和檢查。
相同點:都是基於Class類來執行的,均可以獲取類的類型信息。
6、總述
其實你們會發現,相比於反射,咱們基本不會接觸到傳統RTTI機制,這是爲什麼呢?其實它的名字已經給出了答案,這是一個機制---傳統RTTI機制,其實在Java不少地方都依賴於這個機制來實現,好比說多態(當咱們把子類對象的引用賦給父類對象的狀況時,須要使用RTTI去識別該對象所屬的類),因此說這並非可有可有的。咱們也能夠在網上的不少文章看到,不少文章都是把RTTI分爲傳統RTTI和反射,以闡述java類型信息的詳情,這樣咱們便可以很好地學習反射,也搞清楚了Java在運行時對於對象的識別方法。