Desarrollo de tutoriales de Java

T001: Creando un GUI con JFC/Swing

publicado a la‎(s)‎ 23 sept. 2012 19:24 por Hernan Nina Hanco   [ actualizado el 23 sept. 2012 20:21 ]

Introducción
En la presente entrada, se explica la creación de una Interfaz Gráfica de Usuario utilizando el paquete de clases Swing. Se utiliza las Clases JFrame, JLabel, JTextField, JList, JTable, JButton. Para la creación de aplicaciones se utiliza el IDE Netbeans.

Marco teórico

JFC y Swing
JFC significa Java Foundation Classes, que abarca un conjunto de funcionalidades para la creación de de Interfaces Gráficas de Usuario (GUI) adicionando acabados con excelentes gráficos y proporcionando la capacidad de interacción a las aplicaciones de Java. En la siguiente tabla mostramos las funcionalidades de JFC:

FuncionalidadDescripción
Swing GUI Components Incluye varias cosas como botones, división de paneles, tablas, etc. Muchos de estos componentes son capaces de ordenar, imprimir, poder arrastrar y soltar.
Pluggable Look-and-Feel Support El look and feel de aplicaciones Swing, permite elegir diferentes formas de apariencia o temas, un mismo programa podria utilizar un Java o Windows look and feel. Adicionalmente, la plataforma Java soporta GTK+ look and feel, Esto permite que las aplicaciones de Java puedan ejecutarse en cualquier Sistema Operativo.
Accessibility API Permite acceso a las tecnologías de accesibilidad como los lectores de pantalla o los Braille.
Java 2D API Permite a los desarrolladores incorporar fácilmente gráficos de alta calidad en 2D, texto e imágenes en aplicaciones y applets. Java 2D incluye extensiones de APIs para la generación y envío de resultados de alta calidad a dispositivos de impresión.
Internationalization Permite a los desarrolladores crear aplicaciones que puedan interactuar con los usuarios de todo el mundo en sus propios idiomas y convenciones culturales. Las entradas de datos pueden ser realizadas en diferentes lenguajes como japonés, chino o coreano.

Ejemplos de aplicaciones

Creación y compilación de una aplicación en Swing

package presentacion;

/**
 *
 * @author hernan
 */
import javax.swing.JFrame;
import javax.swing.JLabel;

public class PrincipalIU extends JFrame {

    /**
     * Crea y muestra el GUI. es preferente mostrar la GUI
     * dentro dentro de un hilo.
     */
    private static void crearYMostrarGUI() {
        //Crear y modificar una ventana.
        JFrame frame = new JFrame("HolaMundoSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Adicionar y localizar una etiqueta "Hello World".
        JLabel label = new JLabel("Hello World");
        frame.getContentPane().add(label);

        //Mostrar la ventana.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //planificar el trabajo para disparar un evento en un hilo:
        //creando y mostrando la aplicación GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                crearYMostrarGUI();
            }
        });
    }
}


Conclusiones

T002: Java DataBase Connectivity - JDBC

publicado a la‎(s)‎ 23 sept. 2012 18:48 por Hernan Nina Hanco   [ actualizado el 16 oct. 2012 19:02 ]

Introducción
En la presente entrada proporcionamos una ilustración de la gestión de la persistencia de datos en una aplicación de Java utilizando un Sistema de Gestión de Base de Datos. El API JDBC permite la conectividad de las aplicaciones Java y un especifico Sistemas de Gestión de Bases de Datos. Para las demostraciones practicas se utilizara el gestor de bases de datos PostgreSQL.  

Marco teórico


Ejemplos de aplicaciones



Conclusiones

T004: Tipos Genéricos y Java Framework Collections

publicado a la‎(s)‎ 22 may. 2012 15:22 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 11:03 ]

I) Objetivo

  • Conocer el uso de Tipos Genéricos y Java Framework Collections.


II) Marco conceptual


Generics Type

Permite que un objeto pueda usarse uniformemente como parámetro en distintos contextos o situaciones. Las clases genéricas o paramétricas permiten definir clases que no se quiere o puede especificar completamente hasta determinar un tipo de dato. En estas clases el tipo concreto de datos que manipulan se especifica como un parámetro en el momento en que se crean los objetos de la clase.

Los tipos genéricos tratan de abstraernos de algún detalle y permitirnos trabajar a un mayor nivel de abstracción.


Comparable en Java

Comparable es una interfaz que sólo contiene un método: compareTo, que nos sirve para ordenar los valores según un orden natural, bien sea numérico o alfabético. El método compareTo devuelve un int, que puede ser 1, -1 o 0.


Iterator


Los objetos de tipo iterator permiten recorrer colecciones. Disponen de un conjunto de métodos que permiten avanzar sobre la colección y obtener los objetos de ésta durante un recorrido para su tratamiento.


El framework de Collections

El framework de Collections fue incorporado a Java en la versión 1.2 por el arquitecto Joshua Bloch, uno de los principales gurús de Java. En Java 5 este framework sufrió una revisión bastante fuerte, el último trabajo que Bloch realizó en Sun Microsystems antes de irse a trabajar para Google, que consiste en soportar tipos de datos genéricos. Este framework se construye sobre las seis interfaces que, junto con sus relaciones jerárquicas, se muestran en la siguiente figura.

Collection

Se trata de una de las dos clases raíz de la jerarquía. Representa cualquier colección de objetos que pertenezcan a un mismo tipo, y proporciona operaciones para añadir y eliminar objetos de la colección, recorrer la colección, conocer el tamaño de la colección, etcétera.


Interfaz List

Esta interfaz representa una colección de datos ordenada en la cual se admiten datos duplicados y sobre la cual el usuario tiene control respecto a en qué posición de la lista se encuentra cada elemento. Podríamos pensar en este contenedor como en una lista doblemente enlazada, donde cada elemento tiene un elemento anterior y un elemento siguiente y donde, por tanto, la posición de cada elemento dentro de la lista está bien definida. Para dar soporte a las operaciones que permiten añadir un elemento en una posición determinada de la lista, borrar un elemento que se encuentre en una posición determinada, añadir una colección de elementos después de una posición determinada.

Las dos implementaciones más comunes de la interfaz List son ArrayList y LinkedList


La interfaz Set


La interfaz Set no añade ningún método respecto a la interfaz Collection, pero se usa para representar conjuntos de elementos que no admiten duplicados. Por tanto, un Set necesita conocer si los objetos que contiene son o no iguales entre sí. Existen dos implementaciones principales de esta interfaz: HashSet y TreeSet


Map en Java


Un mapa es una estructura de Java que nos permite almacenar pares clave/valor. De tal manera que para una clave solamente tenemos un valor. Si añadimos un nuevo elemento clave/valor cuando la clave ya existe, se sobrescribe el valor almacenado anteriormente. La estructura a listar que utilizamos como mapa es un HashMap. Lo primero que tenemos que hacer es crear el mapa y añadirle elementos:

Map<String,String> hm = new HashMap<String,String>();

hm.put("1","Luis");
hm.put("2","Amaya");
hm.put("3","Julio");

Si intentamos añadir otro elemento con una clave ya existente, sobreescribe el valor. Ya que no puede haber elementos duplicados. 

Para recorrerlo nos apoyaremos sobre un Iterator que será el puntero encargado en recorrer los elementos del mapa. Obtendremos un iterador sobre la estructura invocando los métodos .entrySet() e .iterator(). Usar iteradores permite separar la lógica de la clase de la lógica de la iteración. Los iteradores tienen un comportamiento similar a los enumerados. Para mover el iterador utilizaremos el método .next() y si queremos comprobar que el iterador ha llegado al final de la estructura tenemos el método .hasNext()

Iterator it = hm.entrySet().iterator();
while (it.hasNext()) { 
    Map.Entry e = (Map.Entry)it.next();
    System.out.println(e.getKey() + " " + e.getValue());
}

De la estructura recuperaremos los valores mediante .getKey(), para la clave y .getValue(), para el valor.

III) Prácticas

1) Ejemplo de Tipos Genéricos o polimorfismo parametrizado

En el presente programa la clase "Concatenador" utiliza un tipo genérico identificado con "E" y encerrado entre el signo "<>" después del nombre de la clase. Esto da la posibilidad de declarar "dato1" y "dato2" del tipo genérico "E". Esto significa mas adelante cuando se invoque objetos de la clase "Concatenar" podemos reemplazar el tipo genérico "E" por cualquier tipo de datos concreto (Ejem. Integer, Float, Persona, etc.).

package miselania.tiposgenericos;

/**
*
* @author hernan
*/
public class Concatenador<E> {
   private E dato1;
   private E dato2;
   public String toString() {
       return "El primer dato es: " + getDato1()
               + " y el segundo es: " + getDato2();
   }

   public E getDato1() {
       return dato1;
   }

   public void setDato1(E dato1) {
       this.dato1 = dato1;
   }

   public E getDato2() {
       return dato2;
   }
   public void setDato2(E dato2) {
       this.dato2 = dato2;
   }
}



package miselania.tiposgenericos;

/**
*
* @author hernan
*/
public class PruebaTiposGenericos {
   public static void main(String[] args) {
       Concatenador concatenador1 = new Concatenador();
       concatenador1.setDato1(42.35F);
       concatenador1.setDato2(2.365F);
       Concatenador concatenador2 = new Concatenador();
       concatenador2.setDato1("Hola");
       concatenador2.setDato2("Adiós");
       Concatenador concatenador3 = new Concatenador();
       concatenador3.setDato1(23);
       concatenador3.setDato2(246);
       System.out.print(concatenador1 + "\n" + concatenador2
               + "\n" + concatenador3);
   }
}

En el programa anterior podemos observar que Concatenar funciona para diferentes tipos de datos concretos como es un Float, String y Integer, cada uno de estos utilizan a "E".

2) Ejemplo de interfaz Comparable

La implementación significa que objetos de la clase Persona pueden ser comparados cuando estos pertenezcan a una colección de objetos, y se podrá obtener ordenamiento automático de los elementos de dicha colección.
Para hacer que los objetos de una clase sean comparables solo se debe implementar la Interfaz Comparable como se muestra en la implementación siguiente. Además el método abstracto implementado "compareTo" define que atributo toma en cuenta para la ordenación, en este caso se ha tomado el atributo nombre de persona, de esa misma manera se procede con los valores alfabéticos. Si los atributos fuesen números entonces se hace una diferencia. recuerda si el resultado es -1, 0 y 1 tiene significado. 
package miselania.tiposgenericos;

/**
*
* @author hernan
*/
public class Persona implements Comparable<Persona> {

   private String nombre;

   public Persona(String nombre) {
       super();
       this.nombre = nombre;
   }
   

   public String getNombre() {
       return nombre;
   }

   public void setNombre(String nombre) {
       this.nombre = nombre;
   }

   @Override
   public int compareTo(Persona o) {
       return nombre.compareTo(o.nombre);
   }
   @Overrideción
   public String toString()
   {
       return "Nombre:"+this.nombre;
   }
}

package miselania.tiposgenericos;

import java.util.Set;
import java.util.TreeSet;

/**
*
* @author hernan
*/
public class PruebaComparable {
   public static void main(String[] args)
   {
      Set <Persona> lista = new TreeSet<Persona>();
      lista.add(new Persona("Juan"));
      lista.add(new Persona("Alberto"));
      lista.add(new Persona("Ivan"));
      lista.add(new Persona("Angel"));
      
      System.out.println(lista);
   }
   
}
El resultado de la ejecución de la prueba es una lista de objetos ordenados alfabéticamente por el nombre, como se muestra enseguida.
run:
[Nombre:Alberto, Nombre:Angel, Nombre:Ivan, Nombre:Juan]
BUILD SUCCESSFUL (total time: 1 second)
 

IV) Tarea

1) Modificar el programa para ordenas los elementos en forma descendente utilizando la interface Comparable.

2) Utilizando la interfaz comparable y en base al programa de la práctica, hacer que los elementos se ordenen en base a la edad de una persona. Añadir el atributo edad a la clase Persona.

3) Implementar una lista enlazada utilizando tipos genéricos.

4) Utilizar la clase Persona que implementa la interface Comparable con una lista LinkedList como la colección de objetos.

5) Modificar la tarea 3 para que la lista enlazada de tipos genéricos implemente la Interface Iterator.

6) Utilice la interfaz Map para crear un diccionario de palabras.


V) Referencias

  • Beginning Java 2 JDK 1.5 Edition, Ivor Horton´s

T003: Serialización de Objetos para persistencia en Java

publicado a la‎(s)‎ 14 may. 2012 11:34 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 11:00 ]

I) Objetivo

  • Conocer la Serialización de objetos como técnica de persistencia de datos..


II) Marco conceptual


Almacenar objetos en un Archivo

La serialización consiste en convertir un objeto en una secuencia de bytes para guardarlo en un archivo o enviarlo por la red, y luego reconstruirlo, con los valores que tenía al ser serializado, para su posterior utilización. La serialización es muy utilizada en las bases de datos relacionales, pero tiene también otras aplicaciones. En Java, esta capacidad de serialización, es decir, de guardar información sobre un objeto para luego recuperarla, se llama persistencia.


Para que un objeto sea serializable basta con que la clase a la que pertenezca, o una superclase de ésta, implemente la interfaz Serializable o su subinterfaz Externalizable, ambas en el paquete java.io.


Implementar Serializable es muy sencillo, porque no tiene métodos. En realidad actúa como un marcador que indica que los objetos de una clase (o de sus subclases) son serializables, de esta manera:


class MiClase implements Serializable


Para utilizar correctamente Serializable, hay que tener en cuenta algunos detalles.

  • Primero, lo que estamos serializando son objetos y sus campos, así que las variables marcadas como static, es decir, que pertenecen a la clase y no al objeto, no pueden ser serializadas.
  • Segundo, supongamos que queremos serializar un objeto que contiene una referencia a una instancia de una clase que no es serializable. Esto produciría la ya conocida NotSerializableException. Para evitarlo, debemos marcar esa instancia como transient. Todos los campos marcados como transient serán ignorados por la JVM en el proceso de serialización.

Veamos todo esto con un ejemplo:


public class MiClase implements Serializable{

     private int variable1;

     private static double variable2;

     private transient OtraClase oc = new OtraClase();

}

class OtraClase{} //OtraClase no es serializable


Cuando un objeto de la clase MiClase sea serializado, sólo su variable "variable1" será serializada. La variable "variable2" no, porque es static y por tanto pertenece a la clase y no al objeto, y la variable oc tampoco porque está marcada transient. Si no añadiéramos el modificador transient tendríamos una NotSerializableException, pero también podemos utilizarlo cuando no nos interese serializar algo.


III) Practicas


1) Ejemplo de serialización y recuperación de objetos.

Implementar una Clase Agenda Serializable

package demo;

/**
 *
 * @author hernan
 */
import java.io.*;
class Agenda implements Serializable {

    private String nombre;
    private String p_Apellido;
    private String s_Apellido;
    /*getters y setters*/

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getP_Apellido() {
        return p_Apellido;
    }

    public void setP_Apellido(String p_Apellido) {
        this.p_Apellido = p_Apellido;
    }

    public String getS_Apellido() {
        return s_Apellido;
    }

    public void setS_Apellido(String s_Apellido) {
        this.s_Apellido = s_Apellido;
    }

    
    public Agenda(String nombre, String p_Apellido, 
            String s_Apellido) {
        super();
        this.nombre = nombre;
        this.p_Apellido = p_Apellido;
        this.s_Apellido = s_Apellido;
    }

    @Override
    public String toString() {
        return (getNombre() + " " + 
                getP_Apellido() + " " + getS_Apellido());
    }
}


Implementar una clase para Serializar objetos de la clase Agenda


package demo;

import java.io.*;

/**

 *

 * @author hernan

 */

public class Serializacion {


    public static void main(String[] args) {

        // Crear objetos de clase Agenda

        Agenda a1 = new Agenda("Ana1", "Martínez1", "Fernández1");

        Agenda a2 = new Agenda("Ernesto", "García", "Pérez");

        // iniciar el proceso de serialización

        // colocar los objetos a1 y a2 en disco

        try {

            //Creamos el archivo

            FileOutputStream fs =

                    new FileOutputStream("agenda1.ser");

            //Esta clase tiene el método writeObject() que necesitamos

            ObjectOutputStream os =

                    new ObjectOutputStream(fs);


            //El método writeObject() serializa el objeto 

            //y lo escribe en el archivo         

            os.writeObject(a1);

            os.writeObject(a2);

            //Hay que cerrar siempre el archivo

            os.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

        System.out.println(

                "Los Objetos se han serializado correctamente.");

    }

}


Implementar una clase para desealizar objetos de la clase Agenda.

package demo;

import java.io.*;
/**
 *
 * @author hernan
 */
public class Deserealizacion {

    public static void main(String[] args) {
        Agenda a1 = null;
        Agenda a2 = null;
        try {
            // abrir o Recuperar un archivo de disco
            FileInputStream fis = 
                    new FileInputStream("agenda1.ser");
            // Stream para recuperar o reconstruir objetos
            ObjectInputStream ois = 
                    new ObjectInputStream(fis);
            //El método readObject() recupera el objeto
            a1 = (Agenda) ois.readObject();
            a2 = (Agenda) ois.readObject();
            ois.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        System.out.println(a1);
        System.out.println(a2);

    }
}

2)
Ejemplo práctico utilizando el modificador transient y reescribir los métodos writeObject y readObject

import java.io.*;

import java.util.*;


public class TestSer{

  public static void main(String[] args) throws Exception{

     FileOutputStream fos = new FileOutputStream("test.ser");

     ObjectOutputStream os = new ObjectOutputStream(fos);

     Prueba p = new Prueba(358);

     os.writeObject(p);

     os.close();

     FileInputStream fis = new FileInputStream("test.ser");

     ObjectInputStream is = new ObjectInputStream(fis);

     p = (Prueba) is.readObject();

     System.out.println("Datos: " + p.getDatos());

     System.out.println("Hora actual: " + p.getHoraActual());

     is.close();

  }

}

class Prueba implements Serializable{

  private static final long seriaVersionUID = 3L; //

  private transient int datos; //son transient pero necesitamos serializarlos

 private transient Date horaActual;//lo queremos sólo en el servidor receptor

  public Prueba(int datos){

     this.datos = datos;

     this.horaActual = new Date();

  }

  private void writeObject(ObjectOutputStream os){

     try{

        os.defaultWriteObject(); //el método por defecto

        /*ahora escribimos lo que queremos que haga*/

        os.writeInt(datos);

        System.out.println("Serialización");

     }catch(IOException e){

        e.printStackTrace();

     }

  }

  private void readObject(ObjectInputStream is){

     try{

        is.defaultReadObject();

        datos = is.readInt();

        horaActual = new Date();

        System.out.println("Recuperación");

     }catch(IOException e){

        e.printStackTrace();

     }catch(ClassNotFoundException e){

        e.printStackTrace();

     }

  }

  public int getDatos(){

     return datos;

  }

  public Date getHoraActual(){

     return horaActual;

  }

}


IV) Tarea

1) Probar la serialización con clases que tienen atributos transient y static. Interpretar los resultados.

2) Defina una clase Persona para encapsular el nombre de una persona y su dirección. El nombre y la dirección debe ser del Tipo Nombre y Tipo de Dirección. Escriba un programa que permite que los nombres y direcciones que deben introducirse desde el teclado, se almacenen como objetos de Persona en un archivo. Una vez que el archivo existe se añaden nuevas entradas al archivo.

3) Extender el programa anterior para listar las personas del archivo.

 

V) Referencias



1-4 of 4