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