【问题标题】:".class" way of obtaining Class - does it initialize the class?“.class”获取类的方式——它会初始化类吗?
【发布时间】:2012-12-06 08:35:38
【问题描述】:

问题是关于 Java。获取类型的类有3种方式(注意,代码只是sn-ps的集合,用于演示):

Class c1 = Class.forName("com.mypkg.MyClass"); //assumes initialize = true
// - OR - 
Class c1 = Class.forName("com.mypkg.MyClass", true/false,
                         this.getClass().getClassLoader());

Class c2 = com.mypkg.MyClass.class;
// - OR - 
import com.mypkg.MyClass;
Class c2 = MyClass.class;

MyClass mc = new MyClass();
Class c3 = mc.getClass();

我的问题是关于初始化的。对于方法 1,我可以使用布尔参数控制类是否被初始化。对于方法3,既然创建了一个对象,那么显然这个类已经被初始化了(对吧?)。

但是方法 2 呢?如果类尚未初始化,调用 .class 是否会对其进行初始化?
并且如何以编程方式检查是否存在类是否已经初始化?

总结答案:

请参阅已接受的解决方案及其 cmets 以获得完整答案。这只是一个摘要。

调用.class 不会初始化尚未初始化的类。您可以通过在打印消息的类定义中使用静态块来检查类是否正在初始化。

原始问题的原因:

根据Class.forName 的javadoc,“对forName("X") 的调用会导致初始化名为X 的类。”。还有两种Class.forName 方法,其中一种接受名为initialize 的布尔参数。根据javadoc,“只有当initialize参数为真并且之前没有被初始化时,该类才会被初始化。”

【问题讨论】:

  • 加载时初始化?
  • c1, c2, c3 是 Class 类型的对象,而不是初始化的类
  • @ivanovic 当我检查 Class.forName 的 javadoc 时,它说 “调用 forName("X") 会导致初始化名为 X 的类。”。还有两个 Class.forName 方法,一个接受布尔参数。根据javadoc,“只有当initialize参数为true并且之前没有初始化过时,才会初始化类。”..如果你说类没有初始化,这里的初始化是什么意思?顺便说一句,我使用的是 JVM 1.6。
  • @ice 我知道。问题是.class 是否会导致类初始化,就像Class.forName 会一样。
  • @ivanovic 如果您费心阅读 java 文档中的 Class.forName,它会谈到“初始化”。类被初始化,这大概是指初始化static变量并执行static代码块。

标签: java class


【解决方案1】:

自己测试一下,看看你的虚拟机做了什么?

只需将这个类与所有三个方法一起使用(在独立运行中,因为它最多只会初始化一次!)

class Example {
    static {
        System.out.println("Class was initialized!");
    }

    public static int bananas = 0;
}

详情何时一个类应该被初始化,见http://docs.oracle.com/javase/specs/#12.4.1

粗略地说,一个类应该在以下任一情况下被初始化

  • 第一个实例已创建
  • 调用了static 方法
  • 使用了非最终的static 字段
  • 一些更复杂的极端案例

所以本质上,当你第一次使用实际类的任何东西时,不仅仅是引用它。

但是例如Example.bananas = 1; 也应该触发类初始化,而不需要实例。

【讨论】:

  • 啊,你回答了我的第二个问题:)好吧,有点:D
  • 我用你的方法做了一个测试,结果是,当我做MyClass.class 来获取Class对象时,这个类是NOT初始化的。它在我随后执行c2.newInstance() 时被初始化(假设它之前从未初始化过)。非常感谢!
【解决方案2】:

在字节码级别,对类的引用由ldc instructions 之一加载。 VM 规范没有提到类已初始化,所以可以肯定地说 VM 不保证这样的引用会初始化类,但请注意 VM 规范没有也需要 VM 尽可能延迟地进行初始化。

类可以在首次引用和严格要求初始化之间的任何时间合法地初始化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多