This was originally posted on Takipi blog. Takipi tells you when and why code breaks in production. Learn more.
Lambdas lambdas lambdas. Eso es todo lo que se oye hablar sobre Java 8. Pero esa no es nada más que una parte. Java 8 cuenta con muchas nuevas funcionalidades: algunas de ellas son nuevas -y muy poderosas- clases y expresiones, mientras que otras son cosas que deberían haber estado allí desde el mismo nacimiento.
Me gustaría hacer un recorrido por diez nuevas funcionalidades que considero pequeñas joyas dignas de tener en cuenta. De seguro habrá por lo menos una o dos que querrás probar, así que... ¡allá vamos!
Una nueva incorporación al lenguaje Java consiste en que ahora es posible agregar cuerpos de métodos a las interfaces (llamados métodos default o por defecto). Estos métodos son incorporados implícitamente a cada clase que implemente la interfaz.
Esto te posibilita el añadir funcionalidad a las librerías existentes sin generar desorden en nuestro código. Eso, definitivamente, es una ventaja. Por otro lado, esto también implica desdibujar los límites entre una interfaz, que se supone debe servir como un contrato, y una clase, que representa concretamente su implementación. Por un lado es positivo que se trate de una manera elegante de crear interfaces más prolijas, evitar repeticiones y extender librerías. Por otra parte, parece que negativo que dentro de poco estemos viendo métodos de interfaz consultando a this y asignándole una herencia de tipo concreto. Escalofríos…
El lanzamiento de un proceso externo es una de esas cosas que haces sospechando que necesitarás volver para hacer depuración cuando el proceso se cuelgue, se tranque o consuma un 100 % del CPU. La clase Proceso ahora viene equipada con dos nuevos métodos para ayudarte a controlar los procesos rebeldes.
El primero de ellos, isAlive(), te permite analizar fácilmente si el proceso todavía está funcionando bien, sin necesidad de esperarlo. El segundo -que es también el más poderoso- es destroyForcibly(), que te brinda la posibilidad de matar (por la fuerza) un proceso que ha caducado o que ya no es necesario.
He aquí algo de lo que sentirse felices. A nadie le gusta sincronizar código. Es un camino seguro a la reducción del rendimiento de tu aplicación (especialmente bajo escala), o peor aún: causar que se cuelgue. Aun así, a veces no tienes otra opción.
Existen muchas expresiones para sincronizar el acceso desde múltiples hilos a un recurso. Una de las más veneradas es ReadWriteLock y sus implementaciones asociadas. Esta expresión está pensada para reducir la contención, por medio de permitir que múltiples hilos consuman un mismo recurso, bloqueando únicamente a aquellos que lo manipulan. Suena perfecto (en teoría), pero en la práctica este bloqueo es muy leeeento, especialmente con un número alto de hilos escritores.
Esto se volvió peor y peor, tanto que Java 8 presenta un RWLock (bloqueo de lectura y escritura) totalmente nuevo, hecho desde cero, llamado StampedLock. No solo este bloqueo es más rápido, sino que también provee una API muy potente para el bloqueo optimista, donde puedes obtener un bloqueo lector con un muy bajo costo, esperando que no ocurra ninguna operación de escritura durante la sección crítica. Al final de la sección consultas al bloqueo para ver si ha ocurrido alguna escritura durante ese lapso, en cuyo caso puedes decidir si intentarlo nuevamente, escalar el bloqueo o rendirte.
Este bloqueo es una herramienta tan potente que merece un artículo completo exclusivamente sobre él. Estoy aturdido de felicidad con este nuevo juguete... ¡bien hecho!
Puedes leer más aquí.
Esta es otra pequeña joya para todos aquellos que trabajen en aplicaciones multihilos. Una nueva API simple y eficiente para leer y escribir en contadores desde múltiples hilos, de una manera que es aún más rápida que los AtomicIntegers. ¡Eso sí que es impresionante!
¡Ah, NullPointers, la perdición de todo desarrollador Java! Esta, que es probablemente la más popular entre todas las excepciones, ha estado por aquí desde el comienzo de los tiempos. O, al menos, desde 1965.
Inspirado en Scala y Haskell, Java 8 tiene una nueva plantilla denominada Optional para envolver referencias que puedan ser nulas. No significa, ni cerca, la extinción de los nulls, sino más bien un medio para que el diseñador de una API pueda expresar al nivel del código (vs. la documentación) que puede que un valor nulo (null) sea devuelto o pasado a un método, y que el llamador debería estar listo para ello. Así, esto únicamente funcionará para nuevas API, asumiendo que los llamadores no permitirán que la referencia escape al wrapper (clase envolvente) en que puede ser desreferenciado de forma insegura.
Tengo que admitir que tengo opiniones encontradas con respecto a esta funcionalidad. Por un lado, los nulls todavía son un gran problema, así que agradezco cualquier cosa que se haga en ese frente. Por otra parte, sin embargo, tengo mis reservas con respecto a su éxito. Y esto porque el empleo de Optional requiere continuar con los esfuerzos a lo ancho de la compañía y con muy pocos valores inmediatos. A menos que revista una fuerte obligatoriedad, lo más probable es que sea dejado a un lado.
Encontrarás más información sobre Optional aquí.
Otra pequeña mejora al lenguaje Java consiste en el hecho de que las anotaciones ahora puedan ser añadidas a casi cualquier cosa dentro de tu código. Anteriormente, las anotaciones podían exclusivamente ser agregadas a cosas como declaraciones de métodos o clases. En Java 8, las anotaciones pueden ser añadidas a declaraciones de parámetros y variables, al crear descendientes a un valor de un tipo específico o aún al asignar un nuevo objeto.
Esto es parte de un esfuerzo en conjunto (junto con las mejoras en las API y las herramientas de documentación de Java) por lograr que el lenguaje tenga una mayor conexión con las herramientas de instrumentación y análisis estadístico (como, por ejemplo, FindBugs). Es una funcionalidad interesante aunque, como en el caso del invokeDynamic presentado en Java 7, su valor auténtico dependerá de lo que la comunidad haga con ella.
Aquí tenemos un conjunto de métodos que deberían haber formado parte de las librerías principales desde el primer día. Uno de mis pasatiempos favoritos consiste en depurar desbordamientos numéricos (overflow) cuando los enteros superan 2^32, y seguir hasta crear la peor de las más desagradables y aleatorias combinaciones de errores (básicamente, “¿Cómo obtuve este valor tan extraño?”).
Una vez más, aquí no hay una solución perfecta, sino un grupo de funciones para operar en números que arrojan, cuando se desbordan, de una manera menos indulgente que tu operador +/ * estándar, que desborda implícitamente. Si fuera por mí, yo haría que este fuera el modo por defecto de la JVM, con funciones explícitas que permitan el desbordamiento aritmético.
La iteración de los contenidos de un árbol de directorios ha sido por largo tiempo una de esas típicas búsquedas de Google (en cuyo caso deberías estar usando Apache.FileUtils). Java 8 ha proporcionado un lavado de cara a la clase Files, con diez métodos nuevos. Mi favorito es walk(), que crea una corriente perezosa (importante en sistemas de archivos grandes) para iterar los contenidos de una estructura de directorios.
No es poco lo que se escucha hablar hoy en día sobre la vulnerabilidad de claves y contraseñas. La seguridad en la programación es un campo complicado y propenso a los errores. Por eso me gusta el nuevo método SecureRandom.getinstanceStrong() que elige automáticamente el generador aleatorio más fuerte disponible para la JVM. Esto reduce las posibilidades de que falles al obtener –o selecciones por defecto- un generador débil, lo cuál haría los valores encriptados y las claves más susceptibles al hacking (piratería).
Java 8 presenta una API Date Time (de tiempo y hora) completamente nueva. Esto es perfectamente entendible, ya que la actual no es muy buena. Joda ha sido, básicamente, la API de uso para la hora y el tiempo en Java por años. Aún así, con la nueva API, persiste un gran problema: hay un MONTÓN de código y librerías que usan la antigua API.
Y todos sabemos que ellas vinieron para quedarse. Así que, ¿qué hacemos?
Con este fin, Java 8 ha hecho algo muy elegante, al agregar un nuevo método a la clase Date, llamado toInstant(), que le convierte a la nueva API. Esto te posibilita un salto veloz a la nueva API, aun cuando trabajes con código que utilice la antigua API Date (y que va a seguir haciéndolo así, por lo menos en el futuro próximo).
¿Hay alguna funcionalidad que crees que faltó aquí, o algo en lo que estás en desacuerdo con este análisis? Déjanos saberlo en la sección de comentarios que aparece más abajo: ¡Para eso esta allí!