domingo, 28 de junio de 2015

¿Cómo crear nuestras propias excepciones en Java?

Podemos crear nuestras propias extensiones debido a que es posible heredar de la clase Exception, que a su vez contiene todas las excepciones.

Primero, revisaremos la jerarquía de esta clase y luego iremos con un ejemplo.

Es común haber notado excepciones del tipo RuntimeException en nuestros programas. Además hay que recordar que es posible arrojar la excepción o tratarla allí mismo. Si la vamos a arrojar quiere decir que algún otro método va a tratar la excepción. Por ejemplo:
Esto quiere decir que las excepciones no serán tratadas en la clase principal, si no que serán arrojadas al método donde se dio la excepción.

A veces resulta más conveniente tratar las excepciones, dentro de la clase donde se originan. Para esto se utiliza los operadores try & catch.

Para el ejemplo haremos uso del try-catch, con una excepción propia.
Se tiene un conjunto de figuras y se quiere imprimir la lista de ellas pero solo aquellas cuyo perímetro esté dentro de un rango establecido por el usuario. Entonces se solicita el rango es decir el perímetro mínimo y el perímetro máximo. Nuestro programa puede dejar de funcionar si el perímetro mínimo es mayor que el perímetro máximo, y es un tipo de excepción particular. Por lo cual crearemos nuestra propia excepción llamama ExcepcionFiltroPerimetro.

Interfaces en Java

Las interfaces en Java
Supongamos que tenemos un conjunto de clases y necesitamos que hereden de JFrame, pero además necesitamos que herede de otra clase de la cual solo necesitamos sus métodos, es decir de una clase abstracta. Java no permite realizar esta acción debido a que no soporta herencia múltiple. Existe un artificio para la herencia múltiple que se denomina: implementar interfaces.

No necesariamente se aplica una interface como artificio para la herencia múltiple, cuando solo se tiene métodos comunes, constantes comunes entonces se habla de una interface.

Una interface es como un protocolo: todas las clases deben implementar todos los métodos abstractos de la interface.

Generalmente, nombres como: comparable, medible, ordenable, etc se asocian directamente a una interface.

Para hacer uso de una interface luego del nombre de la clase se escribe la palabra implements seguido del nombre de la interface. En herencia se maneja extends en interfaces implements.

Cabe mencionar que existen interfaces predeterminadas por java como por ejemplo: clonable, comparable, seriable, etc.

Ejemplo:

Se tiene 2 clases: Estudiante y Curso. La idea es gestionar a los Estudiantes mediante Curso. Luego ordenar los objetos Estudiante contenidos en un ArrayList creado en Curso. Al final implementar una interface (Comparable) predeterminado por Java, para ordenar los elementos del ArrayList de acuerdo a algún parámetro deseado.

La clase estudiante implementa la interface Comparable. Al momento de implementar esta clase, es obligación implementar el único método abstracto de esta clase: toCompare.
Entonces, se implementa el método toCompare y se lo sobreescribe:
Para la sobrescritura, dependiendo del tipo de parámetro se retorna un entero que devuelve un entero -1 en caso de que el Objeto comparado sea "menor" que alguno de los demás objetos.

La sobrescritura de este método nos sirve para la utilización dentro de la misma clase. Pero si nos fijamos todos los Estudiantes están en un ArrayList dentro de la clase curso.

Debe ser desde esta clase que se de el ordenamiento debido a que contiene la información de todos los estudiantes ingresados. Entonces como ordenar desde la clase Curso?

La clase Collections que hereda directamente de Object (es decir no necesitamos importarla para usarla) tiene un método llamado sort, que hereda de directamente de la interface comparable, tal como lo muestra el API de java:

Entonces, creamos un método llamado ordenarPorEdad en la clase Curso que contiene lo siguiente:

Esto hará que los Estudiantes dentro de listaEstudiantes se ordenen por edad, en orden ascendente de acuerdo al ordenamiento natural.

Por último se muestra la clase principal en la cual se crea los archivos y se hace el ordenamiento respectivo. Se comprueba por pantalla.


La salida por consola:

LA INTERFAZ CLONEABLE
Esta interfaz permite realizar una copia exacta de un objeto, es decir cada campo tendrá el mismo contenido para el objeto original y el objeto clonado. Cabe recalcar que algunas referencias indican que no es muy recomendado utilizar esta interfaz ya que pueden existir subclases que necesiten implementar su propia lógica clonable, y al momento de heredar de una clase que implemente Clonable y tenga sobrescrito el método clone de cierta forma, puede ser que para la clase hija no sea tan conveniente. Más información de porqué muchos programadores utilizan el constructor de copia en vez de la interface clonable aquí: http://stackoverflow.com/questions/4081858/about-java-cloneable

Como sea, voy a mostrar un ejemplo de como implementar está clase. Qué a diferencia de la interfaz Comparable es más simple.


En la clase Estudiante se debe asegurarse 2 cosas:
1) Que se implemente la interfaz Comparable
2) Sobrescribir el método clone

La excepción CloneNotSupportedException solo se da cuando la clase no implementa la interfaz Clonable.

Algo ha tomar en cuenta es que si se aplica herencia, este método nos devuelve un objeto de tipo estudiante, es decir es necesario hacer un casting al tipo de la clase hija.

En el main, tendríamos algo así:

Y la salida por pantalla:


Por si fuera necesario, también dejo un ejemplo de un constructor de copia, que es más recomendado.

Serialización de Objetos en Java

SERIALIZACIÓN DE OBJETOS EN JAVA
De manera muy sencilla, es posible escribir información de un objeto Java en un archivo para evitar perder la información luego de que se cierre el programa Java, es decir tener persistencia en Java. Es muy básicamente una forma de evitar solo trabajar en tiempo de ejecución y ampliar el alcance de nuestro programa cada vez que se vuelva a iniciar el programa. Existen maneras de escribir sobre un archivo de tal manera que la información se escriba en forma de caracteres. Es decir los atributos de cada objeto pueden estar almacenados en un archivo en forma de caracteres. Supongamos que tenemos una clase Paciente con los atributos: nombre(String), no. documento(String) y género(char). Entonces es posible enviar como caracteres, la información de cada campo hacia un archivo pudiendo obtener un archivo así:


Este método funciona como un registro de datos, pero al momento de querer obtener este registro y almacenarlo como un objeto necesitamos obtener cada campo de cada línea, hacer casting para cada valor (porque hay que recordar que los vamos a obtener como caracteres) y luego setearlos de nuevo en el objeto. Este ejemplo puede no presentar muchos problemas, pero que sucede si tenemos muchos atributos, eso implicaría líneas de código y redundancia. Más bien este método mostrado, sirve para enviar datos listos para su impresión. 

La serialización de Objetos, permite enviar datos en forma de bytes, de tal manera que cada archivo contendrá toda la información del objeto, es decir incluye que librerias ha importado, paquetes, herencia, etc. Pero principalmente contiene el tipo de datos de cada atributo lo que simplificaría mucho las cosas. Es decir, el mecanismo de serialización realiza copias exactas de los objetos.

Para el envío de objetos nos apoyamos en las clases ObjectInputStream y ObjectOutputStream, permirten leer y enviar objetos respectivamente. El constructor de estas dos clases espera recibir como argumento de entrada un objeto flujo(Output/InputStream) que pueden escribir o enviar información.
Este mecanismo sirve como envoltura, por ejemplo para archivos: para envolver un objeto FileInputStream en un objeto ObjectInputStream, se pasa el objeto FileInputStream al constructor de ObjectInputStream, así:
ObjectInputStream entrada = ObjectInputStream(new (FileInputStream archivo)) ;  
donde archivo es de tipo File.

O para el constructor de ObjectOutputStream:
ObjectOutputStream entrada = ObjectOutputStream(new (FileOutputStream archivo)) ;   donde archivo es de tipo File.

A continuación se muestra un ejemplo:
Se tiene la clase paciente con 4 atributos:


Como es de notarse, el envío de datos mediante flujo de caracteres se complica aquí por la presencia del atributo Calendar fechaNacimiento, además de lo nombrado al inicio de este post. 

Para poder serializar primeramente la clase debe implementar la interface Serializable, que no requiere implementar ningún método. Además si queremos que uno de los atributos no se serialize, entonces añadimos la palabra transient.

En la clase principal:



El archivo de texto no mostrará nada debido a que lo que se envía es bytes y para ver esa información se necesitará un editor diferente. Pero una buena forma de comprobar de que si se está enviando información, es chequeando el tamaño del archivo, que se modificará luego de enviar información.

Una vez que la información está almacenada en el archivo se la leerá y luego se la almacenará en un nuevo ArrayList de Pacientes. Para realizar esta opción necesitaremos de un objeto del tipo ObjectInputStream:

miércoles, 8 de abril de 2015

MANUAL DE USUARIO acerca de cómo COMPILAR un programa en JAVA utilizando CMD (Windows) y BASH (Linux)

CMD
Para compilar un programa escrito en lenguaje Java en Windows desde el símbolo del sistema primero es necesario descargar el Java Development Kit (JDK) debido a que se necesita un compilador y dentro del paquete JDK entre otras cosas viene javac.exe que es el compilador de java.
El JDK se lo puede descargar directamente desde la página oficial de oracle: Oracle-descargas

Una vez instalado el JDK, para que se pueda compilar desde el símbolo del sistema se debe agregar la dirección donde se instaló el JDK al path en variables de entorno, así:

1. En propiedades del equipo,
2. Luego en configuración avanzada del sistema,

 3. Luego en Variables de entorno...,

 4. Seleccionamos la variable Path del sistema y le damos a Editar,
 5. Buscamos la ruta donde instalamos el JDK y entramos en la carpeta bin,
 6. Copiamos la ruta anterior y la agregamos al final del texto escrito en 'Valor de la variable' entre punto y coma.
7. Abrimos el CMD y escribimos javac y damos enter. El comando debe ejecutarse.
 8. Creamos un archivo en Bloc de Notas con sentencias en lenguaje Java, y lo guardamos tomando en cuenta que algunas cosas podrían dar error, por ejemplo: Se debe comenzar con la palabra public antes de class. . Si escribimos "class Hola" entonces el archivo se llamará Hola.java. Hay que tener en cuenta que .java es la extensión del archivo. Si Bloc de Notas evita que se cree con esta extensión y por defecto pone la extensión txt (Ejemplo.java.txt) sin que nos demos cuenta, deberemos revisar en las propiedades del archivo. En caso de suceder esto, se debe marcar la casilla "Extensiones de nombre de archivo" ubicada en la pestaña Vista de la cinta de opciones en el explorador y luego modificar la extensión manualmente.


9. Guardamos el archivo .java y respetando la ruta donde se lo guardó en el CMD, ejecutar el comando "javac Ejemplo.java" para cargar las clases contenidas allí. Luego ejecutar el comando "java Ejemplo" para compilar. 

Tomado de: Referencia
Para aprender a cambiarse de directorio en CMD: Referencia1
Para cambiar las extensiones de un archivo, de: Referencia2

Nota: En el caso de querer ejecutar un código java que dentro de su estructura tenga referencia de un paquete(package) entonces la ejecución se la debe hacer de la siguiente manera:
Una vez creado nuestro archivo .java que contenga de inicio la referencia de un paquete (en este caso package javaapplication1;) o de subreferencia,


Entonces se procede a generar el .class como se hizo anteriormente(con el comando javac):


Recordando que package hace que el archivo .java se guarde dentro de una carpeta que contenga el nombre del paquete lo que primero hacemos es eso, colocar el .java dentro de una carpeta con el nombre, en este caso, javaapplication1 (nombre del package),, en este caso como ya se generó el .CLASS entonces también se deberá llevar ese archivo a dicha ruta, así:



Luego ya en el cmd, desde la ruta padre a la del paquete (en este caso el Desktop) se ejecuta el comando:  java javaapplication1.JavaApplication1



*Los 2 números del final son para este programa de java en particular y son aleatorios, ya que si revisan el código verán que se solicita dos argumentos de entrada. Estos números son de tipo String. En un programa que no solicite argumentos de entrada, estos 'strings' son innecesarios.

** Como el programa este dentro de un package, se debe ejecutar desde la ruta padre, y si el programa tiene subpackage de igual manera, así:
Desde la ruta padre al package de "último nivel":  java subpackage.package.nombredelaclaseprincipal
*nombredelaclaseprincipal es sin .java y tampoco sin .CLASS, esto se debe hacer una vez generado el .CLASS con el javac.





BASH
 Antes que nada accedemos a la página de Oracle y descargamos el JDK para Linux:
 El proceso es parecido a Windows. En linux extraemos el contenido descargado y añadimos esa ruta al PATH, mediante el comando export:
 Comprobamos que el comando "javac" funcione.Y procedemos a escribir un archivo de texto de extensión .java
 Luego tomando en cuenta la ruta de creación del archivo .java ejecutamos el comando "javac Ejemplo.java". Ejemplo.java es el nombre del archivo contenedor del código. Una vez cargadas las clases de Ejemplo.java, interpretamos las clases mediante el comando "java Ejemplobash"
Netgrafía: Referencia