简体   繁体   English

Java中的静态字段初始化

[英]Static field initialization in Java

I encountered this problem when doing a question on LeetCode: https://leetcode.com/problems/print-in-order/我在 LeetCode 上做题时遇到这个问题: https ://leetcode.com/problems/print-in-order/

Consider two submissions:考虑两个提交:

1. 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. 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();
    }
}

Try submitting these two and you'll find submission 1 will result in Time Limit Exceeded while submission 2 will be accepted.尝试提交这两个,您会发现提交 1 将导致超出时间限制,而提交 2 将被接受。

The only difference is that in submission 2, I explicitly added a statement signal = 0;唯一不同的是,在提交2中,我明确添加了一个语句signal = 0; to initialize the static variable.初始化静态变量。 It should play no difference as I have already given this variable a default value in private static int signal = 0;它应该没有什么区别,因为我已经在private static int signal = 0;给了这个变量一个默认值private static int signal = 0; , so what is going on here. ,所以这里发生了什么。 Is there any subtleties in the static field initialization in Java that I did not know? Java 中的静态字段初始化有什么我不知道的微妙之处吗?

Thank you very much.非常感谢。

LeetCode runs several different test cases against your solution. LeetCode 针对您的解决方案运行多个不同的测试用例。 Let's assume that LeetCode is running a single JVM and running all the test cases in that JVM, but it is instantiating a new Foo for each case.让我们假设 LeetCode 正在运行单个 JVM 并运行该 JVM 中的所有测试用例,但它为每个用例实例化一个新的Foo

When running the first case, signal is zero, and your code works as expected.运行第一种情况时, signal为零,您的代码按预期工作。 But at the end of this test case signal is now 2, because the test case increments it twice.但是在这个测试用例的末尾, signal现在是 2,因为测试用例将它增加了两次。 Since it is static, it is shared among all instances of Foo .由于它是静态的,它在Foo所有实例之间共享。 Even though LeetCode instantiates a new Foo for the second test case, the static signal is still 2. The first method increments it to 3, but then the test hangs because the condition while (signal != 1) is always true.即使 LeetCode 为第二个测试用例实例化了一个新的Foo ,静态signal仍然是 2。第first方法将它增加到 3,但随后测试挂起,因为条件while (signal != 1)始终为真。

Initializing signal to 0 in the Foo constructor has the effect of resetting signal before the second and subsequent test runs.Foo构造函数中将signal初始化为 0 具有在第二次和后续测试运行之前重置signal的效果。

There's no reason to make signal static here.没有理由在这里使signal静态。 It should be a regular non-static member so that each instance of Foo gets a new signal initialized to zero.它应该是一个常规的非静态成员,以便Foo每个实例都获得一个初始化为零的新signal

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM