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

时间:2016-05-17 12:44:20

标签: java javac

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

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 ++编译器在运行之前对数字文字表达式进行了优化,以预先计算它们。 虽然相同的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;

3 个答案:

答案 0 :(得分:5)

虽然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

答案 1 :(得分:4)

是的,final String s = "foo" + "bar"将预编译编译时常量。它还将连接编译时常量字符串,例如, "foobar"会在字符串池中生成字符串"foo",而不是两个字符串"bar"24 * 60 * 60

您应该始终编写代码以便于阅读。如果将其写为84_600对于您正在编写的内容更有意义,请使用它。即使它不是在编译时计算出来的,我也会认为这种重复乘法对你的代码的性能产生了有意义的影响而非常怀疑。

调试您编写86_400而不是/boot这一事实的成本要高出几个数量级。

答案 2 :(得分:1)

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

考虑不要这样做。

当然,使用原始int存储几秒钟可能完全有效。但是:取决于你的背景,以及如何使用它......在这里实际使用OO建模的力量可能是一个更好的设计。含义:如果你想表达持续时间的时间;那么为什么不使用对象和类来表示那些持续时间呢?

我看到很多人在调用方法的错误

someX.waitForGivenNumberOfSeconds()

someX.waitForGivenNumberOfSeconds(someValue * 1000)

只是因为他们复制+粘贴;并忽略了他们从一个使用毫秒的地方复制;而不是秒。即使用方法命名说“给我秒”;人们通过了“毫秒”。或相反亦然。更糟糕的是:很多时候,唯一可见的指示可能是要调用的方法的源代码附加了一些@param durationInSeconds。很容易出错。以后很容易更改,并将所有现有代码渲染成混乱。

所以,长话短说:只需退一步,然后确定“OO建模”开销是否适合您正在使用的“整体解决方案”。