Les opérations arithmétiques sur les littéraux sont-elles calculées au moment de la compilation ou de l’exécution?

J’ai ce qui suit:

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

L’opération (1000 * 60) effectuée au moment de la compilation ou de l’exécution? En d’autres termes, existe-t-il des différences de performances lors de l’exécution entre l’extrait de code ci-dessus et:

 double timeInMinutes = (double) timeInMilliseconds / 60000; 

EDIT: ma question est différente de Est-ce que le compilateur Java précalculera des sums de littéraux? , car je mélange l’utilisation de variables et de littéraux dans les opérations arithmétiques. C’est une petite différence, mais comme l’a noté @TagirValeev dans les commentaires ( les opérations arithmétiques sur les littéraux sont-elles calculées au moment de la compilation ou de l’exécution? ), Il existe des cas où certains littéraux ne sont pas pré-compilés.

Selon JLS §15.2 – Formes d’expressions

Certaines expressions ont une valeur pouvant être déterminée au moment de la compilation. Ce sont des expressions constantes (§15.28).

Les opérateurs multiplicatifs tels que *, /, and % entrent dans des expressions constantes, donc elles seraient déterminées lors de la compilation.

@SergeyMorozov était plus rapide que moi pour écrire et obtenir une preuve de code d’octet ( #2 = Integer 60000 ), mais voici la preuve pratique et ci-dessus est la déclaration théorique / officielle:

Essayez également de générer du code d’octet à votre fin en utilisant 1000 * 60 et 60000 , et vous verrez les mêmes instructions de code d’octet, et donc les mêmes performances à l’exécution.

Classe Java:

 public class Test { public static void main(Ssortingng[] args) { int comstackTest = 1000 * 60; } } 

Code d’octet:

 Classfile /E:/Test.class Last modified Oct 9, 2015; size 265 bytes MD5 checksum fd115be769ec6ef7995e4c84f7597d67 Comstackd 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/Ssortingng;)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.Ssortingng[]); 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 } 

Au moment de la compilation. C’est l’une de ces optimisations de base du compilateur, appelée pliage constant .

Il suffit de créer la classe Test

 public class Test { public static void main(Ssortingng [] args) { long timeInMilliseconds = System.currentTimeMillis(); double timeInMinutes = (double) timeInMilliseconds / (1000 * 60); System.out.println(timeInMinutes); } } 

et le décomstackr en utilisant la commande: javap -v Test

Vous pouvez voir la sortie de la classe décompilée:

  public static void main(java.lang.Ssortingng[]); 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 

Jetez un coup d’oeil sur la ligne 6: ldc2_w # 3 // double 60000.0d