1. 程式人生 > >Java-API-Class類詳解、用法及泛化

Java-API-Class類詳解、用法及泛化

Java-API-Class類詳解、用法及泛化

轉載宣告:

本文系轉載自以下文章:

轉載僅為方便學習檢視,一切權利屬於原作者,本人只是做了整理和排版,如果帶來不便請聯絡我刪除。

0x01 摘要

Java程式在執行時,JavaRuntime一直對所有的物件進行執行時型別標識,即所謂的RTTI。這項資訊紀錄了每個物件所屬的Class。虛擬機器通常使用執行時型別資訊選準正確方法去執行,用來儲存這些型別資訊的類是Class類,他封裝了一個物件或介面執行時的狀態。當裝載類時,Class型別的物件會被自動建立。

0x02 什麼是Class類

  • Class類也是類的一種,只是名字和class關鍵字高度相似。
  • Class類的物件內容是建立的類的型別資訊。比如你建立一個shapes類物件例項,那麼,Java會生成一個內容是shapes的Class類的物件
  • Class類的物件不能像普通類一樣,以 new shapes() 的方式建立,它的物件只能由JVM通過反射建立,因為這個類沒有public建構函式
  • Class類的作用是執行時提供或獲得某個物件的型別資訊,這些資訊也可用於反射。

0x03 Class類原理

我們都知道所有的java類都是繼承了Object這個類,其中有一個方法:getClass()

,用來取得該類已經被例項化了的物件對應類的引用。這個引用指向的是Class類的物件。

我們自己無法生成一個Class物件(建構函式為private),而這個Class類的物件是在當各類被載入時,由 JVM自動建立 ,或通過ClassLoader中的 defineClass 方法生成。我們生成的物件都會有個Field來記錄該物件所屬類在Class類的物件的所在位置。如下圖所示:
Class類物件

0x03 獲得一個Class類物件

  1. Class類的forName方法
public class shapes{}  
Class obj= Class.forName("shapes");
  1. 使用物件的getClass()
    方法
public class shapes{}
shapes s1=new shapes();
Class obj=s1.getClass();
//這個函式作用是獲取shapes類的父類的class物件
Class obj1=s1.getSuperclass();
  1. 使用類字面常量
Class obj=String.class;
Class obj1=int.class;

注意,使用第三種方法生成Class類物件時,不會使JVM自動載入該類(如String類)。而其他辦法會使得JVM初始化該類。

0x04 使用Class類的物件來生成目標類的例項

  • 生成不精確的Oobject例項
    獲取一個Class類的物件後,可以用 newInstance()函式來生成目標類的一個例項。然而,該函式並不能直接生成目標類的例項,只能生成Object類的例項
Class obj=Class.forName("shapes");
Object ShapesInstance=obj.newInstance();
  • 使用泛型 Class引用生成帶型別的目標例項
Class<Shapes> obj=Shapes.class;
Shapes newShape=obj.newInstance();
  • 因為有了型別限制,所以使用泛化Class語法的物件引用不能指向別的類。
Class obj1=int.class;
Class<Integer> obj2=int.class;
obj1=double.class;
//obj2=double.class; 這一行程式碼是非法的,obj2不能改指向別的類了
  • 然而,有個靈活的用法,使得你可以用Class的物件指向基類的任何子類。
Class<? extends Number> obj = int.class;
obj = Number.class;
obj = double.class;

因此,以下語法生成的Class物件可以指向任何類。

Class<?> obj = int.class;
obj = double.class;
obj = Shapes.class;

最後一個奇怪的用法是,當你使用這種泛型語法來構建你手頭有的一個Class類的物件的基類物件時,必須採用以下的特殊語法

public class Shapes{}
class Round extends Shapes{}
Class<Round> rclass = Round.class;
Class<? super round> sclass= rclass.getSuperClass();
//Class<shapes> sclass=rclass.getSuperClass();