Sabias que el serialVersionUID en las clases Java nos previene de errores en la deserialización

Estoy seguro que todos aquellos que hemos programado en Java en alguna oportunidad hemos visto como nuestro IDE nos arrojaba un warning (advertencia) indicandonos que «la clase serializable nombre_clase no declara un campo serialVersionUID final estatico de tipo long» y más seguro estoy (por experiencia propia) de que sin meditarlo mucho optamos por la opción que nos daba el IDE (eclipse, netbeans o cualquier otro) para que nos resolviera el warning y asi tener nuestro código limpio de mensajes de advertencia y errores.

Ejemplo de mensaje warning de serialVersionUID

¿Qué es serialVersionUID?

Es un número de versión que posee cada clase Serializable, el cual es usado en la deserialización para verificar que el emisor y el receptor de un objeto serializado mantienen una compatibilidad en lo que a serialización se refiere con respecto a la clases que tienen cargadas (el emisor y el receptor).

¿Qué pasa si no declaro un serialVersionUID?

El proceso de serialización asocia cada clase serializable a un serialVersionUID. Si la clase no especifica un serialVersionUID el proceso de serializacion  calculará un serialVersionUID por defecto, basandose en varios aspectos de la clase. Es muy recomendable que se declare un serialVersionUID en las clases serializables, ya que el calculo del serialVersoinUID es muy sensible a detalles de la clase, los cuales pueden variar entre compiladores, es decir, si trabajamos serializando/deserializando objetos y trabajamos con distintos compiladores Java podemos llegar a obtener una InvalidClassException durante el proceso de deserialización debido a discrepancias entre los serialVersionUID calculados por cada compilador. Por eso para garantizar un serialVersionUID que sea indiferente a la implementación del compilador es altamente recomendado declarar un valor explicito del serialVersionUID (de tipo long) y de ser posible que tenga el modificador de acceso private para que afecte unicamente a la clase que lo ha declarado y no a las clases hijas (subclases) que hereden de ella, forzando de alguna manera a cada clase hija a declarar su propio serialVersionUID (Ver imagen abajo).

Ejemplo de herencia de clase Serializable observando warning de serialVersionUID en clase hija

Para mas información no dejen de revisar en la API la interfaz Serializable

Como compilar código Java desde una clase Java

Días atras dandole un vistazo a la Java API, me encontre con una interfaz que no tenia idea que existiera y es la interfaz JavaCompiler. A continuación un ejemplo sencillo de como compilar una clase:

Para el ejemplo anteriormente mostrado, asumimos que hemos codificado una clase y ubicada en c:/Example.java. Como mi idea es demostrar como compilar, le dejo a ustedes la tarea de crear una clase cualquiera, con y sin errores para poder observar la salida de la ejecución de este programa.

Brevemente comento del código.

  • Clase ToolProvider, disponible desde la versión 6, esta clase nos permite obtener proveedores de compiladores.
  • Invocación del método run, método heredado de la interfaz Tool (presente desde la versión 6 de Java), es una interfaz utilizada para invocar programas, y en nuestro caso la utilizamos para la invocación del compilador. Incluso podríamos obtener las versiones soportadas por la herramienta invocando el método getSourceVersions();

La anterior no es la única forma de poder llevar a cabo la compilación, he aquí otro ejemplo, pero en este caso usando métodos propios de la interfaz JavaCompiler.

Esta ultima forma de llevar a cabo la compilación, particularmente es de mi preferencia ya que nos permite mejorar en rendimiento, en el caso de que llevemos a cabo la compilación de un grupo de ficheros (archivos) mientras reutilicemos el gestor de archivos, además de poder pasarle de una forma mas ordenada las opciones de compilación.

NOTA: En este segundo ejemplo también dejo de parte de ustedes la creación del fichero a compilar (C:/Example.java), que en este caso he hecho uso del mismo en ambos ejemplos.

espero les pueda ser de utilidad, incluso podríamos hasta crearnos nuestro propio IDE, donde compilemos y a su vez nos muestre los mensajes de error en caso de haberlos.

 

Sabias que los literales enteros en Java por defecto son compilados como int

Este es el primer post de la nueva categoría que he denominado «Sabias que…», donde les iré contando cosas que me resultan curiosas e interesantes  sin que por eso no dejen de ser algunas veces «triviales», en esta oportunidad les contare algo que algunos puede que desconozcan e incluso puede que llegue a serles útil en el caso de buscar certificarse.

Sin más preámbulos, así como dice el titulo, por defecto todos los literales enteros que declaremos en nuestro programa Java, serán compilados como int (entero). Lo demostrare mediante el siguiente ejemplo, que consistirá de una función que validará el rango de un número entero. Realmente es un ejemplo sencillo pero que cumple con el objetivo del post. A continuación el código.

Si compilan el código mostrado anteriormente, les aparecería el mensaje

Si hacen uso del IDE Eclipse les aparecería el mensaje «The literal 9999999999 of type int is out of range».

Es un error de compilación que se resuelve sencillamente agregando la letra «L», al literal quedando de esta manera 9999999999L.

Como pueden ver es algo muy sencillo, incluso para algunos será trivial pero les aseguro que en una prueba de certificación mas de uno de seguro se equivocaría y diría que el código se compila perfectamente, asumiendo un cast automático.

Si deseas compartir con nosotros eso que te parece interesante y/o curioso, no dudes en hacerlo, así todos aprenderemos.

entrada por linea de comandos con Java

Aquellos que como yo vienen de la vieja escuela Java (por ejemplo java 1.1 o 1.2) recordarán que era algo engorroso la cantidad de lineas de código a escribir para ingresar datos por linea de comandos con Java(hay que comprender que desde un principio Java no estuvo pensado para esto), he aqui un ejemplo

Desde la versión 1.6 de java existe la clase java.io.Console, una clase que nos hace un poco mas intuitivo el manejo (entrada y salida) de datos por linea de comandos, al igual que otros lenguajes como podrían ser C/C++.
Les muestro ahora la clase anterior haciendo uso de la clase Console

Como se puede observar es código es menor e incluso no hay que agregar una parte de código que para mi es engorrosa (en este caso) y son los bloques try, catch, así como tampoco manejar flujos, sino que en cambio se hace todo de una forma mas amigable por medio de la invocación de métodos de la clase Console. Hay una parte del código que seguro les causa un poco de curiosidad y es el ubicado entre las lineas 9-12, y este se debe, ya que hay ocasiones en que la obtención de la consola puede ser null, esto es debido a que las operaciones de consola o linea de comandos no están permitidas, por ejemplo al intentar el programa anterior desde el IDE Eclipse.

Además de los métodos de la clase Console utilizados en el segundo ejemplo, también existen métodos para entrada de password, lo cual deshabilita la impresión (o mostrado) de los valores ingresados por linea de comandos, así como también métodos para salida de datos formateados.

Si no has utilizado antes esta clase, no te preocupes tiene una API muy sencilla.

¿Has hecho alguna aplicación interesante con la clase Console? cuentalo y comparte tu experiencia con nosotros.