Java Class类的用法详解
Class 类和 Java 反射机制有关。
反射应用面很广,大部分类库以及框架底层都用到了反射机制,它是动态语言的关键。
反射是一个比较抽象的概念,不好理解,这里先简单做一个解释,让大家对它有一个基本的认识和概念。反射顾名思义就是反转执行,我们日常生活中的反射有哪些呢?
比如通过照镜子可以反射出你的容貌,水面可以反射出物体的形态,等等。无论是哪种反射,都可以通过一个虚像映射到实物,这样我们就可以获取实物的某些形态特征。
程序中的反射也是同样的道理,它完成的是通过一个实例化对象映射到类,这样我们在程序运行期间就可以获取类的信息了。
看到这里大家可能会有疑问,类的结构都是开发者自定义的,它的信息我完全可以看到啊,为什么还要通过反射来获取呢?注意这里讲的通过反射获取类信息是在程序运行期间,我们可以直接看到的类结构是静态的,而程序运行起来是动态的,两者是不同的两个概念。我们要做的就是在运行期间获取类的结构然后完成某些特定功能。
一句话来简单理解反射:常规情况下是通过类来创建实例化对象的,反射就是将这一过程进行反转,通过实例化对象来获取对应的类信息。
既然是对象,那么就一定有对应的类,这个类就是 Class。所以 Class 这个类你可以把它理解为专门用来描述其他类的类,Class 的每一个实例对象对应的都是其他类的结构特征,定义如图1所示。

图1
在外部不能通过构造函数来实例化 Class 对象,因为 Class 类只有一个私有的构造函数,如图2所示。

图2
我们要如何获取 Class 的实例化对象来描述其他类的结构呢?既然 Class 的实例化对象是描述其他类的,那么在创建 Class 对象时就需要用到被描述的类,创建 Class 实例化对象的方式有3种。

图3
getClass() 方法定义在 Object 类中,被所有类继承,通过实例对象获取内存中该类 class 对象的引用,getClass() 方法的定义如图4所示。

图4
上述3种创建 Class 实例对象的具体操作如代码片段1所示。
代码片段1:

图5
我们可以看到在结果中打印了3次“class java.lang.String”,为什么会是这样的结果呢?
因为在打印某个对象时,会自动调用它的 toString() 方法将该对象转为一个字符串。toString() 是定义在 Object 类中的方法,所有的类都可以继承并进行重写,很显然 Class 类就对 toString() 方法进行了重写,如图6所示。

图6
在上述代码中我们获取了3个 Class 对象,那么这3个 Class 对象是否相等,即在内存中到底是创建了一个 Class 对象还是3个 Class 对象呢?我们通过代码来验证,修改上述代码如代码片段2所示。
代码片段2:

图7
通过结果可以看到3个 Class 对象的散列值相同,同时依次比较 clazz 和 clazz2,clazz2 和 clazz3 的内存地址也相同,证明这3个 Class 对象是相等的,但内存中只有一份。
这一点很好理解,因为 Class 的实例对象是用来描述某个目标类的,而每一个目标类的运行时类在内存中只有一份,所以对应的 Class 对象也只有一份。
声明:《Java系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
反射应用面很广,大部分类库以及框架底层都用到了反射机制,它是动态语言的关键。
反射是一个比较抽象的概念,不好理解,这里先简单做一个解释,让大家对它有一个基本的认识和概念。反射顾名思义就是反转执行,我们日常生活中的反射有哪些呢?
比如通过照镜子可以反射出你的容貌,水面可以反射出物体的形态,等等。无论是哪种反射,都可以通过一个虚像映射到实物,这样我们就可以获取实物的某些形态特征。
程序中的反射也是同样的道理,它完成的是通过一个实例化对象映射到类,这样我们在程序运行期间就可以获取类的信息了。
看到这里大家可能会有疑问,类的结构都是开发者自定义的,它的信息我完全可以看到啊,为什么还要通过反射来获取呢?注意这里讲的通过反射获取类信息是在程序运行期间,我们可以直接看到的类结构是静态的,而程序运行起来是动态的,两者是不同的两个概念。我们要做的就是在运行期间获取类的结构然后完成某些特定功能。
一句话来简单理解反射:常规情况下是通过类来创建实例化对象的,反射就是将这一过程进行反转,通过实例化对象来获取对应的类信息。
Java Class类
Class 类是反射的基础,上面提过反射就是通过对象来获取类的信息。那么问题来了,Java 程序中如何来描述类的信息?或者类的信息应该以一种什么样的形式呈现呢?我们知道 Java 是面向对象的编程语言,Java 世界中的一切都可以看作对象,这里也不例外,可以将通过反射获取的类信息抽象成对象。既然是对象,那么就一定有对应的类,这个类就是 Class。所以 Class 这个类你可以把它理解为专门用来描述其他类的类,Class 的每一个实例对象对应的都是其他类的结构特征,定义如图1所示。

图1
在外部不能通过构造函数来实例化 Class 对象,因为 Class 类只有一个私有的构造函数,如图2所示。

图2
我们要如何获取 Class 的实例化对象来描述其他类的结构呢?既然 Class 的实例化对象是描述其他类的,那么在创建 Class 对象时就需要用到被描述的类,创建 Class 实例化对象的方式有3种。
方式1
调用 Class 的静态方法 forName(String className) 创建,将目标类的全限定类名(全限定类名就是包含所在包信息的类名全称,如 java.lang.String)作为参数传入,即可获取对应的 Class 对象,forName(String className) 方法的定义如图3所示。
图3
方式2
通过目标类的 class 创建,Java 中的每一个类都可以调用类 .class,这里的 class 不是属性,它叫作“类字面量”,其作用是获取内存中目标类型 class 对象的引用。方式3
通过目标类实例化对象的 getClass() 方法创建。getClass() 方法定义在 Object 类中,被所有类继承,通过实例对象获取内存中该类 class 对象的引用,getClass() 方法的定义如图4所示。

图4
上述3种创建 Class 实例对象的具体操作如代码片段1所示。
代码片段1:
public class Test { public static void main(String[] args) { try { Class clazz = Class.forName("java.lang.String"); System.out.println(clazz); } catch (ClassNotFoundException e) { } Class clazz2 = String.class; System.out.println(clazz2); String str = new String("Hello"); Class clazz3 = str.getClass(); System.out.println(clazz3); } }运行结果如图5所示。

图5
我们可以看到在结果中打印了3次“class java.lang.String”,为什么会是这样的结果呢?
因为在打印某个对象时,会自动调用它的 toString() 方法将该对象转为一个字符串。toString() 是定义在 Object 类中的方法,所有的类都可以继承并进行重写,很显然 Class 类就对 toString() 方法进行了重写,如图6所示。

图6
在上述代码中我们获取了3个 Class 对象,那么这3个 Class 对象是否相等,即在内存中到底是创建了一个 Class 对象还是3个 Class 对象呢?我们通过代码来验证,修改上述代码如代码片段2所示。
代码片段2:
public class Test { public static void main(String[] args) { Class clazz = null; try { clazz = Class.forName("java.lang.String"); System.out.println(clazz); } catch (ClassNotFoundException e) { } Class clazz2 = String.class; System.out.println(clazz2); String str = new String("Hello"); Class clazz3 = str.getClass(); System.out.println(clazz3); System.out.println(clazz.hashCode()); System.out.println(clazz2.hashCode()); System.out.println(clazz3.hashCode()); System.out.println(clazz == clazz2); System.out.println(clazz2 == clazz3); } }运行结果如图7所示。

图7
通过结果可以看到3个 Class 对象的散列值相同,同时依次比较 clazz 和 clazz2,clazz2 和 clazz3 的内存地址也相同,证明这3个 Class 对象是相等的,但内存中只有一份。
这一点很好理解,因为 Class 的实例对象是用来描述某个目标类的,而每一个目标类的运行时类在内存中只有一份,所以对应的 Class 对象也只有一份。
声明:《Java系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。