文字的算术运算是在编译时还是运行时计算的?
我有以下内容:
double timeInMinutes = (double) timeInMilliseconds / (1000 * 60);
操作(1000 * 60)
是在编译时还是在运行时完成的? 换句话说,在上面的代码片段和运行时间之间是否存在性能差异:
double timeInMinutes = (double) timeInMilliseconds / 60000;
编辑:我的问题不同于Java编译器是否会预先计算文字的总和? 因为我在算术运算中混合使用变量和文字。 这是一个很小的区别,但正如@TagirValeev在评论中指出的那样( 在编译时或运行时计算文字的算术运算? ),有些文字虽然可以预先编译,但是没有预编译。
根据JLS§15.2 – 表达forms
某些表达式具有可在编译时确定的值。 这些是常量表达式(§15.28)。
像*, /, and %
这样的乘法运算符属于常量表达式,因此它将在编译时确定。
@SergeyMorozov写得比我快,并且得到字节码certificate( #2 = Integer 60000
),但这里是实际证据,上面是理论/官方声明:
尝试使用1000 * 60
和60000
生成字节代码,您将看到相同的字节代码指令,因此运行时性能相同。
Java类:
public class Test { public static void main(String[] args) { int compileTest = 1000 * 60; } }
字节代码:
Classfile /E:/Test.class Last modified Oct 9, 2015; size 265 bytes MD5 checksum fd115be769ec6ef7995e4c84f7597d67 Compiled from "Test.java" public class Test SourceFile: "Test.java" minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #4.#13 // java/lang/Object."":()V #2 = Integer 60000 #3 = Class #14 // Test #4 = Class #15 // java/lang/Object #5 = Utf8 #6 = Utf8 ()V #7 = Utf8 Code #8 = Utf8 LineNumberTable #9 = Utf8 main #10 = Utf8 ([Ljava/lang/String;)V #11 = Utf8 SourceFile #12 = Utf8 Test.java #13 = NameAndType #5:#6 // " ":()V #14 = Utf8 Test #15 = Utf8 java/lang/Object { public Test(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object." ":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=2, args_size=1 0: ldc #2 // int 60000 2: istore_1 3: return LineNumberTable: line 3: 0 line 4: 3 }
在编译时。 这是最基本的编译器优化之一,称为常量折叠 。
只需创建类Test
public class Test { public static void main(String [] args) { long timeInMilliseconds = System.currentTimeMillis(); double timeInMinutes = (double) timeInMilliseconds / (1000 * 60); System.out.println(timeInMinutes); } }
并使用命令对其进行反编译: javap -v Test
你可以看到反编译类的输出:
public static void main(java.lang.String[]); flags: ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=5, args_size=1 0: invokestatic #2 // Method java/lang/System.currentTimeMillis:()J 3: lstore_1 4: lload_1 5: l2d 6: ldc2_w #3 // double 60000.0d 9: ddiv 10: dstore_3 11: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 14: dload_3 15: invokevirtual #6 // Method java/io/PrintStream.println:(D)V 18: return LineNumberTable: line 3: 0 line 4: 4 line 5: 11 line 6: 18
看看第6行: ldc2_w#3 //双60000.0d