当使用静态方法时,类是否会被实例化?

6

假设我有一个静态方法increment:

public class StaticTest {
    private static int no = 0;

    public static void increment()
    {
        no++;
    }
}

当我使用StaticTest.increment()语法调用increment方法时,该类是否被实例化?如果堆上不存在该类型的对象怎么办?

3
“那种类型的类”这个短语让我觉得你对类的一些基本概念存在误解。 - user253751
3个回答

6
当我使用StaticTest.increment()语法调用增量时,类是否会被实例化?
本身,这个类会被加载(由类加载器),如果它还没有被加载的话。 如果它已经被加载,那么就不会再次加载。没有创建该类的实例(该类类型的对象),因为您尚未创建任何实例。
假设所有调用StaticTest.increment()的代码都使用相同的类加载器(这通常是情况),那么调用该静态方法的多少不重要,只使用该类的单个副本。他们共享它。例如:
// Some bit of code somewhere
StaticTest.increment();

// Another bit of code somewhere else
StaticTest.increment();

// A third bit of code in yet another place
StaticTest.increment();

所有这些都运行完毕后,StaticTest 类中的 no 静态变量将具有值 3

如果堆上不存在该类型的类会怎样呢?

那么类加载器将加载它。


将上述代码与以下代码进行对比(没有 static 变量):

public class NonStaticTest {
    private int no = 0;

    public void increment()
    {
        no++;
    }

    public int getNo() // So we can see the results
    {
        return no;
    }
}

现在我们不能这样做:

NonStaticTest.increment(); // WRONG, fails with error saying `increment` is not static

我们改为这样做:
NonStaticTest instance = new NonStaticTest();
instance.increment();
System.out.println(instance.getNo()); // "1"

当代码第一次这样做时,classloader将加载NonStaticTest类。然后,new NonStaticTest()表达式创建了一个该类的实例,它具有no成员。当代码第二次这样做时,NonStaticTest已经被加载,因此不会再次加载。然后,new NonStaticTest()表达式创建了该类的第二个实例。
如果我们有三个以上的代码执行上述操作,则每个代码都会看到“1”,因为no是特定于类的实例而不是附加到类本身的。

1
谢谢,这正是我在寻找的。 - james_dean

2
您必须清楚区分两个概念:
- 类(classes),它们是一种“自定义类型”(这里我简化了) - 对象(objects),它们是这些类的实例
类只会被类加载器加载一次,而类的对象每次调用new ClassName()(如果类名为ClassName)时都会创建。
现在,回到您的问题:使用static关键字使您的声明独立于类的任何实例(对象)。
因此,当您使用StaticTest.increment()时,不会创建类StaticTest的任何对象(也不需要创建对象)。

1

你可以通过使用new StaticTest来实例化一个对象,除非你已经创建了这样的对象,否则你还没有创建实例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接