Java Class類詳解
最近的Java學習中又學習了一遍工廠模式,其中寫到這樣一句程式碼Class.forName(className).newInstance()
,當時沒注意,但是最後程式報錯了,在除錯的過程中注意到該句有問題,於是開啟了百度之旅,這次旅途還真是收穫不少
一:Class類的簡介
首先宣告的是Class類是Java的一個類,與我們平時自定義的類一樣,只不過名字較特殊,也是繼承了Object類,官網是這樣定義的:
public final class Class<T>
extends Object
implements Serializable, GenericDeclaration, Type, AnnotatedElement
從程式碼中可看出,它是一個靜態類,繼承了Object類,實現了介面。
Java程式在執行時,Java執行時系統一直對所有的物件進行所謂的執行時型別標識。這項資訊紀錄了每個物件所屬的類。JVM通常使用執行時型別資訊選準正確方法去執行,用來儲存這些型別資訊的類是Class類。Class類封裝一個物件和介面執行時的狀態,當裝載類時,Class型別的物件自動建立。
Class 沒有公共構造方法。Class 物件是在載入類時由JVM以及通過呼叫類載入器中的 defineClass 方法自動構造的,因此不能顯式地宣告一個Class物件。
虛擬機器為每種型別管理一個獨一無二的Class物件。也就是說,每個類(型)都有一個Class物件。執行程式時,JVM首先檢查是否所要載入的類對應的Class物件是否已經載入。如果沒有載入,JVM就會根據類名查詢.class檔案,並將其Class物件載入
基本的 Java 型別(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也都對應一個 Class 物件。
每個陣列屬於被對映為 Class 物件的一個類,所有具有相同元素型別和維數的陣列都共享該 Class 物件。
一般某個類的Class物件被載入記憶體,它就用來建立這個類的所有物件。用一段程式碼來表示:
Date date1 = new Date();
Date date2 = new Date();
Class c1 = date1.getClass();
Class c2 = date2.getClass();
System.out.println(c1 == c2); // true
可以看出,例項化出的物件是同一個物件。因為對於相同的類,JVM只會載入一次,而與該類對應的Class物件也只會存在一個,無論該類例項化了多少物件。實上,Class物件就是用來建立類的所有的“普通”物件的。 類是程式的一部分,每個類都有一個Class物件。換言之,每當編寫並且編譯了一個新類,就會產生一個Class物件(恰當地說,是被儲存在一個同名的.class檔案中)。在執行時,當我們想生成這個類的物件時,執行這個程式的 Java虛擬機器(JVM)首先檢查這個類的Class物件是否已經載入。如果尚未載入,JVM就會根據類名查詢.class檔案,並將其載入。 一旦某個類的Class物件被載入記憶體,它就被用來建立這個類的所有(例項)物件
二:得到Class型別物件的3種方法
- 呼叫Object類的getClass()方法來得到Class物件,這也是最常見的產生Class物件的方法
- 使用Class類的中靜態forName()方法獲得與字串對應的Class物件
- 如果T是一個Java型別,那麼T.class就代表了匹配的類物件
public class TestClass {
public static void main(String[] args)
{
try {
// 測試Class.forName()
Class testTypeForName = Class.forName("TestClassType");
System.out.println("testForName---" + testTypeForName);
// 測試類名.class
Class testTypeClass = TestClassType.class;
System.out.println("testTypeClass---" + testTypeClass);
// 測試Object.getClass()
TestClassType testGetClass = new TestClassType();
System.out.println("testGetClass---" + testGetClass.getClass());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class TestClassType {
// 建構函式
public TestClassType() {
System.out.println("----建構函式---");
}
// 靜態的引數初始化
static {
System.out.println("---靜態的引數初始化---");
}
// 非靜態的引數初始化
{
System.out.println("----非靜態的引數初始化---");
}
}
執行結果:
---靜態的引數初始化---
testForName---class TestClassType
testTypeClass---class TestClassType
----非靜態的引數初始化---
----建構函式---
testGetClass---class TestClassType
由上面結果可看出:
- forName()呼叫的是靜態的引數初始化;new是先呼叫非靜態的引數初始化,然後呼叫建構函式
- 生成Class物件是一樣的,其實在JVM中只生成了一個Class物件,
- 只列印一次“靜態的引數初始化”,靜態的方法屬性初始化時,是在載入類的時候初始化;非靜態方法是new類例項物件的時候初始化的
三:常用方法
Class.forName(字串)
- 字串內容為:包名.類名(即完整的類路徑)
- 返回的是一個類
- 首先Java中任何class都要裝載在JVM上才能執行,這句話作用就是用來在JVM中查詢並載入指定的類
newInstance()
- 建立物件
- 上面講到Class.forName(字串)來裝載類的,都知道類在使用時必須建立物件後才能使用,該句話用來建立物件的
- 與new的區別
- 直觀看來它是一個方法,new是一個關鍵字
- new建立一個類時,這個類可以沒有被載入,但是可能需要classloader來載入;newInstance()方法必須保證該類已載入,而且已連線了
- new是動態載入,newInstance()靜態載入
- new是強型別,效率教高,能呼叫任何public構造;newInstance()是弱型別,效率較低,只能呼叫無參構造
四:應用情景
Java的Class類是Java反射機制的基礎,通過Class類可獲得關於這個類的相關資訊
- 載入資料庫驅動時
JdbcConfig jdbcConfig = XmlConfigReader.getInstance().getJdbcConfig();
//載入驅動
Class.forName(jdbcConfig.getDriverName());
conn = DriverManager.getConnection(jdbcConfig.getUrl(),jdbcConfig.getUserName(),jdbcConfig.getPassword());
- 使用工廠模式時
使用工廠模式時,通常會根據讀取到的配置檔案裡的資訊來建立具體的工廠,然後通過該具體工廠建立具體的產品,當想使用別的工廠生產別的產品時,只需改一下配置檔案即可,這樣提高了軟體的可伸縮性、可擴充套件性
String className = XmlConfigReader.getInstance().getDaoFactory("item-dao-factory");
ItemDaoFactory factory = null;
//例項化一個工廠
factory = (ItemDaoFactory)Class.forName(className).newInstance();
總結
- 可以說工廠模式學了很多遍了,但是這一次的學習又有了新認識,看來知識要不斷應用
- 理解明白一些底層程式碼還是非常重要的,明白了執行機制,感覺思路順暢了好多
相關文章
- Java語言class類用法及泛化(詳解)Java
- java class檔案詳解Java
- Java Class檔案詳解Java
- Java中的java.lang.Class API 詳解JavaAPI
- Class詳解
- Kotlin——中級篇(一):類(class)詳解Kotlin
- java反射之Class類Java反射
- [Java]File類詳解Java
- [Java]RandomAccessFile類詳解JavarandomMac
- Java集合類詳解Java
- 理解java.lang.Class類Java
- Java內部類詳解Java
- Java 內部類詳解Java
- generator class="" id詳解
- Java Class 位元組碼檔案結構詳解Java
- JAVA Class類檔案結構Java
- Java類載入器詳解Java
- Java 內部類使用詳解Java
- java之內部類詳解Java
- Java內部類詳解--匿名內部類Java
- Class 檔案格式詳解
- Java | 頂層類(Top-Level Class)Java
- Java基礎-內部類詳解Java
- Java 類載入機制詳解Java
- Java類的生命週期詳解Java
- Java中的類與物件詳解Java物件
- Java內部類詳解-- 成員內部類Java
- Java類載入機制詳解【java面試題】Java面試題
- Java | 靜態巢狀類(Static Nested Class)Java巢狀
- 詳解 Java 17 中新推出的密封類Java
- Java File 類的使用方法詳解Java
- Java中的介面與抽象類詳解Java抽象
- Java內部類詳解--區域性內部類Java
- python 詳解類class的繼承、__init__初始化、super方法Python繼承
- HTML中關於class內容空格多類名的問題詳解HTML
- java反射(1) 之class.forName(""), 類名.class, 物件.getClass()區別Java反射物件
- Java面試題之Java類載入機制詳解!Java面試題
- JavaScript class 類JavaScript