javac 是否预先计算固定表达式?

Does javac precalculate fixed expressions?

是否为此类变量声明提供了优化:

final int secondsInDay = 24 * 60 * 60;

尽管根本没有使用 additional_funct,但 C++ 上的这段代码甚至无法编译:

#include <iostream>

void additional_funct(int num);


void main()
{
    std::cout << "just a text";
}


void additional_funct(int num)
{
    // For both lines will be shown "divide by zero"
    int var = 5 / 0;
    int another_var = num + (2 / 0);
}

这证明 C++ 编译器在 运行ning 之前对数字文字表达式进行了预计算优化。 虽然相同的 Java 代码将简单地开始 运行:

package experimental_main;

public class Experimental_start {
    public static void main(String[] args) {
        // Will throw ArithmeticException "by zero"
        additionalMethod(2);
        System.out.println("just a text");
    }


    static void additionalMethod(int num) {
        int var = 5 / 0;
        int anotherVar = num + (2 / 0);
    }
}

我理解javac没有编译C语言意义的代码。但也许它以其他方式提供优化,或者以这种方式声明此类数字文字更好:

// 24 * 60 * 60
final int secondsInDay = 86_400;

虽然javac没有做任何重大优化,但这样的表达式可以在javac级别进行评估,

如果你反编译表达式 int secondsInDay = 24 * 60 * 60; 你会得到类似

的东西
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=1, locals=2, args_size=1
     0: ldc           #2                  // int 86400
     2: istore_1
     3: return
  LineNumberTable:
    line 7: 0
    line 9: 3

#2驻留在常量池中,

Constant pool:
 ...
#2 = Integer            86400

如您所见,表达式的计算结果为 86400

是的,javac 将预先计算编译时常量。它还将连接编译时常量字符串,例如final String s = "foo" + "bar" 将导致字符串池中的字符串 "foobar",而不是两个字符串 "foo""bar".

您应该始终以可读性编写代码。如果将其写为 24 * 60 * 60 就您所写的内容而言更有意义,请使用它。即使它不是在编译时计算的,我也会以极大的怀疑态度对待任何关于这种重复乘法对代码性能产生有意义影响的说法。

调试您编写 84_600 而不是 86_400 的成本要大几个数量级。

其他答案都是正确的(最后,与 this question 重复)但是有一个重要的方面到目前为止没有提到。

考虑不这样做。

当然,使用原始 int 来存储秒数可能是完全有效的。但是:根据您的上下文以及事物的使用方式……在这里实际使用 OO 建模的力量可能是一个更好的设计。含义:如果你想表达duration的时间;那为什么不使用对象和 类 来表示这些持续时间呢?

我见过很多人们调用方法的错误

someX.waitForGivenNumberOfSeconds()

喜欢

someX.waitForGivenNumberOfSeconds(someValue * 1000)

就因为他们复制+粘贴了;并忽略了他们从一个使用毫秒的地方复制;而不是秒。即使方法命名说 "give me seconds";人通过了 "milli seconds"。或相反亦然。更糟糕的是:通常情况下,唯一可见的指示可能是一些 @param durationInSeconds 附加到要调用的方法的源代码。很容易出错。以后很容易更改,并使所有现有代码变得混乱。

所以,长话短说:先退后一步,然后确定 "OO modeling" 开销是否适合您正在处理的 "overall solution"。