深入研究java.lang.Class

Class的作用

  Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。

Class的特点

  1. Class没有公共构造方法。Class对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass方法自动构造的,因此不能显式地声明一个Class对象。
  2. 虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
  3. 基本的Java类型(boolean、byte、char、short、int、long、float 和 double)和关键字void 也都对应一个。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。

获得Class对象的三种方法

  1. 调用Object类的getClass()方法了获得Class对象,这也是最常见的产生Class对象的方法。例如:
Date date1 = new Date();
Date date2 = new Date();
Class c1 = date1.getClass();
Class c2 = date2.getClass();
System.out.println( c1.getName() );  // java.util.Date
System.out.println( c1==c2 );        // true

  需要注意的是,代码中的date1和date2的getClass方法返回了相同的Class对象(c1==c2的值为true)。这是因为,对于相同的类,JVM只会载入一次,而与该类对应的Class对象也只会存在一个,无论该类实例化了多少对象

Set set = new HashSet();
Iterator it = set.iterator();
System.out.println(it.getClass().getName());  // java.util.HashMap$KeyIterator

  从代码可以看出,HashSet的iterator方法返回的是实现了Iterator接口的HashMap内部类(KeyIterator)对象。

  1. 使用Class对象中静态方法forName()方法,获得与字符串对应的Class对象。例如:
      该方法可以根据字符串参数所指定的类名获取与该类关联的Class对象。如果该类还没有被装入,该方法会将该类装入JVM。
      该方法声明抛出ClassNotFoundException异常。顾名思义,当该方法无法获取需要装入的类时(例如,在当前类路径中不存在这个类),就会抛出这个异常。
    例如,如果当前类路径中存在Foo类:
package reflection;

public class Foo {

	public Foo() {
		System.out.println("Foo()");
	}
    static{
    	System.out.println("Foo is initialized");
    }
}

运行以下代码:

Class cl = Class.forName("reflection.Foo");

控制台输出如下:

Foo is initialized

Class.forName("reflect.Foo")首先会将reflection.Foo类装入JVM,并返回与之关联的Class对象。JVM装入Foo类后对其进行初始化,调用了其static块中的代码。需要注意的是:forName方法的参数是类的完整限定名(即包含包名)。

  1. 获取Class类型对象的第三种方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配类对象。
Class cl1 = Manager.class;
Class cl2 = int.class;
Class cl3 = Double[].class;

  这个方法可以直接获得与指定类关联的Class对象,而并不需要有该类的对象存在。

Class类的常用方法

  1. getName()
      一个Class对象描述了一个特定类的属性,Class类中最常见的方法。getName()以String的形式返回此类的实体()类、接口、数组类、基本类型或void)名称。
  2. newInstance()
      Class还有一个有用的方法,可以为类创建一个实例,这个方法叫newInstance()。例如:x.getClass().newInstance(),创建了一个通x一样类型的的新实例。 newInstance()方法调用的默认构造器初始化新建对象。(要求类有默认构造函数)
  3. getClassLoader()
    返回该类的加载器
  4. getComponentType()
    返回表示数组组件类型的Class
  5. getSuperclass()
    返回表示此Class所表示的实体(类、接口、基本类型或void)的超类的Class。
  6. isArray()
    判定此Class对象是否表示一个数组类;

Class的一些使用技巧

  1. forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象。例如
Object obj = Class.forName(s).newInstance();
  1. 虚拟机为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。例如:
if( e.getClass() == Employee.class)
...

参考博客:
http://blog.sina.com.cn/s/blog_6c7702a30100m9yq.html
http://lavasoft.blog.51cto.com/62575/15433/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值