New 2 Java: Suplementos

Una declaraci�n de variable le dice al compilador el nombre y el tipo de dato de un trozo espec�fico de memoria y donde se puede utilizar legalmente esta variable. El "donde se puede utilizar legalmente esta variable" es el �mbito de la variable. Cuando una variable entra en �mbito, el sistema de ejecuci�n la crea. Cuando sale del �mbito, el sistema la destruye. S�lo podemos acceder a un variable dentro del �mbito de su declaraci�n.

�Qu� significa que una variable entre en �mbito? Definimos las variables entre una pareja de corchetes, un corchete abierto { y un corchete cerrado }. Cuando el c�digo entra en el conjunto de corchetes m�s interno alrededor de la declaraci�n de la variable, la variable entra en �mbito. Por ejemplo, en la siguiente declaraci�n de clase, la variable scopeMe entra en �mbito en la l�nea 1, y la variable scopeYou entra en �mbito en la l�nea 3:

1: class CheckScope {
2:   int scopeMe;
3:   public static void main(String args[]) {
4:     int scopeYou;
5:   }
6:   int scopeWe;
7: }

Al igual que scopeMe, la variable scopeWe tambi�n entra en �mbito en la �nea 1. Las declaraciones de variabales no tienen porque hacerse al principio de la declaraci�n de la clase.

Esto trae a cuento el punto de los diferentes tipos de variables. Aqu� las variables, scopeMe y scopeWe son conocidas como variables miembro. Son parte de la declaraci�n de la clase y son inicializadas cuando se inicializa la clase. Las variables miembro obtienen del compilador un valor por defecto bas�ndose en su tipo de datos:

0       byte, short, int, long
0.0     float, double
false   boolean
\u0000  char
null    Object

La variable scopeYou es conocida como una variable local. Cuando se llama al m�todo main(), el sistema reserva espacio para la variable scopeYou. Las variables locales no son inicializadas autom�ticamente y el compilador protestar� si intentamos acceder a una variable local no inicializada. Las variables locales est�n s�lo dentro del �mbito del conjunto de corchetes m�s interno que envuelven la declaraci�n de la variable.

La variable args del m�todo main() de la clase CheckScope es llamada una variable de m�todo. Las variables de m�todo se usan para pasar valores de par�metros a constructores o m�todos. El �mbito de las variables de m�todos es el m�todo en el que son declaradas. Una vez que un m�todo retorna, no podemos acceder a ning�n par�metro (o variable clocal) desde fuera del m�todo.

No mostrado en la definici�n de la clase CheckScope es el par�metro de la clausula catch de un manejador de excepciones:

try {
   // troublesome code
} catch (IOException exception) {
   // "exception" is valid
} catch (Exception exception) {
   // "exception" is valid
}

aqu�, las clausulas try-catch pueden tratar con dos tipos de excepciones que podr�an lanzarse desde la secci�n de c�digo troublesome. Ambas clausulas tratan con un variable exception com�n como el par�metro del manejador de excepci�n. S�lo dentro de las respectivas clausulas catch la variable exception est� dentro de �mbito. Debido a esta l�mitaci�n de ambito de los par�metros de los manejadores de excepciones, cada clausula catch puede tener el mismo nombre de variable como su par�metro.

Para demostrar los l�mites de �mbito, el siguiente c�digo intenta encontrar qu� m�s del a�o es Junio. Las dos primeras l�neas de main() obtienen los meses del a�o en un array de strings. Luego, el bucle for pasa por el array, antes de imprimir donde se encuentra June.

import java.util.*;
import java.text.*;

public class June {
   public static void main(String args[]) {

     DateFormatSymbols symbols = 
		       new DateFormatSymbols(Locale.US);
     String months[] = symbols.getMonths();
     for (int i=0, n=months.length; i < n; i++) {
       if (months[i].equals("June")) {
         break;
       }
     }
     System.out.println("June month = " + i);
   }
}

Aqu� se han declarado cinco variables:

  • args es un par�metro del m�todo main()
  • symbols y months son variables lcoales dentro de main()
  • i y n sin variables locales dentro del bucle for.

Como i y n son variables locales dentro del buble for, no podemos acceder a ellas desde fuera del bucle. No son v�lidas. En este ejemplo particular, sin intentamos compilar la clase, el compilador protestara:

June.java:14: cannot resolve symbol
symbol  : variable i
location: class June
System.out.println("June month = " + i);
                                      ^
1 error

En otras palabas, la variable i no est� en el �mbito nunca m�s. Para hacer que este programa funcione, debemos mover la declaraci�n de la variable i fuera del bucle for, o usar una variable separada. El �ltimo caso se muestra aqu� con el ejemplo corregido:

import java.util.*;
import java.text.*;

public class June {
   public static void main(String args[]) {

     DateFormatSymbols symbols = new DateFormatSymbols(Locale.US);
     String months[] = symbols.getMonths();
     int j = -1;
     for (int i=0, n=months.length; i < n; i++) {
       if (months[i].equals("June")) {
         j = i;
         break;
       }
     }
     System.out.println("June month = " + j);
   }
}

Ahora el programa produce el siguiente resultado:

June month = 5 

Como los arrays tienen base cero, Junio vuelve como 5. (Enero es 0).

.�Entender la Librer�a de Clases Java

.�Las Clases File y BufferedReader

En el Suplemento N� 6 aprendimos sobre las clases FileInputStream y FileOutputStream para leer y escribir en objetos stream. Algunas veces se necesita m�s informaci�n, como encontrar si existe un fichero antes de escrbir en �l, o acelerar los procesos de lectura y escritura.

La clase File nos permite obtener informaci�n sobre un fichero y sus directorios, pero no tiene m�todos para leer o escribir ficheros. La clase File tiene m�todos �tliles para hacer lo siguiente:

Chequear las propiedades de un fichero o directorio:

  • getName
  • lastModified

Crear directorios:

  • mkdir
  • mkdirs

Obtener el path de un fichero o directorio:

  • getAbsolutePath
  • getPath

Seleccionar las caracter�sticas de un objeto File:

  • setReadOnly
  • canWrite

La siguiente aplicaci�n ilustra algunos de estos m�todos:

// Import the java.io package to make the File class
// available to you without having to type the package
// name in front of the class name each time.
import java.io.*;

public class TestFileClass
 {
    public static void main(String[] args)
     {
       // Creates a reference to a file object.
       File aFile = new File("data.txt");
       // Creates a file object to use as
       // a directory name
       File aDir = new File("mydirectory");
       
       // Checks if the file exists and that
       // it is a file. If so the name and path
       // are printed to the screen.
       if(aFile.exists() && aFile.isFile())
         System.out.println(aFile.getName() + 
                       " exists and is located at "
                         + aFile.getAbsolutePath());
           else
             System.out.println(aFile + "Does not exist.");
        if(aFile.canWrite())
          System.out.println(aFile + " can be written to."); 
        // Sets the file to read only.
        aFile.setReadOnly();
          System.out.println(aFile + "is now read only.");    
       // Creates a directory, giving it the
       // object name. The if statement tests
       // if the directory is successfully
       // created.
       aDir.mkdir();
        if (aDir.isDirectory())
          System.out.println(aDir.getName() + " is a directory.");
          else
          System.out.println("Directory was not created.");
        
     }
 }   

Una vez que hemos establecido que el fichero existe y que se puede leer, podemos leer los contenidos del fichero un caracter cada vez con la clase FileReader, o mejor todav�a, podemos envolver FileReader en BufferedReader. Esto es m�s eficiente porque crea un buffer de almacenamineto temporal y lee un bloque de caracteres. BufferedReader se usa principalmente para envolver un objeto Reader para su m�todo readLine, que lee una l�nea de texto y la devuelve como un String. Para hacer estos seguimos estos tres pasos:

  1. Declaramos una variable string como una referencia para el texto a leer.
  2. Creamos un objeto BufferedReader que tome un objeto Reader como argumento.
  3. Llamamos a readLine dentro de un bucle para pasar por todas las l�neas del fichero hasta que se devuelva null.

El siguiente ejemplo demuestra este proceso y asume que hemos creado un fichero llamando texttoread.txt:

import java.io.*;

public class TestBufferedReader
  {
   public static void main(String[] args)
    {
      String text;
       try 
       {
         // Creates a BufferedReader object that takes a
         // FileReader object as an argument. The FileReader
         // associates an object with the file to be read.
         BufferedReader br =
           new BufferedReader(new FileReader("texttoread.txt"));
         // The while loop calls the readLine method as long as
         // there is a line of characters to be read. 
         while ((text = br.readLine()) != null)
          {
            System.out.println(text);
           }
           // Always close a file after opening.
           br.close();
         }
         // Catch and handle the exception in the
         // event that the named file cannot be found.
         catch (FileNotFoundException fnfe)
         {
          System.out.println(fnfe);
          return;
          }
          // Catch and handle an exception if there is
          // a problem reading the file.
          catch (IOException ioe)
          {
           System.out.println(ioe);
          }
        }
    }

.�Programa Ejercicio

El siguiente programa se usa para mostrar informaci�n sobre un objeto File cuyo nombre es pasado desde la l�nea de comandos. Si el fichero existe y es un fichero normal, se muestra su contenido. El cierre del fichero sucede dentro de la parte try del bloque try-catch. Si ocurre una excepci�n despu�s de que el fichero est� abierto, el fichero no se cierra apropiadamente.

Cambia el �mbito de la variable BufferedReader para que el cierre del fichero suceda en una clausula finally del bloque try-catch:

import java.io.*;
import java.util.*;

public class ReadFile {
   public static void main(String args[]) {
     if (args.length == 0) {
       System.err.println("Please provide filename to process");
       System.exit(-1);
     }
      String filename = args[0];
      try {
        File file = new File(filename);
        if (file.exists() &amp;&amp; file.isFile()) {
          long lastModified = file.lastModified();
          System.out.println("Date  : " + new Date(lastModified));
          System.out.println("Length: " + file.length());
          System.out.println("-----");
          FileReader fr = new FileReader(file);
          BufferedReader br = new BufferedReader(fr);
          String line;
          while ((line = br.readLine()) != null) {
            System.out.println(line);
          }
          br.close();
        }

      } catch (IOException e) {
        System.err.println("Problem: " + e);
      }
   }
}

.�Un poco de Java

.�M�s Atajos de Programaci�n

En el Suplemento N� 5 aprendimos sobre el uso de bucles for, y en el Suplemento N� 1 aprendimos sobre los arrays. Aqu�, aprederemos como combinar bucles for y arrays para un atajo de programaci�n usado muy frecuentemente. Esta t�cnica se usa frecuentemene para crear series de componentes GUI.

Cuando aprendas programaci�n GUI, ver�s un c�digo similar a este:

JLabel nameLabel = new JLabel("Name: ");
JLabel addressLabel = new JLabel("Address: ");
JLabel phoneLabel = new JLabel("phone: ");
JLabel titleLabel = new JLabel("title: ");

JTextField name = new JTextField();
JTextField address = new JTextField();
JTextField phone = new JTextField();
JTextField title = new JTextField();

etc. para declarar e inicializar tantos componentes como tenga el panel o la aplicaci�n. Dichas declaraciones podr�an requerir muchas l�neas de c�digo y la repetici�n de los nombres de clases.

En su lugar, podemos usar bucles for para hacer lo mismo, eliminando la necesidad de reteclear o copiar y pegar. El proceso es similar a listar las declaraciones y ejemplarizaciones con la variaci�n de la configuraci�n de arrays para hacer el tabajo en su lugar:

  • Configurar las variables para los arrays.
  • Configurar las variables para las etiquetas y los campos de texto.
  • Inicializar cada objeto pasado pasando el array a un bucle for.
  • A�adir los objetos al panel pasando el array a un bucle for.

Por ejemplo, cuando creamos una aplicaci�n con etiquetas y campos de texto, empezamos con un array para el texto:

String names[] = { "Name: ", "Address: ", "Phone: ", "Title: " }

Luego especificamos una variables para referenciar un array de cuatro etiquetas:

JLabel labels[4];

Luego configuramos una variable de referencia para los cuatro campos de texto:

JTextField textfields[4];

En el constructor de la clase, o desde dentro de un m�todo, incializamos todos los objetos label o textField usando un bucle for.

El bucle for se inicializa a 0, chequea la longitud del array labels llamando al m�todo length, luego pasa a trav�s de cada etiqueta, pasando cada etiqueta del array labels en la siguiente l�nea donde todos son inicializados como un objeto JLabel:

for (int i = 0; i < labels.length; i++)
      labels[i] = new JLabel(names[i]);

El bucle de los campos de texto funciona de la misma forma:

 
for (int i = 0; i < textfields.length; i++)
      textfields[i] = new JTextField();

Usamos un bucle for para a�adir cada objeto label y textField a un panel, podemos registrar cada uno con un oyente usando el bucle:

for (int i = 0; i < 4; i++)
   {
     panel.add(labels[i]);
     panel.add(textfields[i]);
     textfield[i].addActionListener(this);
    }

La aplicaci�n de abajo demuestra estos conceptos para compilar y ejecutar. Experimenta con el c�digo, a�adiendo m�s texto al array de strings y creando m�s etiquetas y campos de texto:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ForLoopShortcuts extends JFrame
                           implements ActionListener
 {
 
 private String names[] = 
     { "Name: ", "Address: ", "Phone: ", "Title: " };
 private JLabel labels[];
 private JTextField textfields[];
 private int size = 4;
 private JPanel panel;
 
 public ForLoopShortcuts()
   {
     // Calls the JFrame constructor, setting
     // the title for the frame.
     super("Demo of for Loop Shortcuts");
     // Gets the content pane for the frame.
     Container c = getContentPane();
     
     // Set up arrays to hold
     // four labels and 
     // four the text fields.
     labels = new JLabel[size];
     textfields = new JTextField[size];
     
     // The for loop initializes at zero,
     // checks the size of the labels
     // array, then steps through each.
     for (int i = 0; i < labels.length; i++)
     // Initializes a new label object, 
     // assigning the Strings from the String
     // array.
      labels[i] = new JLabel(names[i]);
     // Initializes new text field objects.
     for (int i = 0; i < textfields.length; i++)
      textfields[i] = new JTextField();
     
     panel = new JPanel();
     panel.setLayout(new GridLayout(size,2));
     panel.setBackground(Color.white);
     
     // Sets up a loop for the labels and
     // textfields array to add to the panels
     // and to register each as a listener.
     for (int i = 0; i < size; i++)
      {
        panel.add(labels[i]);
        panel.add(textfields[i]);
        //panel.textfields[i].addActionListener(this);
       }
      c.setLayout(new GridLayout(1, 1));
      c.add(panel);
      //The following line ensures that the application
      //closes down when exiting. This method only works
      //with J2SE 1.3 to 1.4. 
      setDefaultCloseOperation(EXIT_ON_CLOSE); 
     }
     
    public static void main(String[] args)
      {
        ForLoopShortcuts fls = new ForLoopShortcuts();
        fls.setSize(350, 130);
        fls.setVisible(true);
       }
 }

Algunos desarrallodores prefieren declarar e incializar los objetos individualmente porque puede hacer un poco m�s sencilla la depuraci�n, mientras que otro prefieren ahorrar espacio y teclear menos. La programaci�n usando est� t�cnica es correcta tanto por el estilo como por la conveniencia.

.�Soluci�n al Programa de Ejercicio

Esta es una posible soluci�n al programa del ejercicio:

: 
import java.io.*;
import java.util.*;

public class ReadFile {
   public static void main(String args[]) {
     BufferedReader br = null;
     if (args.length == 0) {
       System.err.println("Please provide filename to process");
       System.exit(-1);
     }
     String filename = args[0];

     try {
       File file = new File(filename);
       if (file.exists() && file.isFile()) {
         long lastModified = file.lastModified();
         System.out.println("Date  : " + new Date(lastModified));
         System.out.println("Length: " + file.length());
         System.out.println("-----");
         FileReader fr = new FileReader(file);
         br = new BufferedReader(fr);
         String line;
         while ((line = br.readLine()) != null) {
           System.out.println(line);
         }
       }
     } catch (IOException e) {
       System.err.println("Problem: " + e);
     } finally {
       if (br != null) {
         try {
           br.close();
         } catch (IOException ignored) {
         }
       }
     }
   }
}

.�Descargar la Plataforma Java 2

Para la mayor�a del desarrollo Java, necesitas las librer�as de clases Java, el compilador, las herramientas, y el entorno de ejecuci�n proporcionado por el kit de desarrollo de Java 2, Standard Edition.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO