Sun Java Solaris Communities My SDN Account Join SDN
 
Java Technology Fundamentals Newsletter Index

Java Technology Fundamentals Newsletter

 

New-to-Java Programming Center
Programming Center Supplement

Welcome to the Java Developer ConnectionSM New to Java Programming Center Supplement

This monthly supplement provides a way for you to learn the basics of the Java programming language, discover new resources, and keep up-to-date on the latest additions to the JDC's New to Java Programming Center.

CONTENTS

1. Java Programming Language Basics

Variable Scope

2. Making Sense of the Java Class Libraries

The File and BufferedReader Classes

3. Program Challenge

ReadFile

4. Java Bits:

More Programming Shortcuts

5. New to the Programming Center

Building an Application, Part 3

6. For More Information

Links to articles, Tech Tips, trails, and tutorials that provide more information on the topics discussed here.

7. Program Challenge Solution and Explanation

Possible solution to the ReadFile program

Java Programming Language Basics

Variable Scope

A variable declaration tells the compiler the name and data type for a specific piece of memory and where that variable can be legally used. The "where that variable can be legally used" is a variable's scope. When a variable comes into scope, the runtime system creates it. When it goes out of scope, the system destroys it. You can only access a variable when you are within the scope of its declaration.

What does it mean for a variable to come into scope? You define variables within a pair of squiggly braces, an open brace { and a close brace }. When your code enters into the innermost set of braces wrapped around a variable declaration, the variable comes into scope.

For instance, in the following class declaration, the variable scopeMe comes into scope at line 1, and variable scopeYou comes into scope at line 3:

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

Like scopeMe, the variable scopeWe also comes into scope at line 1. Variable declarations do not have to be at the beginning of a class declaration. They can be spread throughout.

This brings up the point of different types of variables. Here, the variables scopeMe and scopeWe are known as member variables. They are part of the class declaration and are initialized when the class is initialized. Member variables get initialized by the compiler to a default value based upon their data type:

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

The scopeYou variable is known as a local variable. When the main() method is called, the system reserves space for the scopeYou variable. Local variables are not automatically initialized and the compiler complains if you try to access an uninitialized local variable. Local variables are only within scope within the innermost set of squiggly braces wrapped around the variable declaration.

The args variable for the main() method of the CheckScope class is called a method variable. Method variables are used to pass the values of parameters to constructors and methods. The scope for method variables is the method they are declared in. Once the method returns, you can't access any parameters (or local variables) from outside the method.

Not shown in the CheckScope class definition is the parameter to the catch clause of an exception handler:

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

Here, the try-catch clauses can deal with two types of exceptions that may be thrown from the troublesome code section. Both clauses rely on a common exception variable as the exception handler parameter. Only within each respective catch clause is the exception variable within scope. Because of this limited scope for exception handler parameters, each catch clause can have the same variable name as its parameter.

To demonstrate the limits of scope, the following code tries to find out which month of the year is June. The first two lines of main() get the months of the year into a String array. Then, the for loops through the array, before printing where June is found.

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);
   }
}

There are five variables declared here:

  • args is a method parameter to main()
  • symbols and months are local variables within main()
  • i and n are local variables within the for loop

Since i and n are local variables within the for loop, you can't access them outside the for loop. They aren't valid. In this particular example, when you try to compile the class, the compiler complains:

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

In other words, the variable i is not within scope any more. To get this program to work, you must move the declaration of the variable i outside the for loop, or use a separate variable. The latter case is shown here the corrected example:

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);
   }
}

Now the program produces the following results:

June month = 5

Since array accesses are zero based, June comes back as 5. (January is 0.)

Making Sense of the Java Class Libraries

Classes File and BufferedReader

In the December 2001 issue you learned about the FileInputStream and FileOutputStream classes for reading and writing to stream objects. Sometimes more information is needed, such as finding out if a file exists before writing to it, or speeding up the reading and writing processes.

The File class allows you to get information about a file and its directories, but does not have methods to read from or write to files. The File class has useful methods to do the following:

Check the properties of a file or directory:

  • getName
  • lastModified

Create directories:

  • mkdir
  • mkdirs

Get the path of a file or directory:

  • getAbsolutePath
  • getPath

Set or check the characteristics of a file object:

  • setReadOnly
  • canWrite

The following application illustrates some of these methods:

// 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.");
        
     }
 }   

Once you've established that a file does exist and is readable, you can read the contents of the file a character at a time with the FileReader class, or better yet, wrap FileReader in BufferedReader. This is more efficient because it creates a temporary storage buffer and it reads in a block of characters.

BufferedReader is mainly used to wrap around a Reader object for its readLine method, which reads a line of text and returns it as a String. To do so follow these three steps:

  1. Declare a string variable as a reference to the text to be read.
  2. Create a BufferedReader object that takes a Reader object as an argument.
  3. Call readLine within a loop to step through each line in the file until null is returned.

The following example demonstrates this process and assumes you've created a file called 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);
          }
        }
    }

Program Challenge

ReadFile

The following program is used to display information about a File object whose name is passed in from the command line. If the file exists and is a normal file, its contents are displayed.

File closing happens within the try part of the try-catch. If an exception happens after the file is opened, the file doesn't close properly.

Change the scope of the BufferedReader variable below so that file closing happens in a finally clause for the try-catch block.

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);
      }
   }
}

Java Bits

More Programming Shortcuts

In the November 2001 issue, you learned about the use of for loops, and you learned about arrays in the July 2001 issue. Here, you learn to combine for loops and arrays for a frequently used programming short cut. This technique is often used to create a series GUI components.

As you learn GUI programming, you see code similar to this:

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();

and so forth to declare and initialize however many components the panel or application contains. Such declarations may require many lines of code and repetition of class names.

Instead, you can use for loops and arrays to do the same thing, eliminating the need for retyping or cutting and pasting.

The process is similar to listing declarations and instantiations with the variation of setting up arrays to do the work instead:

  • Set up variables for the arrays
  • Set up variables for the labels and text fields
  • Initialize each object by passing the array into a for loop
  • Add the objects to the panel by passing the array into a for loop

For instance, when creating an application with labels and text fields, begin with an array for the text:

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

Next, specify a variable to reference an array of four labels:

JLabel labels[4];

Then set up a variable reference for four text fields:

JTextField textfields[4];

In the class constructor, or from within a method, initialize each of the label and text field objects using a for loop.

The for loop initializes at 0, checks the length of the labels array by calling the length method, then steps through each label, passing each into the labels array in the next line where each is initialized as a JLabel object:

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

The for loop for the text fields works the same way:

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

Use a for loop to add each label and text field object to a panel. In addition, you can register each as a listener using the for loop:

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

The application below demonstrates these concepts to compile and run. Experiment with the code, adding more text to the String array and creating more labels and text fields:

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);
       }
 }

Some developers prefer to declare and initialize objects individually because it can make debugging easier while others prefer to save space and typing stress. Programming using either technique is correct and a matter of style and convenience.

New to the Programming Center

Building an Application, Part 3

Part 3 of this series introduces encapsulation, event handling basics, and inner classes, demonstrating how to retrieve user data and display it on a panel.

For More Information

December 2001 Supplement

November 2001 Supplement

Scope

Class File

FileInputStream and FileOutputStream

Lesson: I/O: Reading and Writing (but no 'rithmetic)

Class BufferedReader

How to Wrap a Stream

Java 2 Platform, Standard Edition
Product Family

New I/0 Functionality for Java 2 Standard Edition 1.4

J2SE, version 1.4 Summary of New Features and Enhancements

New to Java Programming Center
Building an Application Introduction

Program Challenge Solution

This is one possible solution to the Program Challenge:

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) {
         }
       }
     }
   }
}

Downloading the Java 2 Platform

For most Java development, you need the class libraries, compiler, tools, and runtime environment provided with the Java 2, Standard Edition (J2SE) development kit.

IMPORTANT: Please read our Terms of Use and Privacy policies:

Copyright 2002 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA

Have a question about programming? Use Java Online Support.

- Note -

Sun respects your online time and privacy. The Java Developer Connection mailing lists are used for internal Sun Microsystems purposes only. You have received this email because you elected to subscribe.

- Feedback -

Comments? Send your feedback on the New to Java Programming Center Supplement to: dana.nourie@sun.com

- Subscribe/Unsubscribe -

To subscribe, go to the subscriptions page, (https://softwarereg.sun.com/registration/developer/en_US/subscriptions), choose the newsletters you want to subscribe to and click Update

To unsubscribe, go to the subscriptions page, (https://softwarereg.sun.com/registration/developer/en_US/subscriptions), uncheck the appropriate check box, and click Update

This document is protected by copyright.

JDC New-to-Java Programming Center Supplement
February 2002

Sun, Sun Microsystems, Java and J2SE are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.