Strings, I/O, Formateo, and Parseo

A continuación dejo el resumen del sexto capítulo (Strings, I/O, Formatting, and Parsing) del libro "Sun Certified Programmer for Java 6 Study Guide".

String, StringBuilder y StringBuffer (Objetivo 3.1):
Un String es un objeto inmutable, una vez que el mismo se creó, no puede ser modificado. Cuando se realiza una concatenación de dos String, lo que hace la JVM es crear un nuevo objeto String con el valor de las dos cadenas concatenadas. Cuando se invoca un método del objeto String (por ej.: toUpperCase()), el método devuelve un nuevo objeto String con su correspondiente valor, no se modifica el valor original del String (con el que se invoco el método).
Algunos métodos de los objetos String:
  • public char charAt(int index): Devuelve el carácter alojado en el índice pasado como parámetro.
  • public String concat(String s): Agrega un String al final de otro (como el operador ‘+’).
  • public boolean equalsIgnoreCase(String s): Determina la igualdad de dos String, ignorando las diferencias de mayúsculas y minúsculas.
  • public int length(): Devuelve la cantidad de caracteres que componen un String.
  • public String replace(char old, char new): Reemplaza las ocurrencias de un carácter con otro nuevo.
  • public String substring(int begin) - public String substring(int begin, int end): Devuelve una parte de un String.
  • public String toLowerCase(): Devuelve el String con todos los caracteres convertidos a minúsculas.
  • public String toUpperCase(): Devuelve el String con todos los caracteres convertidos a mayúsculas.
  • public String trim(): Remueve los espacios en blanco del principio y final del String.
La clase StringBuilder (agregada en Java 5), posee exactamente los mismos métodos que la clase StringBuffer. La única diferencia entre ellas, es que la clase StringBuilder es más rápida debido a que sus métodos no están sincronizados. Estas dos clases se utilizan para realizar muchas modificaciones sobre los caracteres de una cadena. Los objetos de estas clases no crean un nuevo objeto cada vez que se modifican (como los objetos String), es por esto que son más eficientes para realizar muchas modificaciones sobre cadenas.
Algunos métodos de los objetos StringBuilder y StringBuffer:
  • public synchronized StringBuffer append(String s)
  • public StringBuilder delete(int start, int end)
  • public StringBuilder insert(int offset, String s)
  • public synchronized StringBuffer reverse()
  • public String toString()
Resumen (TWO-MINUTE DRILL):
  • Los objetos String son inmutables, pero las referencias a String no lo son.
  • Si se crea un nuevo objeto String, pero no se asigna a una variable de referencia, el mismo se pierde para el programa.
  • Si se redirecciona una variable referencia a un nuevo objeto String, el objeto String anterior se pierde.
  • Los métodos de objetos String utilizan los índices basados en cero, excepto el método substring(), el cuál utiliza su segundo argumento basado en uno.
  • La clase String es final, sus métodos no pueden ser sobreescritos.
  • Cuando la JVM encuentra un literal String, este se agrega al “String literal pool”.
  • Los objetos String poseen el método length(), los arreglos poseen la propiedad length.
  • La API de la clase StringBuffer es la misma que la de StringBuilder, salvo que los métodos de esta última no se encuentran sincronizados.
  • Los métodos de los objetos StringBuilder son más rápidos que los de StringBuffer.
  • Los siguientes puntos se aplican a ambas clases (StringBuilder y StringBuffer):
    - Son mutables, pueden cambiar su valor sin crear un nuevo objeto.
    - La invocación de sus métodos cambian el valor del objeto, sin realizar ninguna asignación explícita.
    - El método equals() no está sobreescrito, no compara los valores.
  • La encadenación de métodos se evalúa de izquierda a derecha.
Ver ejemplo: Main01.java

File e I/O (Objetivo 3.2):
Clases que se necesitan saber para el examen:
  • File: Es una representación abstracta de un archivo o directorio. Esta clase no se utiliza para escribir o leer datos, si no para trabajar a alto nivel. Es decir, para crear, buscar, eliminar archivos y para trabajar con directorios y rutas.
  • FileReader: Esta clase se usa para leer caracteres de un archivo. Tiene un método read() de bajo nivel, el cual se puede utilizar para leer un simple carácter, un flujo entero de caracteres, o un número especifico de caracteres.
  • BufferedReader: Esta clase se utiliza para hacer más eficientes las clases de bajo nivel como FileReader. Permite leer grandes cantidades de información de un archivo de una sola vez, y almacenar los datos en un buffer. De este modo cada vez que se necesite obtener la información, se obtendrá desde el buffer minimizando así los accesos a disco. También provee el método readLine().
  • FileWriter: Esta clase se usa para escribir caracteres en un archivo. Posee el método write() que permite escribir caracteres o Strings a un archivo.
  • BufferedWriter: Se utiliza para hacer más eficientes y más fácil de utilizar las clases de bajo nivel como FileWriter. Esta clase escribe grandes cantidades de información a un archivo de una vez, minimizando el número de operaciones de escritura. También provee el método writeLine(), el cual añade los caracteres de salto de línea correspondientes a la plataforma en la que se ejecuta.
  • PrintWriter: Envuelve las clases FileWriter y BufferedWriter. Añade varios métodos como format(), printf() y append() que brindan mayor flexibilidad y poder.
Cuando se crea una instancia de la clase File, solo se está creando el nombre de un archivo. Esta clase contiene métodos de utilidad para realizar operaciones sobre archivos y directorios:
  • public boolean exists(): Devuelve true si el archivo existe.
  • public boolean createNewFile(): Crea un nuevo archivo, si el mismo no existe.
  • public boolean mkdir(): Crea un nuevo directorio, si el mismo no existe.
  • public boolean delete(): Elimina un archivo o directorio. No se puede eliminar directorios si los mismos no se encuentran vacios.
  • public boolean renameTo(): Se pasa como argumento una instancia de File con el nuevo nombre del archivo.
  • public String[] list(): Devuelve un arreglo de String’s con los archivos y directorios contenidos en la ubicación actual.
La clase Console permite aceptar entradas desde la línea de comandos. El método readLine() devuelve un String que contiene lo que el usuario haya ingresado. El método readPassword() devuelve un arreglo de caracteres que contienen el password solicitado. La clase Console no se puede instanciar a través de su constructor. Para obtener una instancia se debe invocar el método estático System.console().

Resumen (TWO-MINUTE DRILL):
  • Las clases que se deben entender del paquete java.io son: File, FileReader, BufferedReader, FileWriter, BufferedWriter, PrintWriter y Console.
  • Cuando se crea un nuevo objeto File, no significa que se crea un nuevo objeto.
  • Un objeto File puede representar tanto un archivo como un directorio.
  • La clase File permite administrar (crear, renombrar y eliminar) archivos y directorios.
  • Los métodos createNewFile() y mkdir() agregan archivos y directorios al sistema de archivos.
  • FileWriter y FileReader son clases I/O de bajo nivel. Se pueden utilizar para escribir y leer archivos, pero generalmente se envuelven en clases con mayor funcionalidad.
  • Es muy común envolver un objeto FileReader con una instancia de BufferedReader o una instancia de FileWriter con una de BufferedWriter, para tener métodos más eficientes y de alto nivel.
  • Los objetos PrintWriter’s pueden ser utilizados para envolver tipos Writer, pero desde Java 5 pueden ser instanciados directamente desde instancias File o String.
  • La clase PrintWriter desde Java 5 posee nuevos métodos: append(), format() y printf().
Ver ejemplo: Main02.java

Serialización (Objetivo 3.3):
La serialización permite guardar el estado de un objeto (es decir, todas sus variables de instancia). Si una variable de instancia tiene el especificador transient, la misma no será almacenada por el proceso de serialización.
Para que un objeto pueda ser serializado, el mismo debe implementar la interface Serializable (dicha interface no posee métodos para implementar, solo es un marcador). Un objeto serializado se almacena en un archivo de bytes, se utilizan dos métodos que permiten leer y escribir un stream de datos.
  • ObjectOutputStream.writeObject()
  • ObjectInputStream.readObject()
Ambas clases son envoltorios de las clases FileOutputStream y FileInputStream. Los métodos writeObject() y readObject() trabajan con objetos de tipo Serializable.

Cuando se intenta serializar un objeto (Serializable) que contiene (relación TIENE-UN) una referencia a otro tipo de objeto pueden ocurrir ciertas situaciones:
  • Si el objeto contenido no implementa la interface Serializable: Se produce la siguiente excepción en tiempo de ejecución NoSerializableException.
  • Si la variable de referencia al objeto contenido está marcada con el especificador transient: Se serializa el estado del objeto contenedor, dejando de lado el estado del objeto contenido.
  • Si la clase del objeto contenido implementa la interface Serializable: Se guarda todo el estado completo del objeto. Es decir, cuando se deserialice el estado del objeto contenedor, también se recuperará el estado del objeto contenido.
El proceso de serialización de Java posee un mecanismo especial para los objetos que son especiales y difíciles de guardar. Se trata de un conjunto de métodos privados que se pueden implementar en la clase en cuestión. Si dichos métodos concuerdan con la signatura exacta, se invocarán durante el proceso de serialización y deserialización del objeto. Las signaturas son las siguientes:
  • private void writeObject (ObjectOutputStream os) { }
  • private void readObject (ObjectInputStream is) { }
Gracias a estos dos métodos es posible manejar el proceso de serialización. Esto se puede realizar debido a que los objetos ‘os’ e ‘is’ tienen un conjunto de métodos para invocar el proceso de serialización por defecto y además métodos para almacenar y leer datos adicionales.
Proceso de serialización por defecto:
  • ObjectOutputStream.defaultWriteObject()
  • ObjectInputStream.defaultReadObject()
Métodos para almacenar y leer datos adicionales:
  • ObjectOutputStream.writeInt()
  • ObjectOutputStream.writeFloat()
  • ObjectInputStream.readInt()
  • ObjectInputStream.readFloat()
La herencia también se ve afectada por el proceso de serialización. Cuando una clase base implementa la interface Serializable, hace que todas sus subclases también la implementen.
El problema real se da cuando una clase base no es Serializable pero una de sus clases hijas si lo es. Esta situación produce que se serialice solo el estado de la clase hija, dejando de lado todas las variables de instancia de la clase base. Para que este escenario sea posible, la clase base debe poseer un constructor por defecto. En caso contrario se producirá un error en tiempo de ejecución a la hora de deserializar el objeto, ya que se intentará invocar automáticamente el constructor por defecto de clase base.

Resumen (TWO-MINUTE DRILL):
  • Las clases que se necesitan conocer del paquete java.io son: ObjectInputStream, ObjectOutputStream, FileInputStream, FileOutputStream.
  • Una clase debe implementar la interface Serializable antes de poder ser serializada.
  • El método ObjectOutputStream.writeObject() serializa los objetos, y el método ObjectInputStream.readObject() deserializa los objetos.
  • Si una variable de instancia es marcada con el especificador transient, la misma no será serializada, aunque todas las demás variables de instancia si lo hagan.
  • Si una superclase implementa la interface Serializable, entonces las subclases lo hacen automáticamente.
  • Si una superclase no implementa Serializable, cuando una subclase se deserializa, se invoca el constructor por defecto de la clase padre.
  • DataInputStream y DataOutputStream no se toman en el examen.
Ver ejemplo: Main03.java

Fechas, números y monedas (Objetivo 3.4):
Clases que se necesitan saber para el examen:
  • java.util.Date: La mayoría de los métodos de esta clase están depreciados. Pero esta clase es útil como puente entre Calendar y DateFormat.
  • java.util.Calendar: Provee una gran variedad de métodos que ayudan a convertir y manipular fechas y tiempos.
  • java.text.DateFormat: Esta clase se utiliza no solo para formatear fechas en varios estilos, sino también para formatear fechas de varias localidades del planeta.
  • java.text.NumberFormat: Esta clase se utiliza para formatear números y monedas para varias localidades del planeta.
  • java.util.Locale: Esta clase se utiliza junto con DateFormat y NumberFormat para formatear fechas, números y monedas para una localidad específica.
Resumen (TWO-MINUTE DRILL):
  • Las clases que se necesitan saber para este objetivo son: java.util.Date, java.util.Calendar, java.text.DateFormat, java.text.NumberFormat y java.util.Locale.
  • La mayoría de los métodos de la clase Date están depreciados.
  • Dentro de una instancia Date, la fecha se almacena como un valor long, la cantidad de milisegundos desde el 1ro de Enero de 1970.
  • Los objetos Date son utilizados con instancias Calendar y Locale.
  • La clase Calendar provee un poderoso conjunto de métodos para manipular fechas, realizar tareas como obtener los días de la semana, o agregar un numero de meses o años (u otros tipos de incrementos) a una fecha.
  • Para crear una instancia de la clase Calendar, se debe invocar el método estático (getInstance()).
  • Los métodos de Calendar que se deben conocer son:
    - add(): Permite adicionar o sustraer varias piezas (minutos, días, horas, etc.) de fechas.
    - roll(): Funciona al igual que add(), a diferencia que no incrementa las piezas más grandes de la fecha.
  • Para crear instancias de la clase DateFormat, se deben utilizar los métodos estáticos getInstance() y getDateInstance().
  • Existen diferentes estilos disponibles en la clase DateFormat.
  • El método DateFormat.format() se utiliza para crear String que contienen fechas formateadas.
  • La clase Locale se utiliza conjuntamente con las clases DateFormat y NumberFormat.
  • Las instancias de DateFormat y NumberFormat pueden ser creadas con un objeto Locale específico, el cuál es inmutable.
  • Para el examen se debe saber cómo crear objetos Locale utilizando el leguaje, o la combinación de lenguaje y país.
Ver ejemplo: Main04.java

Parseo, Tokenizing y Formateo (Objetivo 3.5):
Resumen (TWO-MINUTE DRILL):
  • Las expresiones regulares, son patrones utilizados para buscar información dentro de grandes fuentes de datos.
  • Las expresiones regulares, son un sub-lenguaje que existe dentro de Java.
  • Las expresiones regulares permiten crear patrones de búsqueda mediante caracteres o metacaracteres. Los metacaracteres permiten buscar información más abstracta como dígitos o espacios en blanco.
  • Los metacaracteres utilizados en el examen son: ‘\d’, ‘\w’, ‘\s’ y ‘.’.
  • Los cuantificadores utilizados en el examen son: ‘?’, ‘*’ y ‘+’.
  • Los metacaracteres deben ser escapados dentro de los Strings. String s = “\\d”.
  • Las clases Pattern y Matcher poseen las capacidades más poderosas de Java para las expresiones regulares.
  • Los métodos que son utilizados en el examen son:
    - Pattern: compile()
    - Matcher: matches(), pattern(), find(), start() y group().
  • Tokenizing es el proceso de dividir información delimitada en pequeñas piezas.
  • El proceso Tokenizing se puede llevar a cabo mediante la clase Scanner o a través del método String.split().
  • Los delimitadores pueden ser caracteres simples como una coma, o expresiones regulares.
  • La clase Scanner permite dividir información dentro de un bucle, pero también permite parar este proceso en cualquier parte (a diferencia del método String.split() el cuál debe procesar todos los datos de una vez para obtener un resultado).
  • La clase Scanner permite dividir Strings, streams (flujos de datos) o archivos.
  • A partir de Java 5 se encuentran disponibles los métodos format() y printf(). Los cuales pertenecen a la clase PrintWriter. Ambos métodos poseen la misma funcionalidad, formatear una salida.
  • %[arg_index$][flags][ancho][.precision]carcter de conversión
    - Flags: ‘-‘, ‘+’, ‘0’, ‘,’ y ‘(‘.
    - Conversiones: b, c, d, f y s.
  • Si en carácter de conversión no concuerda con el tipo de argumento, se lanza una excepción.

0 comentarios:



Publicar un comentario en la entrada

Este blog dejo de ser mantenido el día 12/02/2010. Para cualquier consulta o comentario realizarlo a través del sitio http://onj2ee.blogspot.com/