2 u010568859 u010568859 于 2013.09.08 21:29 提问

【求解】关于Class对象何时产生的一些疑惑?

《JAVA编程思想》中说每当编写并且编译了一个新类时,就会产生一个Class对象(被保存在一个同名的.class文件中),程序运行的时候JVM也是先检查类对应的class对象是否被加载,如果未加载,JVM会根据类名查找.class文件,并将其载入。一旦某个类的Class对象载入内存,他就被用来创建这个类的所有对象。有一些网上视频和资料说Class对象就是类编译后的字节码文件(.class文件,不知道Class cls=类名.class ;这种取得Class对象的方式后面的“类名.class”是不是类的字节码文件)。综上所述:也就是说每个类Class对象是在类编译后就产生了的,并且在加载类的时候会把Class对象加载到内存。然而我们学校课本以及图书馆查的书上说:Class对象是在加载类时由JVM或者调用类加载器中的defineClass方法自动构造的。也就是说Class对象是在类加载的时候由java虚拟机创建的。这样我就矛盾了,我有以下一些想请教高手们:
(1)这个Class对象到底是编译类后就产生的(甚至就是所说的字节码文件)还是加载类时产生的?
(2)class LoadedClass{//细节暂时省略}
class Test{
public static void main(String[] args){
Class cls=LoadedClass.class;
}
}
这里面是通过“类名.class”的方式获取类Class对象的。而“类名.class”是和类编译后的字节码文件的全称是一样的,难道这就是视频中说的类的字节码文件就是一个类的Class的对象吗?如果是的话,一个字节码文件能赋值给一个引用类型的变量吗?(不过有的说“class”是一个字面常量,可以通过类调用来获取类的Class对象)。
(3)class LoadedClass{
static{
System.out.println(“类LoadedClass载入”);
}
public LoadedClass(){
System.out.println(“类LoadedClass实例化”);
}
}

class Test{
public static void main(String[] args){
System.out.println(“以下是通过.class的方式取得LoadedClass类的Class对象”);

Class cls=LoadedClass.class;
}
}
运行结果:
以下是通过.class的方式取得LoadedClass类的Class对象

通过“类名.class”方式可以取得Class的对象,由运行结果看出此时静态代码块没有执行,也就是说类并没有加载,那么我们课本上说:Class对象是在加载类时由JVM或者调用类加载器中的defineClass方法自动构造的。此时类并没有加载,按这种说法就说JVM就还没有创建Class对象,但是现在“类名.class”方式取得的Class对象是哪里来的呢。
(4)在Test类中添加:System.out.println(cls);语句,结果打印的是:class LoadedClass;
这个变量cls是引用类型变量,按理说如果是打印其他的对象,一般不是用@连接的类名和对象地址,这里怎么不是呢,是不是重写了Class类的toString()了导致的?

我说的可能有点混乱,但是现在查资料要么是说Class对象在类编译后就产生了,加载类就是要加载Class对象,也就是字节码文件(表明类加载之前就已经有了类的Class对象了,)。要么是说Class对象是在加载类时由JVM或者调用类加载器中的defineClass方法自动构造的(表明Class对象是加载类的时候产生的)。
那么:java.lang.Class类的class对象到底是在编译后生成的(存在.class文件中,或者就是.class文件),还是在JVM加载类时生成的?或者说这两个Class对象之间有什么样的关系?是同一个class对象吗?请高手们能给我解释一下,在此谢谢各位!

1个回答

xiaohui_hubei
xiaohui_hubei   2015.03.25 11:33

(1)编译时就会产生,Class对象可以理解为就是同名的.class文件
(2)参考网上

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!