Title: Miscellaneous
Course: CPS 161: An Intro to Programming with Java - DL MM MASTER

StringTokenizer

When you need to break a string apart into pieces, the StringTokenizer can simplify your life.

I would recommend that you compile and execute the following program to get an idea what this class does for you. In effect, it returns words in a string where delimiters can be defined. The different StringTokenizer constructors affect how the delimiters are defined. See the description of the Constructors below.

The StringTokenizer is a class in the package java.util. The StringTokenizer is derived from Enumeration which is an older form of an Iterator. We will encounter this concept in detail when we cover Collection classes. The 3 methods we are demonstrating in the following example are:

1. countTokens - the number of tokens in the parsed string
2. hasMoreElements - returns true as long as there are more tokens
3. nextElement - returns the next token as an Object class
4. nextToken - returns the next token as a String

StringTokenizer Constructors:

StringTokenizer(String) - default delimiter definition of just white space (space, tab, newlines)

StringTokenizer(String, delimString) - the second parameter contains all of the characters that act as delimiters

StringTokenizer(String, delimString, true) - The third parameter set to true indicates we want to get the delimiters returned as tokens as they are recognized.


import java.util.*;
class Tokens
{
   public static void main(String[] args)
   {
        String str = "Oats, Barley, and Wheat are examples of Grain. Apples and Pears are examples of Fruit.";


        System.out.println("Using StringTokenizer(String)");
        System.out.println(" -------------- ");

        StringTokenizer parse = new StringTokenizer(str);
        System.out.println("Number of tokens = " + parse.countTokens());
        while (parse.hasMoreElements())
            System.out.println(parse.nextElement());

        System.out.println("*******************************************");
        System.out.println("Using StringTokenizer(String, DelimString) ");
        System.out.println(" -------------- ");

        parse = new StringTokenizer(str, " ,.");
        System.out.println("Number of tokens = " + parse.countTokens());
        while (parse.hasMoreElements())
            System.out.println(parse.nextElement());

        System.out.println("*******************************************");
        System.out.println("Using StringTokenizer(String, DelimString, true) ");
        System.out.println(" -------------- ");

        parse = new StringTokenizer(str, " ,.", true);
        System.out.println("Number of tokens = " + parse.countTokens());
        while (parse.hasMoreElements())
            System.out.println(parse.nextToken());

   }
}



Packages

To start out, it is necessary to define the concept of a Package. A package is an entity that groups classes and interfaces together. Packages perform the following functions:

- Organize and group classes, normally by functions. For example, the java.awt package contains the classes with graphical components.
- Help to define access to variables and methods. For example, by using the access modifier protected only classes in the same package will have access to it.
- Make it easy to import other programmer's classes into your code, while keeping the code separate from your own.
- If no package is explicitly declared, Java places your classes into a default package.

For the time being we will defer the topic of how to create a package. At that time we will go over the CLASSPATH concept which goes along with it.

In general, the Java compiler makes packages available to your program when you request the Package through an import statement. For example:
import java.util.Math;

One package that is always available to you without asking for it is:
java.lang

Take a look at the online Java help files to see how the help system is organized according to Packages.

Import Statements

As mentioned earlier, Java creates Packages for related modules. Let's look at the different ways that I can get at the Date class which lives in a package known as java.util. If I don't use an import statement, I would need to write my code as follows:


class Mytime
{
public static void main(String[] args)
    {
        java.util.Date now = new java.util.Date();
        System.out.println("Time = " + now);
    }
}


This seems like a lot of extra typing. This especially awkward when the number of classes in other packages is large. That's why you want to consider import statements. Here are 2 alternatives using import statements:


import java.util.Date;
class Mytime2
{
public static void main(String[] args)
    {
        Date now = new Date();
        System.out.println("Time = " + now);
    }
}


OR:


import java.util.*;
class Mytime2
{
public static void main(String[] args)
    {
        Date now = new Date();
        System.out.println("Time = " + now);
    }
}



java.util.* includes all of the classes in the java.util package.

Note that java.* does not do what you might think. The * doesn't recursively go down the package tree. The * only considers all of the classes in the top level tree node: java. By the way there are no classes pulled in by this import statement.

We will start out with a somewhat useful example using Packages. After covering this basic example, I want to defer the rest of the section until later in the course. I think it will make more sense to cover the details of this chapter after we have more Java under our belts.

At this stage, you may have noticed 2 things:

1. It's a pain in the xxx to type System.out.println everytime you want to generate output.
2. It would be nice to have the user type input through the keyboard.

We will solve item number one with a class called P. The second item will be solved with a class called MyInput. Now we could copy these classes to every directory where we want to work. But this seems like another bother. Alternatively, we could put these classes into a package called tools and import the package whenever we want to use this package.

Take a look at the tools Package.

By the way, for MyInput I'm going to sneek in some capability to read files as easily as reading the keyboard. We will use this later. Don't worry too much about the details inside of MyInput because will cover this when we cover Java I/O.

Here are the P.java and MyInput.java files that we are putting into the tools package. The main thing you need to see right now is the fact that both of these files start with the statement:
package tools;

The package statement must be the first executable statement.

Here is a test program that uses our tools package:


import tools.*;
class Test
{

    public static void main(String[] args)
    {
        String s;
        MyInput in = new MyInput();

        P.println("Enter your name:");
        s = in.get();   // read the keyboard
        P.println("echo: " + s);

        P.println("Enter your age:");
        s = in.get(); // read the keyboard
        P.println("echo:" + s);
    }
}



Here are the rules for making this work:

1. You need to set the CLASSPATH environment variable to contain the list of directories where packages can be found.
2. Hanging off one of the CLASSPATH directories we will need a directory called tools which will contain the classes in our tools package.
3. The client program needs an appropriate import statement. Test.java is importing all classes in tools. It could have individually imported each class with:
import tools.P;
import tools.MyInput;

I'm going to assume we are on Linux now, but there is a very similar mechanism for a DOS environment.

Create the Test.java program in some directory say xyz. Then inside of directory xyz, create a directory named tools. Put the P.java and MyInput.java files in the tools directory.

Set your CLASSPATH environment variable with the statement (don't miss the period):
export CLASSPATH=.

Execute your test program.

This still isn't convenient because we don't want to create a tools directory everywhere we do java work. The solution is to put the tools directory in some common place. I have placed the P.java and MyInput.java in a directory named /usr/local/jdk/classes/tools. So we can issue a statement like:
export CLASSPATH=.:/usr/local/jdk/classes

I'm actually going to recommend that the CLASSPATH you setup is :
export CLASSPATH=.:$HOME/classes:/usr/local/jdk/classes

This classpath will allow you to create a directory called classes in your home directory where you can store your own personal packages.

With this statement, your Test program will still preferrentially grab your P.java and MyInput.java from your local xyz/tools directory (which is nice because you can test out new versions locally).

You can now rename your tools directory and Java will find the Common P.java and MyInput.java in the /usr/local/jdk/classes directory.

Take a look at the my_profile we setup at the beginning of the class. Hopefully, it makes a little more sense now. .

Access Rules:

1. If something is labeled Public, it is available to the whole world of Java as long as you properly setup your CLASSPATH and include proper import statements.
2. If you remove Public from a method and let the access default, then if you are in the same package the method is accessable. However, if you are in a different package then the method is private. Note that all classes in the same directory are considered in the same package. Its kind of like there is always a default package consisting of all of the classes in your current directory.
3. If you make a method Private, then you can never access this method outside of the class --- even if you are in the same package.

Try some of these access rules in the MyInput class. Change the Constructor that takes one parameter, or the Open routine and test out the above rules.

Access Modifiers:

Summary of Access Levels

Note that the following table only applies if the class is available to the user. In otherwords, if the class isn't marked as public and you are in another package, then you have no access even if the variable or method is labeled as public.

The following chart shows the access level permitted by each specifier.

Specifier | class | subclass | package | world
private | X |  |  |
protected | X | X | X |
public | X | X | X | X
default | X |  | X |

Package Example and Access Levels

dessert package


//: Cookie.java
// Creates a library
package dessert;


public class Cookie {
  public Cookie() {
   System.out.println("Cookie constructor");
  }

// The following call can only be accessed by classes
//  in the same package (dessert)

  void foo() { System.out.println("foo"); }

// The following call can be accessed by classes derived
//  from Cookie

  protected void fooProtected() { System.out.println("fooProtected");}
}
// **********************************************************
 //: DessertCookie.java
// Because we are in the same package as Cookie.java, we CAN access the foo
//   member function.


package dessert;
//Don't need:   import  dessert.*;

public class DessertCookie {
  Cookie theCookie = new Cookie();
  public DessertCookie() {
   System.out.println("DessertCookie constructor");
  }
  public void foo() {
    theCookie.foo(); // CAN access because we are in the same package
  }
}
// ***************************************



Using the dessert package


//: Dinner.java
// Uses the library:  This demonstrates the fact that we can't access
//   "Default" member functions if we aren't in the same package.
//   However, we can access the foo interface indirectly through a public
//   interface made available inside the desert package in the DesertCookie class


import dessert.*;

public class Dinner {
  public Dinner() {
   System.out.println("Dinner constructor");
  }
  public static void main(String[] args) {
    Cookie x = new Cookie();
    DessertCookie y = new DessertCookie();
    MyCookie z = new MyCookie();

    //! x.foo(); // Can't access  - - Only available inside of dessert package
    y.foo(); // CAN access - - indirect access through
                //  public interface inside of dessert package

    z.myfoo();
  }
}
class MyCookie extends Cookie{

    void myfoo()
    {
        // fooProtected is available to a derived class since
        // it's access is protected

        fooProtected();
    }
}







- In the normal directory where you do your Java work, create a directory by the name of dessert and download the following files into it:
Cookie.java - This class lives in the dessert package and contains a package routine foo and a protected routine fooProtected
DessertCookie.java - This class also lives in the dessert package, and creates an instance of the Cookie class. DessertCookie has a public foo routine. Note that because DessertCookie is in the same package(dessert) as Cookie, that the package routine foo in Cookie can be called.
- In the normal directory where you do your Java work, download the following file:
Dinner.java - This class is not in the dessert package, but imports the dessert package. In the Dinner class, you should observe the following:
  - Dinner cannot call the package foo routine in the Cookie class
  - A class MyCookie derived from Cookie can get to the fooProtected routine
  - Dinner can access the public foo routine in DessertCookie. Inside of the DessertCookie foo routine, we can then access the Cookie package foo routine.
- Compile and execute Dinner.java

Default Package Example

If you don't specify a package, then the default package consists of all files in the working directory.

Create the following Files:

Cake.java


//: Cake.java
// Accesses a class in a separate
// compilation unit. Note that the Pie.class file needs to be in this
// directory to qualify as being in the "Default Package".  The Pie
// constructor needs to either be public or "Default".

class Cake {
  public static void main(String[] args) {
    Pie x = new Pie();
    x.f();
  }
}


PieWrongName.java



//  This Class is used in the Cake.java class.

// Java source files are allowed to have at most 1 public class.
// The name of that class then dictates the name of the file as we
// have seen all through our class so far.

// However, in this file we have no public class, and
// we aren't forced to name the file after any class currently in this
// file.  Note that compiling this file will create a Pie.class file.
// If you think about it, you can see how this yields some compiler and
// loader efficiencies.

class Pie {
  void f() { System.out.println("Pie.f()"); }
}




- In your current directory download, create the files displayed above:
Cake.java and PieWrongName.java
- Try compiling the Cake.java file. The Cake class tries to access the Pie class. When the compiler tries to compile Cake.java, it will first look for Pie.class. If it doesn't exist, then the compiler will look for a Pie.java file to compile.
- You will need to explicitly compile PieWrongName.java. If the Pie class had been put in a file named Pie.java, then the compiling Cake.java would automatically compile Pie.java, because Cake.java needs a class named Pie. Compile Cake.java and execute it.
- The Pie class is defined in a file named PieWrongName.java. This is OK as long as the Pie class is not defined as public.
- Java source files are allowed to have at most 1 public class. The name of the one public class then dictates the name of the file as we have seen all through our class so far. Note that compiling PieWrongName.java will create a Pie.class file. If you think about it, you can see how this yields some compiler and loader efficiencies.

Object Casting

Consider the example we covered earlier:
Shape-Rectangle-Square-Circle

In this example, we have the following relationships:


           Object
             |
             |
             v
           Shape
           |    |
           |    |
           v    v
     Rectangle Circle
        |
        |
        v
     Square



General Rules for Object Casting

If you need a specific type of class. For example, you are calling some procedure and it is looking for some type of class like Object or Shape. In this case, its always OK to pass it a type of class that is subclassed (or derived )from the needed class. So if your need an Object or a Shape class, its OK to pass in a Circle, Rectangle or Square. No casting is needed. This makes sense, because you are providing more than was required and this is OK.

There are times when you have a collection of class instances that are declared to be of type Object, but actually originated from some subclassed (derived) class. In this case it is possible to cast the Object instance into something more derived such as a Square Object instance. If the Object originated from some other class, then an error will be found at Run Time.

The following concepts will become more meaningful when we discuss some of the collection classes such as the Vector class.


import exercise.*;
class Test
{
  public static void main (String[] args)
  {
    Square sq1 = new Square();
    Rectangle r1;
    Shape sh1;
    Object ob1;

    // The following will work with no cast
    r1 = sq1;
    sh1 = r1;
    sh1 = sq1;
    ob1 = r1;
    ob1 = sq1;


    System.out.println("Finished Class operations that work without a cast");

    // The following will work with a cast
    Object ob2 = new Square();
    sh1 = (Shape) ob2;
    r1 = (Rectangle)ob2;
    sq1 = (Square) ob2;

    System.out.println("Finished Class Operations that work with a cast");

    System.out.println("The next operation compiles, but blows up at runtime");

    Circle c1;
    c1 = (Circle)ob2;


  }
}


instanceof

In the above example, how do I deal with the fact that a cast operation can blow up?

Approach 1, is to surround the cast operation with try ... catch logic and catch the exception:
ClasscastException.
We will cover exception handling techniques later.

Approach 2, is to use the instanceof operator to determine when a cast is possible.

import exercise.*;
class Test
{
  public static void main (String[] args)
  {
    Square sq1 ;
    Rectangle r1;
    Object ob1;

    Object ob2 = new Square();
    if (ob2 instanceof Rectangle)
        r1 = (Rectangle)ob2;
      else
        System.out.println("ob2 is not an instanceof Rectangle");

    if (ob2 instanceof Square)
        sq1 = (Square) ob2;

     else
        System.out.println("ob2 is not an instanceof Square");


    Circle c1;
    if (ob2 instanceof Circle)
        c1 = (Circle)ob2;
      else
        System.out.println("ob2 is not an instanceof Circle");

  }
}


Impossible instanceof comparisons generate Compiler errors

The instanceof operator will only compile if it is possible for the object to actually be an instance of the referenced class. If your code compiles, then a runtime the instanceof operator will make the actual determination.

On the otherhand if it can be determined at compile time that there is no possibility, then a Compilation error will occur. For example, the following will generate a Compilation error:


import exercise.*;
class Test
{
  public static void main (String[] args)
  {
    Rectangle r1 = new Square();
    Circle c1;
    if (r1 instanceof Circle)// impossible --> Compile error
        System.out.println("r1 is an instanceof Circle");
      else
        System.out.println("r1 is not an instanceof Circle");
  }
}



Enumerated Types

A feature that was added to Java in release 1.5 was the enum reserved keyword and its associated enumerated types datastructure. Note that in the following example,

- WordDay acts like a class
- MONDAY, TUESDAY, etc. act like static classes like the Color red, blue, green, etc classes.
- The enumerated type has a toString() method that outputs the expected output (i.e. MONDAY, TUESDAY, etc.)

EnumDemo.java


public class EnumDemo
{
    enum WorkDay {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY};

    public static void main(String[] args)
    {
        WorkDay startDay = WorkDay.MONDAY;
        WorkDay endDay = WorkDay.FRIDAY;

        System.out.println("Work starts on " + startDay);
        System.out.println("Work ends on " + endDay);
    }
}


EnumSwitchDemo.java

In this example, note that I can

- use the names of the enumerated types in a switch statement without including Flavor.VANILLA
- valueOf can convert a string to the matching enumerated type


import java.util.Scanner;

public class EnumSwitchDemo
{
    enum Flavor {VANILLA, CHOCOLATE, STRAWBERRY};

    public static void main(String[] args)
    {
        Flavor favorite = null;
        Scanner keyboard = new Scanner(System.in);

        System.out.println("What is your favorite flavor?");
        String answer = keyboard.next();
        answer = answer.toUpperCase();
        favorite = Flavor.valueOf(answer);

        switch (favorite)
        {
            case VANILLA:
                System.out.println("Classic");
                break;
            case CHOCOLATE:
                System.out.println("Rich");
                break;
            default:
                System.out.println("I bet you said STRAWBERRY.");
                break;
        }
    }
}



EnumValuesDemo.java

If you want to know all of the enumerated types as an array, use the method:

values();


import java.util.Scanner;

public class EnumValuesDemo
{

    enum WorkDay {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY};

    public static void main(String[] args)
    {
        WorkDay[] day = WorkDay.values( );

        Scanner keyboard = new Scanner(System.in);
        double hours = 0, sum = 0;

        for (int i = 0; i < day.length; i++)
        {
            System.out.println("Enter hours worked for " + day[i]);
            hours = keyboard.nextDouble( );
            sum = sum + hours;
        }

        System.out.println("Total hours work = " + sum);
    }
}



Exercises:

1. Use the StringTokenizer class to split a string of words into separate words.
2. Write your own StringTokenizer Class using String classes only. Use your new class to solve the previous problem again (i.e. splitting a string of words into separate words).

Last Updated: April 19, 2008 9:14 PM