[英]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.