【问题标题】:Is it true that java.lang.Class object is created when the Java class is loaded, even before instantiation takes place?java.lang.Class 对象是在加载 Java 类时创建的,甚至在实例化发生之前,是真的吗?
【发布时间】:2012-02-24 14:25:08
【问题描述】:

假设类有这样的代码:

class C {
    public static void show() {
    }
}

class CTest {
    public static void main (String[] args) {
        C.show();
    }
}

那么,在引用类C来访问这里的静态方法show()时,是否可以完全合法地得出结论,Java实际上是通过Java反射调用show()方法?

即它实际上是在做这样的事情吗

Class test = Class.forName(C);
test.show();

调用静态方法?

如果不是,那它实际上是如何在不创建对象的情况下调用静态方法的?

如果上述解释属实,那么当我们实际通过java.lang.Class 对象调用方法时,我们将如何证明“静态成员仅与类关联,而不与对象关联”的说法?

【问题讨论】:

    标签: java reflection static jvm instantiation


    【解决方案1】:
    1. JVM 在调用静态方法时不需要像Class.forName() 那样做任何事情,因为当调用该方法的类被初始化时(或者当方法运行第一次,取决于静态方法调用的位置),查找那些其他类,并将对静态方法代码的引用安装到与该调用类关联的数据池中。但是在初始化过程中的某个时刻,是的,会执行 Class.forName() 的等效操作来查找其他类。

    2. 这是一个似是而非的语义论点。您可以轻松地说,这强化了静态方法与 相关联而不是类的任何实例的标准线。

    【讨论】:

    • 欢迎您添加自己的答案,或提出改进此问题的建议。
    • 我明白您在第 1 点中所说的内容,但有点难以理解。第2点是正确的。 +1。
    • 恕我直言,这有点误导。被调用的类将在调用代码第一次引用时被加载。当调用类被初始化或方法运行时并不是真的。这些暗示(对我而言)被调用的类已加载,因为它在调用类或方法中的某处被引用。 JVM 只在它首先需要的特定代码行解析和加载类。
    【解决方案2】:

    JVM 将它可以使用的内存分成不同的部分:一部分用于存储类,另一部分用于对象。 (我认为可能有第三部分,但我现在不太确定)。

    无论如何,当一个对象被创建时,java 会查找相应的类(就像一个蓝图)并创建它的副本 -> 瞧,我们就有了一个对象。当调用静态方法时,执行的是内存第一部分的类的方法,而不是第二部分的对象的方法。 (因此不需要实例化对象)。

    此外,反射需要大量资源,因此使用它来调用静态方法会极大地影响性能。

    【讨论】:

      【解决方案3】:

      更多信息:

      被调用的类将在调用代码第一次引用时被加载。 即 JVM 只在它首先需要的特定代码行解析和加载类。 您可以通过使用 JVM 参数“-verbose:class”并使用调试器单步执行来验证这一点。

      它会调用 ClassLoader.loadClass(String name) 来加载类。

      【讨论】:

        【解决方案4】:

        你可以在ctor里面放一个println语句,来验证它是否被调用:

        class C {
            public static void show () {
                System.out.println ("static: C.show ();");
            }
        
            public C () {
                System.out.println ("C.ctor ();");
            }
        
            public void view () {
                System.out.println ("c.view ();");
            }
        
        }
        
        public class CTest
        {
            public static void main (String args[])
            {
                System.out.println ("static: ");
                    C.show ();
                System.out.println ("object: ");
                    C c = new C ();
                    c.view ();
                    c.show (); // bad style, should be avoided
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2010-09-11
          • 2014-04-17
          • 2021-04-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多