Java 性能差异:在if-else块或额外的“;否则;?

Java 性能差异:在if-else块或额外的“;否则;?,java,performance,Java,Performance,我很好奇以下哪项更有效:使用默认值初始化变量并仅在if-else块中需要时重写它,或者在没有值的情况下初始化变量并在if-else块中设置值 以下是前者和后者的一个例子: 前任: String weightStatus = "Underweight"; if (bMI > 29.9) { weightStatus = "Obese"; } else if (bMI >= 25.0) {

我很好奇以下哪项更有效:使用默认值初始化变量并仅在if-else块中需要时重写它,或者在没有值的情况下初始化变量并在if-else块中设置值

以下是前者和后者的一个例子:

前任:

    String weightStatus = "Underweight";

    if (bMI > 29.9)
    {
    weightStatus = "Obese";
    }

    else if (bMI >= 25.0)
    {
    weightStatus = "Overweight";
    }
    
    else if (bMI >= 18.5)
    {
    weightStatus = "Healthy Weight";
    }
后者:

    String weightStatus;

    if (bMI > 29.9)
    {
    weightStatus = "Obese";
    }
    
    else if (bMI >= 25.0)
    {
    weightStatus = "Overweight";
    }
    
    else if (bMI >= 18.5)
    {
    weightStatus = "Healthy Weight";
    }
    else
    {
    weightStatus = "Underweight";
    }
    

差异可能很小,但我不禁想知道,根据变量赋值的工作原理,哪一个在技术上更快。

如您所知,前一种情况下,字节码将始终设置变量,然后根据
if/then
,它可能会再次重置变量

但这也取决于在运行时传递哪些值,如果它们大部分不在
然后
分支中,那么我想这不会有太大的区别,但是如果它们经常进入
然后
分支,那么大多数情况下会执行双重设置

您可以使用以下方法进行测试:

public class MyTest {

    private static double START = 0;
    private static double END = 100;
    private static double INCREMENT = 0.0001;

    @Test
    public void testFirst() throws Exception {
        long time = System.nanoTime();
        for (double bMI = START; bMI < END; bMI += INCREMENT) {
            first(bMI);
        }
        System.out.println("First  " + (System.nanoTime() - time));
    }

    @Test
    public void testSecond() throws Exception {
        long time = System.nanoTime();
        for (double bMI = START; bMI < END; bMI += INCREMENT) {
            second(bMI);
        }
        System.out.println("Second " + (System.nanoTime() - time));
    }

    private String first(double bMI) {
        String weightStatus = "Underweight";
        if (bMI > 29.9) {
            weightStatus = "Obese";
        } else if (bMI >= 25.0) {
            weightStatus = "Overweight";
        } else if (bMI >= 18.5) {
            weightStatus = "Healthy Weight";
        }
        return weightStatus;
    }

    private String second(double bMI) {
        String weightStatus;
        if (bMI > 29.9) {
            weightStatus = "Obese";
        } else if (bMI >= 25.0) {
            weightStatus = "Overweight";
        } else if (bMI >= 18.5) {
            weightStatus = "Healthy Weight";
        } else {
            weightStatus = "Underweight";
        }
        return weightStatus;
    }
}
公共类MyTest{
专用静态双启动=0;
专用静态双端=100;
专用静态双增量=0.0001;
@试验
public void testFirst()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第一,体重指数;
}
System.out.println(“First”+(System.nanoTime()-time));
}
@试验
public void testSecond()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第二(bMI);
}
System.out.println(“第二个”+(System.nanoTime()-time));
}
私有字符串优先(双bMI){
字符串weightStatus=“重量不足”;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}
返回状态;
}
私有字符串秒(双bMI){
字符串权重状态;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}否则{
weightStatus=“体重不足”;
}
返回状态;
}
}

如您所知,在前一种情况下,字节码将始终设置变量,然后根据
if/then
,它可能会再次重置变量

但这也取决于在运行时传递哪些值,如果它们大部分不在
然后
分支中,那么我想这不会有太大的区别,但是如果它们经常进入
然后
分支,那么大多数情况下会执行双重设置

您可以使用以下方法进行测试:

public class MyTest {

    private static double START = 0;
    private static double END = 100;
    private static double INCREMENT = 0.0001;

    @Test
    public void testFirst() throws Exception {
        long time = System.nanoTime();
        for (double bMI = START; bMI < END; bMI += INCREMENT) {
            first(bMI);
        }
        System.out.println("First  " + (System.nanoTime() - time));
    }

    @Test
    public void testSecond() throws Exception {
        long time = System.nanoTime();
        for (double bMI = START; bMI < END; bMI += INCREMENT) {
            second(bMI);
        }
        System.out.println("Second " + (System.nanoTime() - time));
    }

    private String first(double bMI) {
        String weightStatus = "Underweight";
        if (bMI > 29.9) {
            weightStatus = "Obese";
        } else if (bMI >= 25.0) {
            weightStatus = "Overweight";
        } else if (bMI >= 18.5) {
            weightStatus = "Healthy Weight";
        }
        return weightStatus;
    }

    private String second(double bMI) {
        String weightStatus;
        if (bMI > 29.9) {
            weightStatus = "Obese";
        } else if (bMI >= 25.0) {
            weightStatus = "Overweight";
        } else if (bMI >= 18.5) {
            weightStatus = "Healthy Weight";
        } else {
            weightStatus = "Underweight";
        }
        return weightStatus;
    }
}
公共类MyTest{
专用静态双启动=0;
专用静态双端=100;
专用静态双增量=0.0001;
@试验
public void testFirst()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第一,体重指数;
}
System.out.println(“First”+(System.nanoTime()-time));
}
@试验
public void testSecond()引发异常{
长时间=System.nanoTime();
对于(双倍体重指数=开始;体重指数<结束;体重指数+=增量){
第二(bMI);
}
System.out.println(“第二个”+(System.nanoTime()-time));
}
私有字符串优先(双bMI){
字符串weightStatus=“重量不足”;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}
返回状态;
}
私有字符串秒(双bMI){
字符串权重状态;
如果(体重指数>29.9){
weightStatus=“肥胖”;
}否则,如果(体重指数>=25.0){
weightStatus=“超重”;
}否则,如果(体重指数>=18.5){
weightStatus=“健康体重”;
}否则{
weightStatus=“体重不足”;
}
返回状态;
}
}

我当然会选择带有默认.Phix的switch语句,但我不是在问switch语句。谢谢你,第一个还有一个任务。当你考虑到优化、预测分支、CPU/内存速度等因素时,你肯定不会注意到其中的差异。无论哪个用户使代码更清晰。@yshavit第一个用户少了一次赋值,多了一次初始化。@Phix你不能用开关来实现不等式。显然,我会选择带有默认值.Phix的开关语句,但我不是问开关语句。谢谢你,第一个还有一个任务。当你考虑到优化、预测分支、CPU/内存速度等因素时,你肯定不会注意到其中的差异。用户(以使代码更清晰的为准)。@yshavit第一个减少了一个赋值,又增加了一个初始化。@Phix您不能使用开关执行不等式。我最初会检查IDE,然后在运行时(服务器)环境中使用实际期望值运行它来测试结果,如果您有输入数据。选择作为答案是因为答案清晰、深入,并提供代码示例。谢谢,这太棒了!这不是一个很好的基准;例如,你没有任何热身。在从性能测试中得出任何结论之前,您应该先阅读如何用Java编写微基准。您可能也想看看jmh。我最初会使用IDE进行检查,但如果您有输入数据,则会在运行时(服务器)环境中使用实际期望值运行它来测试结果。选择作为答案是因为答案清晰、深入,