domingo, 22 de diciembre de 2019

Usar y tirar (autoboxing)

A partir de java 5 es posible evitar hacer conversiones explícitas de int a java.lang.Integer, por ejemplo:

   public void main() {
      Integer suma1 = sum(1, 2);
      suma1 = sum(1, 2);
   }

   static int sum(Integer a, Integer b) {
      return a + b;
   }

Cuando cuando se de-compila el código de la functión main (Útilizando Bytecode viewer), se obtiene lo siguiente:

     public main() { //()V
         ...

         L1 {
             iconst_1
             invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer;
             iconst_2
             invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer;
             invokestatic AutoboxExample.sum(Ljava/lang/Integer;Ljava/lang/Integer;)I
             invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer;
             astore1
         }
         L3 {
             iconst_1
             invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer;
             iconst_2
             invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer;
             invokestatic AutoboxExample.sum(Ljava/lang/Integer;Ljava/lang/Integer;)I
             invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer;
             astore1
         }
         L4 {
             return
         }
         L2 {
         }
     }

Donde se ve que el código compilado es idéntico a cuando se utiliza valueOf explícitamente.

Esta funcionalidad del compilador, evita que se creen objetos de tipo Integer mediante el constructor Integer(int). Internamente la función valueOf(int), utiliza un cache,  para disminuir la creación de objetos de un solo uso.

Este cache está configurado por defecto para los número de -128 a 127 y se puede configurar para incrementar la cantidad de elementos (-XX:AutoBoxCacheMax=<size>).