Java 8
Interfaz funcional
¿Qué es esto? Una interfaz funcional es una interfaz que contiene un método (abstracto) no implementado. @FunctionalInterface es una anotación opcional que se coloca encima de dicha interfaz. Necesario para comprobar si cumple con los requisitos de una interfaz funcional (que tiene un solo método abstracto). Pero como siempre, tenemos algunas advertencias: los métodos predeterminados y estáticos no cumplen con estos requisitos. Por lo tanto, puede haber varios métodos de este tipo + uno abstracto, y la interfaz será funcional. También puede contener métodos de la clase Objeto que no afectan la definición de la interfaz como funcional. Agregaré algunas palabras sobre los métodos estáticos y predeterminados:-
Los métodos con el modificador predeterminado le permiten agregar nuevos métodos a las interfaces sin romper su implementación existente.
public interface Something { default void someMethod { System.out.println("Some text......"); } }
Sí, sí, agregamos el método implementado a la interfaz y, al implementar este método, no puede anularlo, sino usarlo como heredado. Pero si una clase implementa dos interfaces con un método determinado, tendremos un error de compilación, y si implementa interfaces y hereda una clase con un determinado método idéntico, el método de la clase principal se superpondrá a los métodos de la interfaz y la excepción no funcionará.
-
Los métodos estáticos en una interfaz funcionan igual que los métodos estáticos en una clase. No lo olvide: no puede heredar métodos estáticos , del mismo modo que no puede llamar a un método estático desde una clase descendiente.
-
Consumidor: toma un argumento de tipo T y no devuelve nada (nulo).
Ejemplo:
void someMethod(T t);
-
Proveedor: no toma nada como entrada, pero devuelve algún valor T.
Ejemplo:
T someMethod();
-
Función: toma un parámetro de tipo T como entrada y devuelve un valor de tipo R.
Ejemplo:
R someMethod(T t);
-
UnaryOperator: toma un argumento T y devuelve un valor de tipo T.
Ejemplo:
T someMethod(T t);
Predicado: toma algún valor T como argumento y devuelve un valor booleano.
Ejemplo:boolean someMethod(T t);
Arroyo
Las transmisiones son una forma de manejar estructuras de datos en un estilo funcional. Normalmente se trata de colecciones (pero puede utilizarlas en otras situaciones menos comunes). En un lenguaje más comprensible, Stream es un flujo de datos que procesamos como si trabajáramos con todos los datos al mismo tiempo, y no con fuerza bruta, como ocurre con for-each. Veamos un pequeño ejemplo. Supongamos que tenemos un conjunto de números que queremos filtrar (menos de 50), aumentarlos en 5 y enviar los primeros 4 números de los restantes a la consola. ¿Cómo hubiéramos hecho esto antes?List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);
int count = 0;
for (int x : list) {
if (x >= 50) continue;
x += 5;
count++;
if (count > 4) break;
System.out.print(x);
}
No parece haber mucho código y la lógica ya es un poco confusa. Veamos cómo se verá usando la transmisión:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)
.filter(x -> x < 50)
.map(x -> x + 5)
.limit(4)
.forEach(System.out::print);
Las transmisiones simplifican enormemente la vida al reducir la cantidad de código y hacerlo más legible. Para aquellos que quieran profundizar más en este tema, aquí tenéis un buen (incluso diría excelente) artículo sobre este tema .
lambda
Quizás la característica más importante y esperada sea la aparición de lambdas. ¿Qué es lambda? Este es un bloque de código que se puede pasar a diferentes lugares para poder ejecutarlo más tarde tantas veces como sea necesario. Suena bastante confuso, ¿no? En pocas palabras, usando lambdas, puede implementar un método de interfaz funcional (una especie de implementación de una clase anónima):Runnable runnable = () -> { System.out.println("I'm running !");};
new Thread(runnable).start();
Implementamos el método run() rápidamente y sin trámites burocráticos innecesarios. Y sí: Runnable es una interfaz funcional. También uso lambdas cuando trabajo con secuencias (como en los ejemplos con secuencias anteriores). No profundizaremos mucho, ya que podemos profundizar bastante, dejaré un par de enlaces para que los chicos que todavía son excavadores de corazón puedan profundizar más:
- artículo sobre expresiones lambda en Java 8 en Habré
- artículo sobre expresiones lambda en Java en el blog de Alexander Kosarev
para cada
Java 8 tiene un nuevo foreach que funciona con un flujo de datos como si fuera un flujo. He aquí un ejemplo:List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);
someList.forEach(x -> System.out.println(x));
(análogo a someList.stream().foreach(…))
Referencia del método
Los métodos de referencia son una sintaxis nueva y útil diseñada para hacer referencia a métodos o constructores existentes de clases u objetos Java a través de :: Las referencias a métodos vienen en cuatro tipos:-
Enlace al diseñador:
SomeObject obj = SomeObject::new
-
Referencia del método estático:
SomeObject::someStaticMethod
-
Una referencia a un método no estático de un objeto de cierto tipo:
SomeObject::someMethod
-
Una referencia a un método regular (no estático) de un objeto específico.
obj::someMethod
someList.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
Para aquellos que quieran más información sobre métodos de referencia:
Tiempo API
Hay una nueva biblioteca para trabajar con fechas y horas: java.time. La nueva API es similar a cualquier Joda-Time. Las secciones más significativas de esta API son:- LocalDate es una fecha específica, por ejemplo: 2010-01-09;
- LocalTime : hora teniendo en cuenta la zona horaria: 19:45:55 (análoga a LocalDate);
- LocalDateTime - combo LocalDate + LocalTime - 2020-01-04 15:37:47;
- ZoneId : representa zonas horarias;
- Reloj : con este tipo puede acceder a la hora y fecha actuales.
- Java y el tiempo: primera y segunda parte sobre Habré
- Introducción a la API de fecha/hora en Java 8
Opcional
Esta es una nueva clase en el paquete java.util , un contenedor de valores cuyo truco es que también puede contener null de forma segura . Recibir opcional: si pasamos nullOptional<String> someOptional = Optional.of("Something");
en Optional.of , obtendremos nuestra NullPointerException favorita . Para tales casos utilizan: - en este método no hay que temer al valor nulo. A continuación, cree un Opcional inicialmente vacío: Para verificar si está vacío, use: nos devolverá verdadero o falso. Realice una determinada acción si hay un valor y no haga nada si no hay ningún valor: Un método inverso que devuelve el valor pasado si Opcional está vacío (una especie de plan de respaldo): Puede continuar durante un tiempo muy, muy largo ( afortunadamente, Opcional ha agregado métodos con ambas manos generosas), pero no nos detendremos en esto. Es mejor para mí dejar un par de enlaces para empezar: Optional<String> someOptional = Optional.ofNullable("Something");
Optional<String> someOptional = Optional.empty();
someOptional.isPresent();
someOptional.ifPresent(System.out::println);
System.out.println(someOptional.orElse("Some default content"));
- Java opcional: el padre de los holívars
- Opcional: El gato de Schrödinger en Java 8
- Nueva clase opcional en Java 8, no es una panacea para NullPointerException
- Características de Java 8: La guía definitiva para JavaRush - Primera y segunda parte ;
- Nuevo en Java 8 en Habré ;
- Las 10 características principales de Java 8 de las que la gente no habla ;
- Tutorial de Java 8 .
Java 9
Entonces, el 21 de septiembre de 2017, el mundo vio JDK 9. Este Java 9 viene con un rico conjunto de características. Si bien no hay nuevos conceptos de lenguaje, las nuevas API y comandos de diagnóstico definitivamente serán de interés para los desarrolladores.JShell (REPL - bucle de lectura-evaluación-impresión)
Esta es una implementación Java de una consola interactiva que se usa para probar la funcionalidad y usar diferentes construcciones en la consola, como interfaces, clases, enumeraciones, operadores, etc. Para iniciar JShell, sólo necesita escribir jshell en la terminal. Luego podemos escribir lo que nuestra imaginación nos permita: usando JShell, puedes crear métodos de nivel superior y usarlos dentro de la misma sesión. Los métodos funcionarán igual que los métodos estáticos, excepto que la palabra clave static se puede omitir. Lea más en el manual Java 9. REPL (JShell) .Privado
A partir de la versión 9 de Java, tenemos la oportunidad de utilizar métodos privados en las interfaces (métodos predeterminados y estáticos, ya que simplemente no podemos anular otros debido a un acceso insuficiente).private static void someMethod(){}
try-with-resources
Se ha actualizado la capacidad de manejar excepciones de prueba con recursos:
BufferedReader reader = new BufferedReader(new FileReader("....."));
try (reader2) {
....
}
Modularidad ( Rompecabezas )
Un módulo es un grupo de paquetes y recursos relacionados junto con un nuevo archivo descriptor de módulo. Este enfoque se utiliza para aflojar el acoplamiento del código. El acoplamiento flexible es un factor clave para la mantenibilidad y extensibilidad del código. La modularidad se implementa en diferentes niveles:- Lenguaje de programación.
- Máquina virtual.
- API estándar de Java.
Colección inmutable
En Java 9, fue posible crear y completar una colección con una línea, mientras la hacía inmutable (anteriormente, para crear una colección inmutable, necesitábamos crear una colección, llenarla con datos y llamar a un método, por ejemplo, Colecciones.listainmodificable). Un ejemplo de tal creación:List someList = List.of("first","second","third");
Otras innovaciones:
- Opcional expandido (se agregaron nuevos métodos);
- las interfaces ProcessHandle y ProcessHandle aparecieron para controlar las acciones del sistema operativo;
- G1: recolector de basura predeterminado;
- Cliente HTTP compatible con protocolos HTTP/2 y WebSocket;
- Corriente ampliada;
- se agregó el marco API Reactive Streams (para programación reactiva);
- Revisión de Java 9 en Habré
- Java 9. ¿Qué hay de nuevo?
- Java 9: nuevas funciones
- Java 9: ¿ya lo has actualizado? ¿No? ¿¡Y no es necesario...!?
- Sander Mak sobre la transición a los módulos Java
Java 10
Entonces, seis meses después del lanzamiento de Java 9, en marzo de 2018 (lo recuerdo como ayer), Java 10 entró en escena.var
Ahora no tenemos que proporcionar un tipo de datos. Marcamos el mensaje como var y el compilador determina el tipo de mensaje según el tipo de inicializador presente a la derecha. Esta característica solo está disponible para variables locales con un inicializador: no se puede usar para argumentos de métodos, tipos de retorno, etc., ya que no existe un inicializador para poder definir el tipo. Var de ejemplo (para tipo String):var message = "Some message…..";
System.out.println(message);
var no es una palabra clave: es esencialmente un nombre de tipo reservado, como int . El beneficio de var es grande: las declaraciones de tipo requieren mucha atención sin aportar ningún beneficio, y esta característica ahorrará tiempo. Pero al mismo tiempo, si una variable se obtiene de una larga cadena de métodos, el código se vuelve menos legible, ya que no queda claro de inmediato qué tipo de objeto se encuentra allí. Dedicado a quienes quieran familiarizarse más con esta funcionalidad:
- Inferencia de tipos de variables locales de Java 10
- Primer contacto con "var" en Java 10
- 26 consejos para usar el tipo var en Java
Compilador JIT (GraalVM)
Sin más preámbulos, permítame recordarle que cuando ejecuta el comando javac, la aplicación Java se compila desde el código Java al código de bytes JVM, que es la representación binaria de la aplicación. Pero un procesador de computadora normal no puede simplemente ejecutar el código de bytes de JVM. Para que su programa JVM funcione, necesita otro compilador para este código de bytes, que se convierte en código de máquina que el procesador ya puede usar. Comparado con javac, este compilador es mucho más complejo, pero también produce código de máquina de mayor calidad. Actualmente, OpenJDK contiene la máquina virtual HotSpot, que a su vez cuenta con dos compiladores JIT principales. El primero, C1 ( compilador de cliente ), está diseñado para un funcionamiento a mayor velocidad, pero la optimización del código se ve afectada. El segundo es C2 (compilador de servidor). La velocidad de ejecución sufre, pero el código está más optimizado. ¿Cuándo se utiliza cuál? C1 es excelente para aplicaciones de escritorio donde las pausas JIT prolongadas no son deseables, y C2 es excelente para programas de servidor de larga ejecución donde dedicar más tiempo a la compilación es bastante soportable. La compilación multinivel es cuando la compilación pasa por C1 por primera vez y el resultado pasa por C2 (utilizado para una mayor optimización). GraalVM es un proyecto creado para reemplazar completamente a HotSpot. Podemos pensar en Graal como varios proyectos relacionados: un nuevo compilador JIT para HotSpot y una nueva máquina virtual políglota. La peculiaridad de este compilador JIT es que está escrito en Java. La ventaja del compilador Graal es la seguridad, es decir, no fallas, sino excepciones, no pérdidas de memoria. También tendremos un buen soporte IDE y podremos utilizar depuradores, perfiladores u otras herramientas convenientes. Además, el compilador puede ser independiente de HotSpot y podrá crear una versión de sí mismo compilada JIT más rápida. Para excavadores:- Profundice en el nuevo compilador Java JIT
- Graal: Cómo utilizar el nuevo compilador JVM JIT en la vida real
- Cómo funciona Graal: compilador Java JVM JIT
Paralelo G1
El recolector de basura G1 es ciertamente genial, de eso no hay duda, pero también tiene un punto débil: realiza un ciclo de GC completo de un solo subproceso. En un momento en el que necesitas toda la potencia del hardware que puedas reunir para encontrar objetos no utilizados, estamos limitados a un solo hilo. Java 10 solucionó este problema. Ahora el GC ahora funciona con todos los recursos que le agregamos (es decir, se vuelve multiproceso). Para lograr esto, los desarrolladores del lenguaje han mejorado el aislamiento de las fuentes principales de GC, creando una interfaz limpia y agradable para GC. Los desarrolladores de esta ternura, OpenJDK, tuvieron que limpiar específicamente el volcado en el código para no solo simplificar al máximo la creación de nuevos GC, sino también para permitir deshabilitar rápidamente los GC innecesarios del ensamblaje. Uno de los principales criterios de éxito es la ausencia de una reducción en la velocidad operativa después de todas estas mejoras. Miremos también: Otras innovaciones:- Se introduce una interfaz limpia de recolector de basura. Esto mejora el aislamiento del código fuente de diferentes recolectores de basura, lo que permite integrar recolectores alternativos de manera rápida y sencilla;
- Combinar fuentes JDK en un repositorio;
- Las colecciones recibieron un nuevo método: copyOf (Collection) , que devuelve una copia inmutable de esta colección;
- Opcional (y sus variantes) tiene un nuevo método .orElseThrow() ;
- A partir de ahora, las JVM saben que se están ejecutando en un contenedor Docker y recuperarán la configuración específica del contenedor en lugar de consultar el sistema operativo en sí.
- Guía de Java 10
- 10 características de JDK 10 que los desarrolladores de Java deben conocer
- Novedades de Java 10: partes uno y dos
GO TO FULL VERSION