getClass()和forName()都是用来获取Class对象引用的函数,他们返回同一个Class对象的引用。不同的是getClass()函数是Object对象的方法,如使用此函数,需要一个对象的引用来调用此方法。forName()函数是Class类中的一个静态方法,参数是全限定名(包名+类名),会抛出ClassNotFoundException异常,因此调用此函数,需要处理或声明抛出该异常。
用一段代码来演示上方讲解的两个函数的相同点和不同点。
package cn.zh.rtti;
public class CompareMethod {
public static void main(String[] args) {
// getClass()需要获取Class对象对应的对象的引用。是根类Objecct的函数
CompareMethod compareMethod = new CompareMethod();
Class c1 = compareMethod.getClass();
Class c2 = null;
try {
// forName()是Class类的static方法,参数是全限定名,会抛出ClassNotFoundException异常
c2 = Class.forName("cn.zh.rtti.CompareMethod");
} catch (ClassNotFoundException e) {
System.out.println("not find class");
System.exit(1);
}
// getName()函数是Class类中的一个static方法,返回该Class对象的全限定名字符串
System.out.println("I'm c1--------- name of class: " + c1.getName());
System.out.println("I'm c2--------- name of class: " + c2.getName());
// 通过.equals()函数得出c1和c2两个对象的内容是相同的
// == 来比较c1和c2的地址,相同,由此得出getName()和forName()函数返回的是同一个Class对象的引用
System.out.println("compared content between c1 and c2: " + c1.equals(c2));
System.out.println("compared address between c1 and c2: " + (c1 == c2));
}
}
为什么返回同一个Class对象的引用呢?
所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员引用时,首先,JVM将使用类加载器检查这个类的Class对象是否已经加载,如果尚未加载,类加载器就会根据类名查找.class文件,加载这个字节码文件并生成Class对象,注意:所有的Class对象只生成一次,那就是JVM第一次调用静态成员时。
Java中构造函数也是一个static方法,只不过用来修饰构造器的static关键字被隐藏了,也就是说通过new关键字创建对象相当于调用了静态方法,也就会加载该对象的.class文件,并生成Class对象。forName()也是一个静态方法。所以,无论getClass()和forName谁先被调用,还是调用几次,得到的都是同一个Class对象的引用。