java - operaciones - codigo de suma resta multiplicacion y division en netbeans
¿Se calculan las operaciones aritméticas en los literales en tiempo de compilación o tiempo de ejecución? (3)
Tengo los siguientes
double timeInMinutes = (double) timeInMilliseconds / (1000 * 60);
¿La operación (1000 * 60)
realiza en tiempo de compilación o en tiempo de ejecución? En otras palabras, ¿hay diferencias de rendimiento durante el tiempo de ejecución entre el fragmento de código anterior y:
double timeInMinutes = (double) timeInMilliseconds / 60000;
EDITAR: mi pregunta es diferente de ¿El compilador de Java calculará previamente sumas de literales? , ya que estoy mezclando el uso de variables y literales en las operaciones aritméticas. Es una pequeña diferencia, pero como @TagirValeev señaló en los comentarios ( ¿Se calculan las operaciones aritméticas en los literales en tiempo de compilación o en tiempo de ejecución? ), Hay casos en que algunos literales no están precompilados, aunque podrían serlo.
En tiempo de compilación. Esta es una de las optimizaciones más básicas del compilador, conocida como Constant Folding .
Según JLS §15.2 - Formas de Expresiones
Algunas expresiones tienen un valor que se puede determinar en tiempo de compilación. Estas son expresiones constantes (§15.28).
Los operadores multiplicativos como *, /, and %
caen bajo expresiones constantes, por lo que se determinaría en el momento de la compilación.
@SergeyMorozov fue más rápido que yo para escribir y obtener la prueba de código de byte ( #2 = Integer 60000
) pero aquí está la prueba práctica y más arriba está la declaración teórica / oficial:
Intente generar el código de bytes en su extremo también usando 1000 * 60
y 60000
, y verá las mismas instrucciones del código de bytes y, por lo tanto, habrá el mismo rendimiento en tiempo de ejecución.
Clase de java
public class Test {
public static void main(String[] args) {
int compileTest = 1000 * 60;
}
}
Código de byte:
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
}
Solo crea prueba de clase
public class Test {
public static void main(String [] args) {
long timeInMilliseconds = System.currentTimeMillis();
double timeInMinutes = (double) timeInMilliseconds / (1000 * 60);
System.out.println(timeInMinutes);
}
}
y descompilarlo usando el comando: javap -v Test
Puedes ver la salida de la clase descompilada:
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
Eche un vistazo a la línea 6: ldc2_w # 3 // doble 60000.0d