当前位置: 首页 > 知识库问答 >
问题:

文字的算术运算是在编译时还是运行时计算的?

印曜灿
2023-03-14

我有以下几点:

double timeInMinutes = (double) timeInMilliseconds / (1000 * 60);

操作(1000*60)是在编译时还是在运行时完成的?换句话说,在运行时,上述代码段和以下代码段之间是否存在性能差异:

double timeInMinutes = (double) timeInMilliseconds / 60000;

编辑:我的问题不同于Java编译器是否会预先计算文字的总和?,因为我在算术运算中混合使用变量和文字。虽然差别很小,但正如@TagirValeev在评论中指出的(对文本的算术运算是在编译时还是在运行时计算的?),有些情况下,某些文字没有预先编译,即使它们可能是。

共有3个答案

赵英资
2023-03-14

只需创建类测试

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#U w#3//double 60000.0d

吕向荣
2023-03-14

在编译时。这是最基本的编译器优化之一,称为常数折叠。

莫宝
2023-03-14

根据JLS§15.2-表达形式

有些表达式的值可以在编译时确定。这些是常量表达式(§15.28)。

*、/、和%这样的乘法运算符属于常量表达式,因此它将在编译时确定。

@SergeyMorozov比我更快地编写和获得字节码证明(#2=整数60000),但这是实际证明,以上是理论/官方声明:

尝试在您的终端生成字节代码,以及使用1000*6060000,您将看到相同的字节代码指令,因此将有相同的运行时性能。

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."<init>":()V
   #2 = Integer            60000
   #3 = Class              #14            //  Test
   #4 = Class              #15            //  java/lang/Object
   #5 = Utf8               <init>
   #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          //  "<init>":()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."<init>":()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
}
 类似资料:
  • 下面是代码 在类中,我使用参数10/3调用方法(如代码中所示)。由于callMtd在baseClass中重载,默认情况下应该调用哪个版本?因为它是重载的,方法绑定应该在编译时发生,但是10/3的计算能在编译时发生吗?

  • 问题内容: 是否可以查询两个字段之间相减的结果? 例如,有两个字段:“开始”,“结束”。我想要带的文件。 可以直接完成此操作吗,还是唯一的方法是在加载具有这种差异的文档时创建一个新字段? 问题答案: 查询中的脚本过滤器可能是解决方法。 http://www.elasticsearch.org/guide/zh- CN/elasticsearch/reference/current/query-ds

  • 我正在学习如何通过OCA考试,并坚持这个java字符串池的概念。 考虑以下几点: 和在字符串中是相同的,在对象中也是相同的,因为它是相同的字符串文本,所以JVM在编译时将字符串池和。 现在,是在运行时计算的,因此应该返回一个新字符串。因此,应该为false,但事实并非如此。为什么? 我的一个理论是方法首先检查是否有空白需要删除,如果没有,则简单返回本身。这可以解释为什么s1==s3,但我不确定。

  • 这两个类路径能完全不同吗?

  • 我试图计算变量,但我的答案是错误的(警告:除以零),我假设它是因为默认情况下,我的变量实际上是零。 我怎么能重写这个来检查它是否为零,只有运行计算,如果它不是零? 除此之外,当我的变量不是“0”时,代码可以完美地工作 在编辑脚本之前,默认情况下所有变量都是“0”。

  • 主要内容:numpy.reciprocal(),numpy.power(),numpy.mod(),复数数组处理函数NumPy 数组的“加减乘除”算术运算,分别对应 add()、subtract()、multiple() 以及 divide() 函数。 注意:做算术运算时,输入数组必须具有相同的形状,或者符合数组的广播规则,才可以执行运算。 下面看一组示例: 输出结果: 下面介绍了 NumPy  中其他重要的算术运算函数。 numpy.reciprocal() 该函数对数组中的每个元素取倒数,并