Anda di halaman 1dari 19

Java es hoy en día el lenguaje de programación más popular y a un que

existe detractores, la verdad es que sigue teniendo una gran popularidad,


que, a decir verdad, yo sigo siendo unos de sus Fans.

Pocas son las versiones de Java que han marcado un antes y un después en
el lenguaje, por ejemplo, la introducción de anotaciones y genéricos de la
Java 5, o los Lambda expresions y paralelismo de Java 8 y finalmente la
llegada de Java 9 trae algunas mejores importantes que son dignas de
elogiar.

Al momento de la redacción de este artículo, la versión de Java 9 se


encuentra en Beta, pero se espera su liberación el día 21 de septiembre, por
lo que, al momento de leer esta nota, es muy probable ya que esta liberada
la versión final.

Como sea, la verdad es que cada versión de Java trae una gran expectativa,
y por lo general cada versión trae tantos cambios como para escribir un libro
completo, por lo que en este artículo trataremos de hablar de lo más
relevante y que como programadores podría ser de los más interesante, así
que, sin más preámbulos, veamos las mejoras.

Sistema de módulos
Sin lugar a duda, el sistema de módulos es la característica más relevantes
y esperadas, pues desde su nacimiento, el JDK de Java ha sido monolítico,
lo que implica que tenías todos o nada. En este sentido, las aplicaciones Java
requerían montar en el classpath todas las clases del JDK + las clases de los
proyectos. lo que implicaba varios problemas, como el espacio requerido para
cargar todas las clases al classpath o la colisión en los nombres de las clases
de diferentes paquetes.

El sistema de módulos ayuda a que se realice un encapsulamiento real, pues


permite definir que paquetes de un módulo se expone a los demás evitando
que otros módulos utilicen paquetes que no fueron expuestos, incluso
mediante Reflexión.

Para crear un módulo en Java 9, es requerido que el proyecto tengo un


archivo llamado module-info.java en la raíz del proyecto, con la siguiente
estructura.

El cual deberá declarar mediante la sentencia export los paquetes que podrán
ser accedidos por otros módulos, y la sentencia requires para importar los
módulos de los que depende. Por default, todos los paquetes que no sean
expuestos serán privados de forma predeterminada.
En la imagen podemos observar que el Modulo A requiere del MóduloB, y que
el Modulo B expone el paquete com.centripio.moduleb, aunque por otro lado,
vemos que el ModuloA importa al módulo completo, no sus paquetes.

Servicios
Otra de las cosas que ofrece la modularización, es exponer servicios. Los
servicios son clases que son expuestas mediante una interface, que la
implementación real queda totalmente oculta, pues no es necesario exponer
mediante export la implementación.

Veamos el siguiente ejemplo, tenemos un Módulo A y un Módulo C, el modulo


A requiere el servicio expuesto por el Modulo C, para esto, el Modulo A no
debe de conocer la implementación del Módulo C. Para esto tendremos un
tercer módulo llamado Hello, el cual solo expone una interface, esta interface
será común entre el modulo A y C, el modulo C va exponer el servicio por
medio de la interface del Módulo C y el Módulo A buscará todos los servicios
expuestos mediante la interface del Módulo Hello.

Fig 2- Servicios con Java 9


El archivo module-info del módulo Hello queda de la siguiente manera:

Podemos observar que el módulo Hello expone el paquete


com.centripio.hello, el cual contiene la interface IHelloWorld. Al contar con la
instrucción exports, le indicamos que todas lo que este en este paquete podrá
ser visible por otros módulos.

El archivo module-info del módulo c queda de la siguiente manera:

El Módulo C indica que requiere (requires) del módulo Hello, como podemos
ver, no hacemos referencia a los paquetes expuestos, sino a todo el modulo.
Por otra parte, le estamos indicando que el módulo expone un servicio
(provides) el cual se expone encapsulado mediante la interface
com.centripio.hello.IHelloWorld del Módulo Hello, pero la implementación
real es la clase com.centripio.modulec.impl.HelloWorldCImpl la cual está
dentro del Módulo c. notemos que en ningún momento estamos exponiendo
mediante export el paquete de la clase de implementación.

El archivo module-info del módulo A queda de la siguiente manera:


Finalmente, vemos que el Modulo A indica que requiere del Módulo Hello, y
adicional, hace uso (uses) de los servicios expuestos por la interface
com.centripio.hello.IHelloWorld.

Ahora bien, veamos cómo se ejecuta esto dentro del método Main.

En la línea 8 utilizamos la case ServiceLoader, la cual tiene el método load


que recibe una clase/interface para buscar todos los servicios encapsulados
por esta interface. El retorno es una lista, pues varios módulos pueden
exponer una implementación diferente. Finalmente, iteramos la lista y
llamamos el método hello definido en la interface del Módulo Hello. Si has
utilizando OSGI, este te podrá resultar algo muy familiar.

Modularize JDK (Jigsaw)


Unos de los principales problemas de Java desde el inicio, ha sido la
popularización del JDK, pues cualquier aplicación desarrollada en Java,
requiere de una instalación completa del JRE, un que solo requiera unas
cuantas API. En Java 9 se soluciona este problema con el proyecto llamado
Jigsaw, el cual se viene consolidado desde le Java 8 y que en el Java 9 ya lo
podemos ver consolidado.

La idea central de modularizar el JDK consiste en que una aplicación puede


ser ejecutada en una versión reducida del JRE, de esta forma, podemos
ahorra recursos importantes en nuestros dispositivos, lo cual viene bastante
bien la arquitectura de micro servicios o despóticos de bajos recursos.
Ilustración 1- Aplicación no modular

La imagen anterior ilustra la forma en que trabajábamos con versiones


anteriores del JDK, en la cual era necesario tener todas las API´s para que
nuestra aplicación funcionara.

Ilustración 2 – Aplicación modular.

Por otra parte, Java 9 nos permite ejecutar nuestra aplicación solo con los
módulos necesario.
Métodos privados en interfaces
Una de las novedades que introdujo el Java 8 es la implementación default
de las interfaces, sin embargo, todos los métodos tenían que ser públicos.
Con la llegada de Java 9, esto cambia, y es posible definir métodos privados,
por lo que solo podrán ser utilizados en dentro de la misma interface, más
precisamente, solo se podrán llamar dentro de los métodos por default. Ya
que fuera de la interface no será accesibles, incluso en las clases que las
implementen.

Se pueden declarar métodos privados y métodos privados estáticos.

Como podemos ver en este ejemplo, solo es necesario declararlos con el


modificador de acceso private, y no es necesario utilizar la instrucción
default.
Anotación @deprecated mejorada
Desde su creación, la anotación @deprecated ha servido a los programadores
para enterarse si una clase o método ya esta no está aconsejada para su
uso, debido a que ya no recibirá más soporte o por que se ha creado una
nueva funcionalidad mejor que sustituye a la anterior, sin embargo, no era
posible determinar desde cuando fue deprecada, y si ha sido marcada para
ser eliminada en el futuro. El nuevo formato de la anotación es la siguiente:

El atributo forRemoval indica si ha sido marcado para ser removido


permanentemente en las siguientes versiones y since le indica al
programador desde que versión ha sido marcado como deprecated.

Métodos de fábrica de conveniencia para


colecciones
Java 9 a incluido algunos métodos de utilidad que ayudan a crear colecciones
inmutables de una forma mucho más simples, pues eliminan la verbosidad
requerida en versiones para crear e inicializar las colecciones inmutables.

Las colecciones inmutables son aquellas en las que no es posible agregar o


eliminar valores, y son muy utilizadas en procesos concurrentes, pues no
generan bloqueos.

Aquí algunos ejemplos de cómo crear una List, Set y un Map:


Como podemos observar, utilizamos el método of de la interface de la
colección deseada, y como resultado, obtendremos una implementación de
colección, pero inmutable. En el caso de las listas y Sets, solo mandamos
una lista de valores, que será agregados en ese orden, pero en el Map, los
valores vienen en pares, el primero es el Key y el segundo él es value.

Existen algunas reglas básicas que debemos de entender cuando utilizamos


estas colecciones inmutables.

1. Si intentamos agregar o eliminar un valor de la colección, lanzarán

UnsupportedOperationException

2. En las List y Set no se permiten valores null y en el Map, la llave no puede

contener valor null, ya que, en cualquiera de estos dos casos, se lanzará

NullPointerException.

3. Instancias basadas en valores, esto quiere decir que el método of puede

devolver la misma instancia para una lista con los mismos valores, por lo que:

List.of(“foo”, “bar”) == List.of(“foo”, “bar”) podrían devolver la misma

instancia, todo dependerá de la JVM

4. La colección resultante será serializable si los valores lo son, en caso

contrario, la lista no será serializable.


Mejoras en el try-with-resources
Una de las novedades que nos trajo Java 7 fue la posibilidad de administrar
recursos dentro de un Try-Catch y que este los cerrar por nosotros al
terminar el bloque, sin embargo, tenía el principal inconveniente de que
requería una nueva variable, ya sea declararla y asignarle el valore de un
recurso existente o declarar la variable y abrir en ese momento el recurso:

El ejemplo anterior es como se hacía en versiones pasadas, la nueva forma


de hacerlo es la siguiente:

En Java 9 es posible utilizar una variable existen, con la única condición es


que la variable input sea efectivamente final, es decir, que se asigne un valor
en su declaración y nunca se modifique.
Nueva API HTTP
La llegada de Java 9 nos trae una nueva API para establecer conexiones HTTP
de una manera más ordena y con soporte para HTTP 2.0, y aunque todavía
es un API que están en la incubadora, ya podemos apreciar algunas de sus
características.

El soporte para HTTP 2.0 es sin duda lo más relevante del API, porque
mostraremos un ejemplo simple de cómo utilizarlo. No quiero entrar en
detalles acerca de las mejoras de HTTP 2.0 pues en el tema central de este
artículo.

Lo primero que debemos de saber es que esta nueva API no viene como
parte del API Base de Java, por lo que debemos de importarlo como módulo:

El nuevo API de HTTP divide su funcionalidad en 3 principales clases:

 HttpClient: gestiona la creación y el envío de las solicitudes


 HttpRequest: Se utiliza para construir el request para ser enviado por medio
de HttpClient
 HttpResponse: Contiene la respuesta de la petición enviada por HttpClient.

Ahora veamos un pequeño ejemplo de cómo consumir un recurso WEB como


es la página de Google:
En este ejemplo rustico, pero bastante claro, podemos apreciar como
utilizamos el nuevo API para consumir la página de Google. En la línea 10
creamos un cliente HTTP y en la línea 11 imprimimos la versión del cliente,
el cual deberá arrojar “Http version: HTTP_2”. En la línea 14 y 15 creamos
un objeto HttpRequest para consultar la página de google mediante el
método GET. En la línea 19 enviamos el Request mediante la clase HttpClient
y obtenemos un objeto HttpResponse como respuesta.

Hay varias cosas que no podemos abarcar en este artículo, pero cabe
mencionar que el API de HTTP soporta conexiones síncronas y asíncronas
además que permite crear clientes de WebSockets.
TIFF Image I/O
El formato TIFF ha venido tomando fuerza, pues es el formato
predeterminado para el sistema operativo IOS. Pero a pesar de tener mucha
fuerza, la realidad es que hasta la versión 9 de Java se empaqueta como una
solución definitiva.

En las versiones anteriores de Java proporcionaba un conjunto de codecs


para mostrar los formatos de imágenes más populares, como JPG, PNG, GIF,
etc. En versiones de pasadas de Java, era necesario utilizar el paquete
com.sun.media.imageio.plugins.tiff el cual en la versión 9 de Java, es
reempaquetada en javax.imageio.plugins.tiff.

Multi-Resolution Images
Con la llegada de Smartphones, tablets y pantallas de diferentes
resoluciones, se ha complicado la forma en que mostramos las imágenes en
el dispositivo, pues en muchas ocasiones no vemos obligados a
redimensionar las imágenes o crear condiciones que muestren una imagen u
otra, según la resolución de pantalla. Cabe resaltar que esta nueva
funcionalidad no se encarga de redimensionar una imagen, sino que, dado
una serie de imágenes, nos ayuda a seleccionar la que mejor se ve para una
resolución dada.

Con la llegada de Java 9, se agregan una serie de clases de utilidad que nos
ayudarán a seleccionar la imagen más adecuada para una resolución de
pantalla. Las clases son las siguientes:
 MultiResolutionImage: Interface base para todas las imágenes multi

resolución

 AbstractMultiResolutionImage: Clase abstracta que implementa la

funcionalidad base

 BaseMultiResolutionImage: Clase concreta que implementa la funcionalidad

mínima.

No quiero entrar un mucho detalle acerca de las clases, pues nos


alargaríamos demasiado, por lo que me quiero centrar en un ejemplo simple.
Imaginemos que tenemos que mostrar el avatar de nuestro usuario o un
banner publicitario, y según la resolución de pantalla, podemos mostrar una
imagen que se vea mejor. Para este ejemplo, vamos realizar una prueba con
una imagen de 64×64, otra de 128×128 y otra de 256×256. Finalmente le
solicitaremos a la interface MultiResolutionImage que nos de la imagen que
mejor se adecua a la resolución solicitada
En la línea 18 definimos las URL de las 3 imágenes con diferentes
resoluciones. En la línea 25 leemos las imágenes para crear un objeto Image.
En la línea 27 creamos el objeto MultiResolutionImage a partir de las 3
imágenes con diferente resolución. En las líneas 31,32 y 33 solicitamos 3
imágenes, para resoluciones 64, 128 y 256, por lo que la interface
MultiResolutionImage nos deberá retornar la imagen que mejor se ajuste.
Cabe mencionar que las resoluciones no tienen que ser exactas con las
imágenes. Ya que, en este caso, MultiResolutionImage nos arrojara la
resolución que mejor se adapta a la resolución. Veamos cómo se ejecuta este
ejemplo:

Mejoras al API de proceso


Esta es una mejora que ya muchos están esperando, pues al ejecutar un
proceso con java.lang.Process era muy difícil tener un control real de los
procesos del sistema operativo, por ejemplo, obtener el Process ID o PID,
realizar una acción cuando el proceso terminara u obtener los procesos hijos,
entre otras cosas. Para esto, Java 9 ofrece la interface ProcessHandle y su
clase internar ProcessHandle.Info la cual nos da información acerca del
proceso.

Por ejemplo, veamos como iniciar el block de notas y obtener el PID


Esto solo es una pequeña parte de todo el potencial de esta mejora, para ver
más información puedes ver la siguiente liga:
https://www.javaworld.com/article/3176874/java-language/java-9s-other-
new-enhancements-part-3.html

Plattform logging API and Service


Una de las grandes problemáticas al modulizar el JDK era que el Módulo Base
(clases base) no podía depender del Módulo (java.loggin) pues crearía una
referencia circular, lo cual todos sabemos que es una mala práctica, por ello,
se decidió crear un API de loggin integrado al Módulo base (java.lang.Loggin)
el cual sirve primero que nada para desacoplar la dependencia con
java.loggin pero también se utiliza para crear Servicios por módulo.

Otra de las ventajas que ofrece este nuevo API, es que permite registrar
mensajes en el log antes de que todos los módulos estén cargados.

Para ver un ejemplo más concreto, te recomendamos la siguiente liga:


http://javasampleapproach.com/java/java-9/java-9-platform-logging-and-
service

Deprecated Applet API


Debido al declive de los Applets y que los navegadores cada vez soportan
menos las tecnologías que se ejecutan con plugin como Java o Flash, Oracle
ha decidido marcar todo el API de Applets como Deprecated, y un que
siguieran siendo parte del JDK, se advierte que será eliminado
permanentemente del JDK en versiones posteriores, un que todavía no
confirman en cual.
JavaDB eliminado del JDK
A partir de la versión Java 9, la base de datos JavaDB o más bien Apache
Derby, será eliminada definitivamente del JDK, por lo que se podrá descargar
por separado. En las versiones pasadas, se podía encontrar en la carpeta db
del JDK.

VisualVM removido
La herramienta VisualVM que es utilizada analizar la JVM en tiempo de
ejecución fue agregada como parte del JDK en la versión 6 del JDK, pero a
partir de la versión 9 de Java, es removida del JDK y se tendrá que descargar
por separado.

Bibliografía
https://www.genbetadev.com/java-j2ee/el-futuro-y-java-9

http://www.cleformacion.com/-/la-actualizacion-de-java-9-ya-esta-lista-para-su-
lanzamiento

http://www.clubdetecnologia.net/blog/2017/java-9-que-herramientas-soportan-las-
caracteristicas-de-modularidad/

http://centripio.io/java-9-analisis-de-las-novedades/

https://picodotdev.github.io/blog-bitix/2017/09/novedades-de-java-9-mas-alla-de-la-
modularidad/

Anda mungkin juga menyukai