java - Java中的静态字段初始化

标签 java

我在LeetCode上做题时遇到了这个问题:https://leetcode.com/problems/print-in-order/

考虑两个提交:

1.

class Foo {
    private static int signal = 0;
    public Foo() {}

    public synchronized void first(Runnable printFirst) throws InterruptedException {
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        signal += 1;
        notifyAll();
    }

    public synchronized void second(Runnable printSecond) throws InterruptedException {
        while(signal != 1)
            wait();

        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        signal += 1;
        notifyAll();
    }

    public synchronized void third(Runnable printThird) throws InterruptedException {
        while(signal != 2)
            wait();

        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
        notifyAll();
    }
}

2.

class Foo {
    private static int signal = 0;
    public Foo() {signal = 0;}

    public synchronized void first(Runnable printFirst) throws InterruptedException {
        // printFirst.run() outputs "first". Do not change or remove this line.
        printFirst.run();
        signal += 1;
        notifyAll();
    }

    public synchronized void second(Runnable printSecond) throws InterruptedException {
        while(signal != 1)
            wait();

        // printSecond.run() outputs "second". Do not change or remove this line.
        printSecond.run();
        signal += 1;
        notifyAll();
    }

    public synchronized void third(Runnable printThird) throws InterruptedException {
        while(signal != 2)
            wait();

        // printThird.run() outputs "third". Do not change or remove this line.
        printThird.run();
        notifyAll();
    }
}

尝试提交这两项,您会发现提交 1 将导致超出时间限制,而提交 2 将被接受。

唯一的区别是,在提交2中,我显式添加了一条语句signal = 0;来初始化静态变量。它应该没有什么区别,因为我已经在 private static int signal = 0; 中给了这个变量一个默认值,所以这里发生了什么。 Java中的静态字段初始化有什么我不知道的微妙之处吗?

非常感谢。

最佳答案

LeetCode 针对您的解决方案运行多个不同的测试用例。我们假设 LeetCode 运行单个 JVM 并运行该 JVM 中的所有测试用例,但它为每个用例实例化一个新的 Foo

运行第一个案例时,signal 为零,并且您的代码按预期工作。但在此测试用例结束时,signal 现在为 2,因为测试用例将其递增了两次。由于它是静态的,因此它在 Foo 的所有实例之间共享。即使 LeetCode 为第二个测试用例实例化了一个新的 Foo,静态 signal 仍然是 2。first 方法将其增加到 3,但是然后测试挂起,因为条件 while (signal != 1) 始终为 true。

Foo 构造函数中将 signal 初始化为 0 可以在第二次及后续测试运行之前重置 signal

没有理由将 signal 设为静态。它应该是一个常规的非静态成员,以便 Foo 的每个实例都会获得一个初始化为零的新signal

关于java - Java中的静态字段初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59698370/

相关文章:

java - 无法使用 IPV6 地址向端点发送 SIP 通知

java - 什么是NullPointerException,我该如何解决?

java - 在 Java 中获取 nanos unix 纪元时间的最快方法

java - Android:固定位置工具栏

java - 关于try-catch的问题

java - 在 JBoss 7 上使用 Maven 成功部署,但 Web 应用程序未运行

java - PS Old Gen 已满,我的应用程序变慢了

java - Slick 3 java.time.LocalDate 映射

java - 如何使用 clone() 方法克隆 Java 对象

java - 在Java中读取二进制文件的特定部分