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:
- Declaramos una variable string como una referencia para el texto a leer.
- Creamos un objeto BufferedReader que tome un objeto Reader como argumento.
- 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() && 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.
- Descarga el Paquete de Software J2SE 1.4.
- A�ade a tu Bookmark las Especificaciones del API