天天看點

java中的Class對象、new關鍵字

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) {
			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

------------------------------------ 介  紹------------------------------------------------ 

java.lang.Class

Java程式在運作時,Java運作時系統一直對所有的對象進行所謂的運作時類型辨別。這項資訊紀錄了每個對象所屬的類。虛拟機通常使用運作時類型資訊選準正确方法去執行,用來儲存這些類型資訊的類是Class類。Class類封裝一個對象和接口運作時的狀态,當裝載類時,Class類型的對象自動建立。

Class 沒有公共構造方法。Class 對象是在加載類時由 Java 虛拟機以及通過調用類加載器中的 defineClass 方法自動構造的,是以不能顯式地聲明一個Class對象。

虛拟機為每種類型管理一個獨一無二的Class對象。也就是說,每個類(型)都有一個Class對象。運作程式時,Java虛拟機(JVM)首先檢查是否所要加載的類對應的Class對象是否已經加載。如果沒有加載,JVM就會根據類名查找.class檔案,并将其Class對象載入。

基本的 Java 類型(boolean、byte、char、short、int、long、float 和 double)和關鍵字 void 也都對應一個 Class 對象。

每個數組屬于被映射為 Class 對象的一個類,所有具有相同元素類型和維數的數組都共享該 Class 對象。

一般某個類的Class對象被載入記憶體,它就用來建立這個類的所有對象。

Class.forName與new

Class.forName(xxx.xx.xx) 傳回的是一個類

首先你要明白在java裡面任何class都要裝載在虛拟機上才能運作。這句話就是裝載類用的(和new 不一樣,要厘清楚)。 

至于什麼時候用,你可以考慮一下這個問題,給你一個字元串變量,它代表一個類的包名和類名,你怎麼執行個體化它?隻有你提到的這個方法了,不過要再加一點。 

A a = (A)Class.forName("pacage.A").newInstance(); 

這和你 

A a = new A(); 

是一樣的效果。 

jvm會執行靜态代碼段,靜态代碼是和class綁定的,class裝載成功就表示執行了你的靜态代碼了。而且以後不會再走這段靜态代碼了。

Class.forName(xxx.xx.xx) 傳回的是一個類 

Class.forName(xxx.xx.xx);的作用是要求JVM查找并加載指定的類,也就是說JVM會執行該類的靜态代碼段

動态加載和建立Class 對象,比如想根據使用者輸入的字元串來建立對象 

String str = 使用者輸入的字元串 

Class t = Class.forName(str); 

t.newInstance();

 在初始化一個類,生成一個執行個體的時候,newInstance()方法和new關鍵字除了一個是方法,一個是關鍵字外,最主要有什麼差別?它們的差別在于建立對象的方式不一樣,前者是使用類加載機制,後者是建立一個新類。那麼為什麼會有兩種建立對象方式?這主要考慮到軟體的可伸縮、可擴充和可重用等軟體設計思想。 

Java中工廠模式經常使用newInstance()方法來建立對象,是以從為什麼要使用工廠模式上可以找到具體答案。 例如: 

class c = Class.forName(“Example”); 

factory = (ExampleInterface)c.newInstance(); 

其中ExampleInterface是Example的接口,可以寫成如下形式: 

String className = "Example"; 

class c = Class.forName(className); 

factory = (ExampleInterface)c.newInstance(); 

進一步可以寫成如下形式: 

String className = readfromXMlConfig;//從xml 配置檔案中獲得字元串 

class c = Class.forName(className); 

factory = (ExampleInterface)c.newInstance(); 

上面代碼已經不存在Example的類名稱,它的優點是,無論Example類怎麼變化,上述代碼不變,甚至可以更換Example的兄弟類Example2 , Example3 , Example4……,隻要他們繼承ExampleInterface就可以。 

從JVM的角度看,我們使用關鍵字new建立一個類的時候,這個類可以沒有被加載。但是使用newInstance()方法的時候,就必須保證:1、這個類已經加載;2、這個類已經連接配接了。而完成上面兩個步驟的正是Class的靜态方法forName()所完成的,這個靜态方法調用了啟動類加載器,即加載java API的那個加載器。 

現在可以看出,newInstance()實際上是把new這個方式分解為兩步,即首先調用Class加載方法加載某個類,然後執行個體化。 這樣分步的好處是顯而易見的。我們可以在調用class的靜态加載方法forName時獲得更好的靈活性,提供給了一種降耦的手段。 

最後用最簡單的描述來區分new關鍵字和newInstance()方法的差別: 

newInstance: 弱類型。低效率。隻能調用無參構造。 

new: 強類型。相對高效。能調用任何public構造。

.class與getClass()

.class其實是在java運作時就加載進去的

getClass()是運作程式時動态加載的

public class ExtendClass extends Baseclass {
	private String width;
	public String getWidth() {
		return width;
	}
	public void setWidth(String width) {
		this.width = width;
	}
	public static void main(String[] arg0) {
		Baseclass baseclass1 = new ExtendClass();
		Baseclass baseclass2 = new Baseclass();
		System.out.println(baseclass1.getClass().getSimpleName());// 實際運作的是繼承類Extendclass
		System.out.println(baseclass2.getClass().getSimpleName());// 實際運作的是Baseclass
		System.out.println(Baseclass.class.getSimpleName());// 加載時類名
		System.out.println(ExtendClass.class.getSimpleName());// 加載時類名
	}
}
class Baseclass {
	private String height;
	public String getHeight() {
		return height;
	}
	public void setHeight(String height) {
		this.height = height;
	}
}
           

 執行結果為:

ExtendClass

Baseclass

Baseclass

ExtendClass