martes, 17 de noviembre de 2015

ARCHIVOS

Los programas usan variables para almacenar información: los datos de entrada, los resultados calculados y valores intermedios generados a lo largo del cálculo. Toda esta información es efímera: cuando acaba el programa, todo desaparece. Pero, para muchas aplicaciones, es importante poder almacenar datos de manera permanente.

Cuando se desea guardar información más allá del tiempo de ejecución de un programa lo habitual es organizar esa información en uno o varios ficheros almacenados en algún soporte de almacenamiento persistente. Otras posibilidades como el uso de bases de datos utilizan archivos como soporte para el almacenamiento de la información.

Antes de proceder al estudio de las clases que describen la lectura y escritura veamos la clase File:

LA CLASE FILE: Proporciona información acerca de los archivos, de sus atributos, de los directorios,etc. Se usa para crear un archivo.

Los archivos también son llamados ficheros y existen de dos tipos:

ARCHIVO DE TEXTO

Los archivos de texto plano son aquellos que están compuestos únicamente por texto sin formato,solo caracteres. estos caracteres se pueden codificar de distintos modos dependiendo de la lengua usada. Se les conoce también como archivos de texto llano o texto simple por carecer de información destinada a generar formatos y tipos de letra.

Lectura/Escritura

Los pasos para leer y escribir en disco son los siguientes:
  1. Para escribir: Se crean dos objetos de las clases FileReader y FileWriter, llamando a los respectivos constructores a los que se les pasa los nombres de los archivos o bien, objetos de la clase File, respectivamente.
  2. Para leer: Se realiza mediante read los caracteres del flujo de entrada, hasta llegar al final(la función final devuelve entonces -1, y se escribe dichos caracteres en el flujo de salida mediante write.
IMPORTANTE: Deben cerrarse los flujos de lectura y escritura llamando a sus respectivas funciones close() en bloques try...catch.


package blogger;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

public class Archivo_de_texto {
    private File f;
    
    public void crearArchivo(){
        try {
            
            f = new File ("Archivos/archivo_plano.txt");
            
            if(!f.exists()){
                f.createNewFile();
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }      
    }
    
    public void escribirArchivo(){
        try {
            FileWriter fw = new FileWriter(f);
            fw.write("Mi primer archivo plano");
            fw.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
   
    }
    public void leerArchivo (){
        try {
            FileReader fr = new FileReader(f);
            BufferedReader br = new BufferedReader(fr);
            String linea = null;
            while ((linea=br.readLine()) != null) {                
                System.out.println(linea);
            }
            br.close();
            fr.close();
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}



ARCHIVO BINARIO

Un archivo binario es una archivo informático que contiene información de cualquier tipo,codificada en forma binaria para el propósito de almacenamiento y procesamiento de ordenadores.

Lectura/Eescritura

  1. Para escribir: Creamos un flujo de salida de disco, pasándole el nombre del archivo en disco un objeto de la clase File.
FileOutputStream fos = new FileOutputStream("media.obj");

El flujo de salida ObjectOutputStream es el que procesa los datos y se ha de vincular a un objeto fos de la clase FileOutputStream.

ObjectOutputStream oos= = new ObjectOutputStream(fos);

     2.Para leer: Creamos un flujo de salida de disco, pasándole el nombre del archivo en disco un objeto de la clase File.

FileInputStream fis = new FileInputStream("media.obj");

El flujo de entrada ObjectOutputStream es el que procesa los datos y se ha de vincular a un objeto fis de la clase FileInputStream.:

ObjectInputStream ois= = new ObjectInputStream(fis);

IMPORTANTE: Deben cerrarse los flujos de lectura y escritura llamando a sus respectivas funciones close() en bloques try...catch y las clases involucradas deben SERIALIZARSE.

Ejemplo: Crearemos un archivo binario que contenga un ArrayList de estudiantes:



package blogger;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public class Archivo_Binario {
    private File f;
    
    public void crearArchivoBinario(){
            try {
                f= new File("Archivos/archivo_binario.txt");
               if(!f.exists()){
                f.createNewFile();
            }
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
    }    
    
    public void escribir_ArchivoBinario(){
        try {
            List  estudiantes = new ArrayList ();
            Estudiante e1 = new Estudiante("Jorge", "75426598", 18, "1234567", "Sistemas");
            Estudiante e2 = new Estudiante("Martha", "7757856", 16, "1745863", "Zootecnia");
            Estudiante e3 = new Estudiante("Martin", "7786626", 22, "1234567", "Ambiental");
           
            estudiantes.add(e1);
            estudiantes.add(e2);
            estudiantes.add(e3);
            
            FileOutputStream fos = new FileOutputStream(f);
            ObjectOutputStream oos= new ObjectOutputStream(fos);
            oos.writeObject(estudiantes);
            oos.close();
            fos.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
    
    public void leerArchivoBinario(){
        try {
            FileInputStream fis = new FileInputStream(f);
            ObjectInputStream ois = new ObjectInputStream(fis);
            ois.close();
            fis.close();
            
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

jueves, 12 de noviembre de 2015

MANEJO DE EXCEPCIONES EN JAVA

La palabra excepción indica una irregularidad en el software que se inicia en alguna sentencia del código al encontrar una condición anormal; no se debe confundir con una excepción hardware. Una excepción es un error de programa que sucede durante la ejecución; si al ocurrir está activo un segmento de código denominado manejador de excepción, entonces el flujo de control se transfiere al manejador; si no existe un manejador para la excepción, ésta se propaga al método que invoca, si en este tampoco se capta, la excepción se propaga al que a su vez le llamó; si llega al método por el que empieza la ejecución, es decir, main() y tampoco es captada, la ejecución termina.
En general, el mecanismo de excepciones en Java permite:
a) Detectar errores con posibilidad amplia de recuperación.
b) Limpiar errores no manejados.
c) Evitar la propagación sistemática de errores en una cadena de llamadas dinámicas.
Mecanismo del manejo de excepciones en Java
El modelo de un mecanismo de excepciones consta fundamentalmente de cinco nuevas palabras reservadas: try, throw, throws, catch y finally.
1.      Try es un bloque para detectar excepciones.
2.   Catch es un manejador para capturar excepciones de los bloques try,
3.   Throw es una expresión para levantar (raise) excepciones,
4.   Throws indica las excepciones que puede elevar un método,
5.   Finally es un bloque opcional situado después de los catch de un try.
Los pasos del modelo son:
1. Establecer un conjunto de operaciones para anticipar errores; esto se realiza en un bloque try.
2. Cuando una rutina encuentra un error, lanzar una excepción; el lanzamiento (throwing) es el acto de levantar una excepción.
3. Para propósitos de limpieza o recuperación, anticipar el error y capturar (catch) la excepción lanzada.
El mecanismo de excepciones se completa con:
Un bloque finally que, si se especifica, siempre se ejecuta al final de un try;

Especificaciones de excepciones que dictamina cuáles, si existen, puede lanzar un método.
Bloques try
Ya se mencionó que un bloque try encierra las sentencias que pueden lanzar excepciones y que comienza con la palabra reservada try seguida por una secuencia de sentencias de programa encerradas entre llaves; a continuación del bloque  hay una lista de manejadores llamados cláusulas catch. Al menos un manejador catch debe aparecer inmediatamente después de un bloque try, si no hay tal manejador, debe especificarse el manejador opcional finally. 
La sintaxis del bloque try es:
try                              
{
   código del bloque try 
 }
 catch (signatura)
 {
   código del bloque catch
 }
Clases de excepciones definidas en Java
En su empeño por estandarizar el manejo de excepciones Java declara un amplio con junto de clases de excepciones, las cuales forman una jerarquía en la que la base es Throwable, que deriva directamente de la superclase base Object.
 De Throwable derivan dos clases: Error y Exception; las excepciones del tipo Error son generadas por el sistema, se trata de errores irrecuperables y es extraño que se produzcan; por ejemplo: salir de la memoria de la máquina virtual; por tanto, de producirse una excepción Error se propagará hasta salir por el método main(); los nombres de las subclases que derivan de dicha excepción acaban con el sufijo Error, como InternalError o NoClassDefFoundError. De Exception derivan clases de las que se instancian objetos (excepciones) para ser  lanzados; pueden ser capturados por los correspondientes catch; las clases derivadas de  Exception se encuentran en los diversos paquetes de Java, todas tienen como nombre un identificador que indica su finalidad, terminado en Exception; la jerarquía de excepciones a partir de esta base es la que se muestra en la figura.

EJEMPLO:
Cálculo de las raíces o soluciones de una ecuación de segundo grado. Una ecuación de segundo grado, tiene dos raíces: 
Los casos de indefinición son: 1) a = 0 ; 2)  b2 – 4ac <0, que no producen raíces reales, sino imaginarias; en consecuencia, se consideran  dos excepciones: NoRaizRealException y CoefAceroException
La clase EcuacionSegGrado tiene como atributos a, b y c, que son coeficientes de la ecuación; además, r1, r2 son las raíces; el método raices() las calcula, su declaración es:
void raices() throws NoRaizRealException, CoefAceroException
El cuerpo del método es:
void raices() throws NoRaizRealException, CoefAceroException
{
  double discr;
  if(b*b < 4*a*c)
    throw new NoRaizRealException("Discriminante negativo",a,b,c);
  if(a == 0)
    throw new CoefAceroException("No ecuaciones De segundo grado  ",a,b,c);
  discr = Math.sqrt(b*b - 4*a*c);
  r1 = (-b - discr) / (2*a);
  r2 = (-b + discr) / (2*a);
}
raíces() lanza excepciones si no tiene raíces reales o si el primer coeficiente es cero; el método no captura excepciones sino que se propagan; es necesaria la cláusula throws con los tipos NoRaizRealException, CoefAceroException. El método desde el que se llame a raices() debe tener un bloque try-catch para capturar las excepciones lanzadas o se propagarán, lo que exige de nuevo la cláusula throws. La siguiente aplicación define las clases con las excepciones antes mencionadas; en el método main() se piden los coeficientes de la ecuación, se crea el objeto, se llama al método de cálculo y se escribe en pantalla.
import java.util.*;
// representa la excepción: ecuación no tiene solución real
class NoRaizRealException extends Exception
{
  private double a,b,c;  
  public NoRaizRealException(String m, double a, double b, double c)
  {
    super(m);
    this.a = a;
    this.b = b;
    this.c = a;
  }
  public String getMessage()
  {
   return  "Para los coeficientes "+(float)a +", " +(float)b + ", " +(float)c +super.getMessage();
  }
}
// representa la excepción: no es ecuación de segundo grado
class CoefAceroException extends Exception
{
  public CoefAceroException(String m)
  {
    super(m);
  }
}
// clase para representar cualquier ecuación de segundo grado
class RaiceSegGrado
{
  private double a,b,c;
  private double r1,r2;   
  public RaiceSegGrado(double a, double b, double c)
  {
    this.a = a;
    this.b = b;
    this.c = c;
  }
  public  void raices() throws NoRaizRealException, CoefAceroException
  {
    ...
  }
  public  void escribir()
  {
    System.out.println("Raices de la ecuaci¢n; r1 = "+ (float)r1 + "  r2 = " + (float)r2);
  }
}      
// clase principal
public class Raices
{
  public static void main(String [] ar)
  {
    RaiceSegGrado rc;
    double a,b,c;
    Scanner entrada = new Scanner(System.in);
    // entrada de coeficientes de la ecuación
    System.out.println("Coeficientes de ecuación de segundo grado");
    System.out.println(" a = ");
    a = entrada.nextDouble();
    System.out.println(" b = ");
    b = entrada.nextDouble ();
    System.out.print(" c = ");
    c = entrada.nextDouble();
    // crea objeto ecuación y bloque para captura de excepciones
    try
    {
      rc = new RaiceSegGrado(a,b,c);  
      rc.raices();
      rc.escribir();
    }
    catch(NoRaizRealException er)
    {
      System.out.println(er.getMessage());
    }
    catch(CoeficienteAcero er)
    {
      System.out.println(er.getMessage());
    }
  }
}
Se puede observar que en el constructor de la clase NoRaizRealException se hace una llamada al constructor de la clase base, Exception, para pasar la cadena; también se redefinió el método getMessage(), de tal forma que devuelve la cadena con que se inicializa al objeto excepción concatenada con los coeficientes de la ecuación de segundo grado.

martes, 10 de noviembre de 2015

Interfaces



Java incorpora una construcción del lenguaje, mediante la declaración interface, que permite enunciar un conjunto de constantes y de cabeceras de métodos abstractos; éstos deben implementarse en las clases y constituyen la interfaz de la clase. En cierto modo, es una forma de declarar que todos los métodos de una clase son públicos y abstractos, con ello se especifica el comportamiento común de todas las clases que implementen la interfaz; su declaración es similar a la de una clase; en la cabecera se utiliza la palabra reservada interface en vez de class, por ejemplo:




La interfaz FIGURAS define dos métodos abstractos y además públicos; sin embargo, no debe especificarse ni abstract ni public ya que todos los métodos de interface lo son.

Sintaxis

acceso interface NombreInterface
{
  Constante_1;
  ...
  Constante_n;
 
Tipo nombreMetodo_1 (argumentos);
  ...
 Tipo nombreMetodo_n (argumentos);

}

acceso visibilidad de la interfaz definida, normalmente public.

Implementación de una interfaz

La interfaz especifica el comportamiento común que tiene un conjunto de clases, el cual se realiza en cada una de ellas y se conoce como implementación de interfaz; utiliza una sintaxis similar a la derivación o extensión de una clase, con la palabra reservada implements en lugar de extends.

class NombreClase implements NombreInterfaz
{
  // Definición de atributos
  // Implementación de métodos de la clase
  // Implementación de métodos del interfaz
}

La clase que implementa la interfaz tiene que especificar el código (la implementación) de cada uno de sus métodos; de no hacerlo, la clase se convierte en abstracta y debe declararse abstract; esto es una forma de obligar a que cada método de la interfaz se implemente.

Múltiples interfaces
Java no permite que una clase derive de dos o más clases, es decir, no permite la herencia múltiple; sin embargo, una clase sí puede implementar más de una interfaz y tener el comportamiento común de varias de ellas; para esto, sencillamente se escriben las interfaces separadas por comas a continuación de la palabra reservada implements; así, la clase tiene que implementar los métodos de todas.
sintaxis
class NombreClase implements Interfaz_1, Interfaz_2,..., Interfaz_n
{
  // ...

}

jueves, 5 de noviembre de 2015

POLIMORFISMO

POLIMORFISMO

Para empezar con esta entrada, se ha de decir que el término “Polimorfismo” es una palabra de origen griego que significa “muchas formas”. Este termino se utiliza en la POO para “referirse a la propiedad por la que es posible enviar mensajes sin tácticamente iguales a objetos de tipos distintos“.

En esta entrada vamos a trabajar un ejemplo rápido y simple aplicando el concepto de Polimorfismo:


import java.util.*;

class Instrumento {
    public void tocar() {
System.out.println("Instrumento.tocar()");
    }
    public String tipo() {
return "Instrumento";
    }
    public void afinar() {}
}



class Guitarra extends Instrumento {
    public void tocar() {
System.out.println("Guitarra.tocar()");
    }
    public String tipo() { return "Guitarra"; }
    public void afinar() {}
}

class Piano extends Instrumento {
    public void tocar() {
System.out.println("Piano.tocar()");
    }
    public String tipo() { return "Piano"; }
    public void afinar() {}
}

class Saxofon extends Instrumento {
    public void tocar() {
System.out.println("Saxofon.tocar()");
    }
    public String tipo() { return "Saxofon"; }
    public void afinar() {}
}

// Un tipo de Guitarra 
class Guzla extends Guitarra {
       public void tocar() {
         System.out.println("Guzla.tocar()");
       }
       public void afinar() {
         System.out.println("Guzla.afinar()");
       }
     }

// Un tipo de Guitarra 
class Ukelele extends Guitarra {
    public void tocar() {
System.out.println("Ukelele.tocar()");
    }
    public String tipo() { return "Ukelele"; }
}

public class Musica {

    // No importa el tipo de Instrumento,
    // seguirá funcionando debido a Polimorfismo:
    static void afinar(Instrumento i) {
// ...
i.tocar();
    }

    static void afinarTodo(Instrumento[] e) {

for(int i = 0; i < e.length; i++)
   afinar(e[i]);
    }


    public static void main(String[] args) {
Instrumento[] orquesta = new Instrumento[5];
int i = 0;
// Up-casting al asignarse el Arreglo
orquesta[i++] = new Guitarra();
orquesta[i++] = new Piano();
orquesta[i++] = new Saxofon();
orquesta[i++] = new Guzla();
orquesta[i++] = new Ukelele();
afinarTodo(orquesta);
    }
}



Clase Música

En el código fuente de Musica.java son diseñadas diversas Clases que demuestran el uso de Polimorfismo:

  • Instrumento: Es utilizada como la Clase Base para el resto de Clases y en ella son definidos tres métodos: tocar,tipo y afinar.

  • Guitarra: Hereda ("Inherit") de la Clase Instrumento y redefine ("Override") los métodos de ésta.

  • Piano: Hereda ("Inherit") de la Clase Instrumento y redefine ("Override") los métodos de ésta.

  • Saxofon: Hereda ("Inherit") de la Clase Instrumento y redefine ("Override") los métodos de ésta.

  • Guzla: Hereda ("Inherit") de la Clase Guitarra y redefine ("Override") los métodos de ésta.

  • Ukelele: Hereda ("Inherit") de la Clase Guitarra y redefine ("Override") los métodos de ésta.

Las definiciones de la Clase principal Musica son descritas en los siguientes incisos:


  • El primer método definido en esta Clase llamado afinar toma como valor de entrada una referencia del tipo Instrumento, sobre la cual es invocado el método tocar.

  • Un segundo método nombrado afinarTodo toma como valor de inicia un arreglo de Instrumento, el cual es procesado por un ciclo que a su vez manda llamar el método afinar con los respectivos valores del arreglo.
Dentro del método principal se define lo siguiente:

  •          Primeramente se genera un arreglo de Instrumento para 5 Objetos.Se inicializa un primitivo i con un valor de cero.

  • A través de la referencia orquesta son asignados distintos Objetos al arreglo, nótese que aunque el arreglo es de tipo Instrumento es posible asignar los Objetos: Guitarra,Piano,Saxofon,Guzla,Ukelele.




  • Finalmente se invoca el método afinarTodo con la referencia que representa el arreglo de Instrumento.


Al ser ejecutado este programa se obtienen los siguientes resultados:

--java Musica----

Guitarra.tocar()
Piano.tocar()
Saxofon.tocar()
Guzla.tocar()
Ukelele.tocar()

Lo interesante de este resultado reside en la manera que fue realizada la invocación de métodos, el método que realiza las llamadas hacia las diversas clases es afinar dentro de la Clase Música, observe que este método toma como valor inicial una referencia del tipo Instrumento y se invoca el método tocar.