Java 在单线程程序中执行两次代码块

Java 在单线程程序中执行两次代码块,java,Java,在我下面的程序中,我观察到score变量的值是预期值的两倍(999000而不是499500)。仔细观察它表明,即使在第一次调用后,标志被设置为true,计算也会进行两次。知道这里出了什么问题吗?该程序是单线程的。实际计算涉及调用RESTAPI,但出于测试目的,我已将其删除 public class DataClient { public static void main(String[] args) { System.out.println(CalculationCache.getS

在我下面的程序中,我观察到
score
变量的值是预期值的两倍(999000而不是499500)。仔细观察它表明,即使在第一次调用后,
标志
被设置为true,计算也会进行两次。知道这里出了什么问题吗?该程序是单线程的。实际计算涉及调用RESTAPI,但出于测试目的,我已将其删除

public class DataClient {

public static void main(String[] args) {

    System.out.println(CalculationCache.getScore());
  }
}
class CalculationCache{

static{

    computeScore();
}

private static int score;

public static int getScore() {

    computeScore();
    return score;
}

private static boolean flag=false;

static void computeScore(){

    if(!flag) {
        //calculate the score
        for (int i = 0; i < 1000; i++) {
            score = score + i;
            flag = true;
        }
    }

 }
}
公共类数据客户端{
公共静态void main(字符串[]args){
System.out.println(CalculationCache.getScore());
}
}
类计算缓存{
静止的{
computeScore();
}
私人静态智力得分;
公共静态int getScore(){
computeScore();
返回分数;
}
私有静态布尔标志=false;
静态void computeScore(){
如果(!标志){
//计算分数
对于(int i=0;i<1000;i++){
分数=分数+i;
flag=true;
}
}
}
}

该问题是由于类初始化的顺序造成的。静态初始值设定项按其定义的顺序执行。变量
标志
仅在调用
computeScore()
后初始化。因此,当第二次调用该方法时,
flag
将为
false
。您可能想要摆脱静态块

static{
    computeScore();
}

如果您想要延迟初始化

这似乎是一个直接查看Java编译器生成的字节码可能非常有用的问题。@HovercraftFullOfEels为什么?关于初始化和静态块的简单规则就足够了。@Jean BaptisteYunès:如果只是在操作中查看这些规则,那么变量标志只有在调用computeScore()之后才初始化,这是不正确的,因为它会破坏java关于初始化的规则。第一次调用computeScore时,实际上标志默认初始化为false,然后在第二次调用时静态初始化为false。@chattambigeek Upvote/如果您认为有帮助,请接受答案。