lunes, 1 de agosto de 2005

Java 5. ¿Que tiene de bueno y de malo?. Parte I

A partir de la nueva versión de Java (Tiger) aparecieron nuevos features que prometen facilitar el proceso de desarrollo de aplicaciones en Java. Cada uno de nosotros puede estar de acuerdo o no, lo cierto es que a medida que se conozca más del tema y se adquiera experiencia en estos nuevos features, se va a poder decir con certeza cuáles de ellos fracasaron, cuáles pasaros desapercibidos y cuáles fueron un éxito.

Mientras tanto, voy a expresar desde este humilde weblog mi opinión acerca de las nuevas funcionalidades de Java 5, los que para mí son sus pro y contras, cuáles son los que van a dar que hablar y cuáles van a terminar complicando las cosas.

Para comenzar voy a dar una lista de dichas nuevas funcionalidades/facilidades que vienen en Java Standard Edition 5:


  • Auto-boxing/Auto-unboxing

  • Varargs

  • Generics

  • Concurrent

  • Enums

  • Formatter

  • Static import

  • for/in statement

  • Annotations

  • Otras (nuevas interfaces y clases, etc)


En esta ocasión, comenzaré hablando de auto-boxing/auto-unboxing.
Este features elimina la conversión manual de tipos primitivos a objetos wrapper permitiendo asignar a un objeto wrapper un tipo primitivo. Donde se puede ver claramente y a modo de ejemplo, el beneficio de esto es cuando trabajamos con Collections. Como todos sabemos las Collections trabajan únicamente con objetos por lo que para poder tener una colección de enteros debemos crear una colección de java.lang.Integer. Ahora con auto-boxing podemos guardar directamente el tipo primitivo, dejando que "alguien" se encargue de realizar la conversión.

Sin embargo hay que tener ciertos cuidados a la hora de trabajar con auto-boxing/auto-unboxing dado que su mal uso puede generar problemas.

Problema con creación de objetos

Tal vez sin saberlo estemos creando una gran cantidad de objetos innecesarios al trabajar intensamente con este features, por ejemplo veamos el siguiente código:

long start = System.currentTimeMillis();

int adder = 0;
int counter = 0;
for (int i = 0; i < 1000000; i++) {
adder += i;
counter++;
}

long end = System.currentTimeMillis();
System.out.printf("Tiempo consumido %f milisegundos", ((float)(end - start)));

Con este código simple y tonto podemos demostrar cómo se puede hacer un mal uso del autoboxing. Al ejecutarlo obtuve los siguientes resultados:

Tiempo promedio: 62 ms.
No hay garbage collection
No hay creación de objetos innecesarios
El método que más tarda es el printf(...)

Ahora si hacemos uso del autoboxing porque queremos que las variables adder y counter sean objetos Integer, podemos hacer lo siguiente:

long start = System.currentTimeMillis();

Integer adder = 0;
Integer counter = 0;
for (int i = 0; i < 1000000; i++) {
adder += i; // auto-boxing.
counter++; // auto-boxing.
}

long end = System.currentTimeMillis();
System.out.printf("\nTiempo consumido %f milisegundos", ((float)(end - start)));

Al ejecutar este código obtuvimos unos resultados realmente aterradores:

Tiempo promedio: 10063 ms.
El garbage collector se ejecuta 3 veces
Hay picos de 61000 objetos java.lang.Integer creados
El método que mas tarda es el Integer.valueOf(...)

Como vemos la diferencia es importante, por lo que hay que tener cuidado cuando se trabaja con autoboxing.

Si lo que queremos es tener en dos objetos Integer los resultados, lo mejor sería hacer los cálculos con los tipos primitivos y luego crear sólo un objeto con el resultado.

En el próximo blog seguiré hablando de los problemas que ocasiona el autoboxing (el problema con el == y el "equals" y el problema con el pasaje de parámetros) y otros de los features de Java5, pero no crean que todas son pálidas, también hablare de las cosas buenas que brindan estos features y principalmente de los mejores features: Metadata y concurrent (según mi opinión).