假设类具有如下代码:
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
对象调用方法时,我们如何证明“静态成员只与类相关联,而不是对象”的语句?
答案 0 :(得分:3)
在调用静态方法时,JVM不需要执行Class.forName()
之类的任何操作,因为当调用方法的类被初始化时(或者当方法时)第一次运行,具体取决于静态方法调用的位置),查找其他类,并将静态方法代码的引用安装到与该调用类关联的数据池中。但是在初始化期间的某个时刻,是的,执行Class.forName()
相当于找到另一个类。
这是一个似是而非的语义论证。您可以很容易地说,这加强了静态方法与类相关联的标准行,而不是类的任何实例。
答案 1 :(得分:1)
JVM将可以使用的内存划分为不同的部分:存储类的一部分和对象的一部分。 (我想可能有第三部分,但我现在不太确定)。
无论如何,当创建一个对象时,java会查找相应的类(如蓝图)并创建它的副本 - >瞧,我们有一个对象。当调用静态方法时,执行内存的第一部分中的类的方法,而不执行第二部分中的对象的方法。 (因此不需要实例化对象)。
此外,反射需要大量资源,因此使用它来调用静态方法会对性能产生很大影响。
答案 2 :(得分:1)
了解更多信息:
当调用代码首次引用时,被调用的类将被加载。 即JVM只解析并在最初需要它的特定代码行加载该类。 您可以使用JVM arg“-verbose:class”并使用调试器逐步验证这一点。
它将调用ClassLoader.loadClass(String name)来加载类。
答案 3 :(得分:1)
您可以将println语句放入ctor,以验证它是否被调用:
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
}
}