From Gossip@Openhome

Java Gossip: 簡介 Class

一個Class物件代表了Java應用程式在運行時所載入的類別或介面,也用來表達enum(屬於類別的一種)、 annotation(屬於介面的一種)、陣列、原生型態(primitive type)、void。

Class沒有公開(public)的建構函式,Class物件是由JVM自動產生,每當一個類別被載入時,JVM就自動為其生成一個Class物件。

您可以透過Object的getClass()來取得每一個物件對應的Class物件,或者是透過class常量(Class literal),下面這個程式簡單的使用getClass()方法來取得String類別的一些基本資訊:

  • ClassDemo.java
package onlyfun.caterpillar;

public class ClassDemo {
public static void main(String[] args) {
String name = "caterpillar";
Class stringClass = name.getClass();
System.out.println("getName: " +
stringClass.getName());
System.out.println("isInterface: " +
stringClass.isInterface());
System.out.println("isPrimitive: " +
stringClass.isPrimitive());
System.out.println("isArray: " +
stringClass.isArray());
System.out.println("SuperClass: " +
stringClass.getSuperclass().getName());
}
}

執行結果:
getName: java.lang.String
isInterface: false
isPrimitive: false
isArray: false
SuperClass: java.lang.Object


您也可以直接使用以下的方式來取得String類別的Class物件:
Class stringClass = String.class;
 
在Java中,陣列也屬於一個類別,也有對應的Class物件,這個 物件是由所有具相同元素與維度的陣列所共用,而原生型態像是boolean, byte, char, short, int, long, float, double以及關鍵字void,也都有對應的Class物件,您也都可以用類別常量(Class literal)來取得這些物件,例如:
  • ClassDemo.java
public class ClassDemo { 
public static void main(String[] args) {
System.out.println(boolean.class.getName());
System.out.println(boolean.class.isPrimitive());
System.out.println(void.class.getName());
}
}

執行結果:
boolean
true
void 


在一些應用中,您無法事先知道使用者將載入什麼類別,您可以使用Class的forName()方法實現動態加載類別,下面這個例子讓您可以指定類別名稱 來獲得類別的相關資訊:
  • ClassDemo.java
package onlyfun.caterpillar;

public class ClassDemo {
public static void main(String[] args) {
try {
Class c = Class.forName(args[0]);
System.out.println("getName: " +
c.getName());
System.out.println("isInterface: " +
c.isInterface());
System.out.println("isPrimitive: " +
c.isPrimitive());
System.out.println("isArray: " + c.isArray());
System.out.println("SuperClass: " +
c.getSuperclass().getName());
}
catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
}

執行結果:
java ClassDemo java.util.ArrayList
getName: java.util.ArrayList
isInterface: false
isPrimitive: false
isArray: false
SuperClass: java.util.AbstractList


Class物件的訊息是在編譯時期就被加入至.class檔案中,它是Java支援執行時期型別辨識(RTTI,Run- Time Type Information或Run-Time Type Identification)的一種方式,在編譯時期編譯器會先檢查對應的.class檔案,而執行時期JVM在沒有用到該類別時,就不會載入它,如果 要用到時,JVM會先檢查對應的Class物件是否已經載入,如果沒有載入,則會尋找對應的.class檔案並載入它。

您可以使用Class.forName()方法動態加載類別,之後使用Class的newInstance()方法產生實例,下面這個程式是個簡單的示 範,您可以動態載入實現List的類別

  • ClassDemo.java
package onlyfun.caterpillar;

import java.util.*;

public class ClassDemo {
public static void main(String[] args) {
try {
Class c = Class.forName(args[0]);
List list = (List) c.newInstance();

for(int i = 0; i < 10; i++) {
list.add("element " + i);
}

for(Object o: list.toArray()) {
System.out.println(o);
}
}
catch(ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}

執行結果:
java ClassDemo java.util.ArrayList
element 0
element 1
element 2
element 3
element 4
element 5
element 6
element 7
element 8
element 9