Novedades y nuevas características de Java 8

Escrito por el , actualizado el .
java programacion planeta-codigo
Enlace permanente Comentarios

La octava versión de Java añade numerosas novedades importantes al lenguaje. Algunas de las más destacadas son las expresiones lambdas y los streams que dotan al lenguaje de características de programación funcional pero también lo hacen en muchas construcciones de código comunes más expresivo, menos extenso y más legible. Pero hay otras novedades relevantes que detallo en el artículo como los métodos por defecto en interfaces o la nueva API para fechas.

Java

El 18 de marzo de 2014 se publicó la nueva versión de la plataforma Java 8, Java 7 fue liberada el en julio de 2011. Java 8 incorpora varias novedades siguiendo la tendencia de otros lenguajes como lambdas o closures o una demandada nueva API para el manejo de fechas entre otras muchas características más. La lista completa de novedades es bastante amplia, a continuación algunas características de Java explicadas con un poco más de detalle.

Introducción

Java 8 representa una evolución notable en este lenguaje de programación al mismo nivel o más del que supuso la versión Java 5. Aunque tengas varios años de experiencia quizá aún no has tenido oportunidad de usar todas las novedades que se han incorporado en cada versión en proyectos reales, probablemente porque los caminos de migración de las empresas son lentos y muchas siguen usando versiones antiguas en sus aplicaciones. Para conocer y aprovechar todas estas novedades de Java recomiendo los siguientes libros que son de lo mejor que he encontrado como documentación, el primer libro es Thinking in Java que nos introduce en este lenguaje de programación desde el inicio, aunque ya conozcas o uses Java el libro Effective Java contiene gran cantidad de información y consejos para usar Java de una forma más efectiva haciendo un repaso de las características del lenguaje que aunque no esté actualizado con las novedades que introduce Java 8 casi todo sigue siendo aplicable, el último libro es Java 8 in Action que explica en mucho más detalle que lo hecho en este artículo cada una de las nuevas características de Java 8 y complementa el libro Effective Java pero aprovechando las novedades introducidas en el lenguaje.

La lista de novedades es la siguiente:

  • Se añaden las expresiones lambda o closures y se adapta la API para usarlas en los sitios que se pueda.
  • Se definen nuevos perfiles compactos para dispositivos que no necesitan toda la API Java, esto es una alternativa a la modularización. Inicialmente la modularización era una característica que estaba planificada para Java 8 pero finalmente se ha aplazado a posteriores versiones.
  • Incluido nuevo motor de JavaScript Nashorn que implementa ECMAscript 5.1 y es más rápido que su predecesor Rhino.
  • Eliminación de espacio de memoria Permanent Generation (PermGen) que pasa a llamarse Metaspace. Su tamaño será dinámico pero no evitará fugas de memoria.
  • Soporte para la creación de una máquina virtual menor a 3 MB.
  • Acceso mediante reflection a los nombres de los parámetros. Mejorará la legibilidad del código que use reflection y permitirá mejorar el soporte en los IDE.
  • Ordenación en java.util.Arrays de forma paralela.
  • Operaciones masivas sobre colecciones tales como filter/map/reduce (streams) de forma serializada o paralela.
  • Soporte de forma estándar para la codificación y decodificación Base64.
  • Nueva API para Date y Time.
  • Varias mejoras de seguridad.
  • Se incorporan en la máquina virtual Java HotSpot características que estaban en JRockit, convergiendo ambas máquinas virtuales. Se incorpora Mission Control.
  • Mejoras en JDBC la base para el acceso en bases de datos en Java.
  • Otras novedades.

Nuevas características

Streams

Los streams no son un nuevo tipo de colección son una nueva forma de recorrer las colecciones distinta a los Iterator. La ventaja de los streams es que pueden procesarse de forma serializada o paralela y proporcionan un estilo de operaciones más funcionales. Un flujo consiste un una fuente (una colección), varias operaciones intermedias (de filtrado o transformación) y una operación final que produce un resultado (suma, cuenta…). Los streams son lazy de modo que las operaciones solo se realizan cuando se llama a la operación final, también son eficientes no necesitando en algunos casos procesar todos los elementos del stream para devolver el resultado final.

Tradicionalmente en la API de colecciones la iteración sobre los elementos debíamos proporcionarla de forma externa. Con Java 8 podemos expresarla de forma interna, de la siguiente manera.

1
2
3
int alturaMedia = personas.stream()
    .mapToInt((Persona p) > { return p.getAltura(); })
    .average();
Stream.java

Lambda

Esta es una de las principales novedades y que más se estaba echando de menos en Java de otros lenguajes como Groovy o Python. Las expresiones lambda son funciones que no está asociadas a un determinado nombre y que pueden pasarse como argumento a otras funciones. Tienen el siguiente aspecto:

1
2
(Persona persona) > { return persona.getAltura(); }

Lambda.java

El uso de expresiones lambdas junto con el stream API proporciona a Java 8 características de programación funcional, pero sobre todo hace el código más sencillo, menos extenso, más expresivo y más legible. En las expresiones lambda de Java podemos seguir aprovechándonos de la compilación estática y del tipado fuerte.

Referencias de métodos

Todo el código desarrollado previamente a Java 8 no hace uso de las lambdas, pero con las referencias a métodos podemos usar esos métodos ya implementados como si se tratasen de funciones lambdas. Hay diferentes formas de hacer referencias a métodos:

  • A métodos estáticos
  • A un método de una instancia concreta
  • A un método de instancia de una instancia arbitraria de un tipo
  • A un constructor
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Método estático
Persona::compareAltura

// Método de una instancia concreta
persona::getAltura

// Método de instancia de una instancia arbitraria de un tipo
Persona::getAltura

// Constructor
Persona::new

ReferenciaMetodos.java

Interfaces funcionales

Una interfaz funcional es aquella que solo tiene un método abstracto (sin implementación). Algunos ejemplos de interfaces funcionales son Runnable, ActionListener, Comparator y Callable. Para definir una interfaz funcional se puede usar la anotación @FunctionalInterface y pueden representarse con una expresión lambda. En el siguiente ejemplo puede apreciarse que con las interfaces funcionales y las lambdas podemos hacer lo mismo de forma más clara, menos verbosa y con código más legible.

1
2
3
4
5
Collections.sort(personas, new Comparator<User>() {
    public int compare(Persona p1, Persona p2) {
        return p1.getAltura().compareTo(p2.getAltura());
    }
});
InterfazFuncional-1.java

En Java 8 podemos hacer:

1
2
3
Collections.sort(personas, (Persona p1, Persona p2) -> { 
    p2.getAltura().compareTo(p2.getAltura())
});
InterfazFuncional-2.java

Java 8 incorpora varias interfaces funcionales que puede ser usadas en expresiones lambda, entre ellas están:

  • Predicate: función que retorna un booleano dado un argumento.
  • Function: función que retorna un valor dado un argumento.
  • Supplier: producen un tipo, al contrario que las funciones no tienen argumento
  • Consumer: representa una operación a realizarse en un argumento.

Métodos por defecto en interfaces

Hasta ahora las interfaces en Java solo podían definir métodos pero no sus implementaciones. El problema con las interfaces es que cuando se modifican se rompen todas las clases que las usan. Esto se ha resuelto de tal forma que se puedan añadir nuevos métodos con implementación a las interfaces y ha sido necesario para incorporar las lambdas a interfaces existentes como List. En Java 8 las interfaces podrán incorporar implementaciones para algunos de sus métodos, teniendo así algo parecido a herencia múltiple.

1
2
3
4
5
6
7
public interface Math { 
    int add(int a, int b);
 
    default int multiply(int a, int b) {
        return a * b;
    }
}
MetodosDefault.java

Métodos estáticos en interfaces

Además de definir métodos por defecto en las interfaces a partir de ahora podemos definir métodos estáticos. Definiendo métodos estáticos en las interfaces evitaremos tener que crear clases de utilidad. Podremos incluir en un mismo tipo (la interfaz) todos los métodos relacionados.

1
2
3
4
5
6
7
8
9
public interface Persona {

    String getNombre();
    int getAltura();

    static String toStringDatos() {
        return getNombre() + " " + getAltura();
    }
}
MetodosStatic.java

Mejoras en la programación asíncrona

Los procesadores actuales están aumentando su capacidad de proceso más a base de concurrencia proporcionando más núcleos que a base de hacerlos más rápidos en Ghz o instrucciones por ciclo, los lenguajes de programación tienen que adaptarse para facilitar su aprovechamiendo de forma fácil. Desde las primeras versiones de Java ya se incluía soporte para trabajar con hilos o threads sin embargo su programación es propensa a errores y difícil de depurar. Java 7 con el nuevo soporte conocido como Fork/Join mejoraba la situación.

Por otra parte para maximizar el aprovechamiento de los recursos disponibles cuando surgen bloqueos de entrada/salida como acceso a disco o comunicación por red surge la programación asíncrona. Para ello Java 8 mejora el soporte existente desde Java 7 con la clase Future que permite recoger el resultado de una operación mientras se realiza otra al mismo tiempo, en Java 8 se proporciona la clase CompletableFuture que implementa la interfaz Future. La clase CompletableFuture soporta el uso de lambdas, hace más fácil la programación concurrente y programación asíncrona que el Fork/Join y el Future respectivamente permitiendo igualmente ejecutar tareas de forma concurrente, combinar el resultado de dos tareas que se ejecutan al mismo tiempo, realizar otra tarea al terminar una prevía o por supuesto esperar a que todas las tareas concurrentes finalicen.

Anotaciones en cualquier uso de tipos

Con la introducción de anotaciones en Java 5 podemos usar anotaciones en la declaración de los tipos (definición de clases, interfaces, propiedades, métodos, …). Desde ahora podremos usar las anotaciones en el uso de cualquier tipo como por ejemplo expresiones new, casts, cláusulas implements y cláusulas throws.

Java Time

Trabajar con fechas, horas y diferentes zonas horarias en Java tradicionalmente ha sido molesto, para tratar de mejorar la situación podíamos usar la librería JodaTime. Finalmente, después de mucho tiempo esperando a que se hiciera se va a proporcionar una mejor API en el JDK 8 para trabajar con fechas, horas y zonas horarias.

Futuro con Java 9

Viendo el pasado reciente de Java hablar del futuro puede ser precipitado, quizá la característica más comentada sea la modularización con el proyecto conocido como Jigsaw, pero ha sido abandonada para Java 8 según tengo entendido por ser difícil incorporarla manteniendo la compatibilidad hacia atrás, por el momento dispondremos de una solución intermedia con los compact profiles.

Otro de los puntos donde parece que se pondrá énfasis es en el soporte para entornos en la nube que son en estos momentos la tendencia hacia la que evolucionan las aplicaciones.

Versiones anteriores de Java

Las versiones de Java 5, 6 y 7 también incluyeron varias novedades y dado que en el ámbito empresarial la tecnología se adopta de forma lenta es posible que mucha gente (incluido yo mismo) aún desconozca cuales eran algunas de las principales novedades y características de versiones anteriores.

Java 7

  • Project coin
  • Strings en switchs
  • Gestión automática de recursos en sentencias try-catch
  • Multicatch
  • Rethrow de excepciones más precisos
  • Operador diamante <>
  • Literales binarios
  • Guiones bajos en literales numéricos
  • Fork/Join y utilidades de concurrencia
  • Mejoras en trabajo con archivos y carpetas

Más en Java 7 New Features and Enhancements y Java 7 a look back

Java 6

  • Lenguajes de scripting
  • API para el compilador
  • Nuevas anotaciones
  • Nueva API para XML (StaX)

Más en Java 6 New Features and Enhancements y Introduction to java 6 new features

Java 5

  • Generics
  • Bucle for mejorado
  • Autoboxing/unboxing
  • Enums
  • Varargs
  • Static import
  • Anotaciones

Más en Java 5 New Features and Enhancements

Presentación

Finalmente, una presentación muy interesante en forma de vídeo de Youtube en español y la presentación de la que se habla en formato pdf que fue publicada en JavaHispano, en él se habla de muchas de las novedades y de algunas futuras en Java 9.


En los tutoriales de Java hay algunos de estos puntos más ampliados y algunos apartados no comentados en esta entrada. Otros artículos muy completos son Java 8 Tutorial y Everything about Java 8, en el apartado de referencia al final de la entrada hay algún enlace más digno de lectura.

Java es usado ampliamente en entornos empresariales ya sean públicos o privados, pequeños o grandes que con las especificaciones de Java EE 7 proporcionan a las aplicaciones un conjunto de funcionalidades estadarizadas con las que tendremos posibilidad de elegir la implementación que mejor consideremos no encadenándonos a un determinado vendedor.


Comparte el artículo: