ITEEDU

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