Java Advanced Placement Study Guide:  Type Conversion, Casting, Common Exceptions, Public Class Files, javadoc comments and Directives, and Null References

Sample question:  Explain the purpose of the terms @param and @return in the comments of a Java program.

Published: January 1,  2004
By Richard G. Baldwin

Questions

File JavaAP028.htm


Welcome

This is one in a miniseries of tutorial lessons designed to help you learn the essential features of Java object-oriented programming as identified by The College Board.

Purpose

The purpose of this miniseries is to help you study for the Advanced Placement Examinations designed by the College Board.

Once you understand everything in this miniseries, plus the material in the lessons that I published earlier on Java Data Structures, you should understand the Java programming features that the College Board considers essential for the first two semesters of object-oriented programming education at the university level.

Approach

These lessons provide questions, answers, and explanations designed to help you to understand the subset of Java features covered by the Java Advanced Placement Examinations (as of October, 2001).

Please see the first lesson in the miniseries entitled Java Advanced Placement Study Guide: Introduction to the Lessons, Primitive Types, for additional background information.  The previous lesson was entitled Java Advanced Placement Study Guide:  Comparing Objects, Packages, Import Directives, and Some Common Exceptions.

Supplementary material

In addition to the material in these lessons, I recommend that you also study the other lessons in my extensive collection of online Java tutorials, which are designed from a more conventional textbook approach.  You will find those lessons published at Gamelan.com.  However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there.  You will find a consolidated index at Baldwin's Java Programming Tutorials.

What is Included?

Click here for a preview of the Java programming features covered by this lesson.



1.  What output is produced by the following program?
public class Ap151{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap151

class Worker{
  void doIt(){
    Object refA = new MyClassA();
    Object refB = 
              (Object)(new MyClassB());
    System.out.print(refA);
    System.out.print(refB);
    System.out.println("");
  }//end doIt()
}// end class Worker

class MyClassA{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassA

class MyClassB{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassB

Answer and Explanation

2.  What output is produced by the following program?

public class Ap152{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap152

class Worker{
  void doIt(){
    Object ref1 = new MyClassA();
    Object ref2 = new MyClassB();
    System.out.print(ref1);
    
    MyClassB ref3 = (MyClassB)ref1;
    System.out.print(ref3);
    System.out.println("");
  }//end doIt()
}// end class Worker

class MyClassA{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassA

class MyClassB{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassB

Answer and Explanation

3.  What output is produced by the following program?

import java.util.Random;
import java.util.Date;

public class Ap153{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap153

class Worker{
  void doIt(){
    Random ref = new Random(
                 new Date().getTime());
    if(ref.nextBoolean()){
      throw new IllegalStateException();
    }else{
      System.out.println("OK");
    }//end else
  }//end doIt()
}// end class Worker

Answer and Explanation

4.  What output is produced by the following program?

import
    java.util.NoSuchElementException;
public class Ap154{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap154

class Worker{
  void doIt(){
    MyContainer ref = 
                     new MyContainer();
    ref.put(0,5);
    ref.put(1,10);
    ref.put(2,15);
    
    System.out.print(ref.get(0)+" ");
    System.out.print(ref.get(1)+" ");
    System.out.print(ref.get(2)+" ");
    System.out.print(ref.get(3)+" ");  

  }//end doIt()
}// end class Worker

class MyContainer{
  private int[] array = new int[3];
  
  public void put(int idx, int data){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException();
    }else{
      array[idx] = data;
    }//end else
  }//end put()
    
  public int get(int idx){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException();
    }else{
      return array[idx];
    }//end else
  }//end put()
    
}//end class MyContainer

Answer and Explanation

5.  The following source code is contained in a single file named Ap155.java

What output is produced by the program?

public class Ap155{
  public static void main(
                        String args[]){
    new Ap155a().doIt();
  }//end main()
}//end class Ap155

public class Ap155a{
  void doIt(){
    System.out.println("OK");
  }//end doIt()
}// end class Ap155a

Answer and Explanation

6.  A Java application consists of the two source files shown below, having names of AP156.java and AP156a.java

What output is produced by this program?

public class Ap156{
  public static void main(
                        String args[]){
    new Ap156a().doIt();
  }//end main()
}//end class Ap156
public class Ap156a{
  void doIt(){
    System.out.println("OK");
  }//end doIt()
}// end class Ap156a

Answer and Explanation

7.  Explain the purpose of the boldface terms @param and @return in the following program.  Also explain any of the other terms that make sense to you.
 
public class Ap157{
    
/**
* Returns the character at the 
* specified index. An index ranges from
* <code>0</code> to 
* <code>length() - 1</code>.
*
* @param  index  index of desired 
* character.
* @return  the desired character.
*/
  public char charAt(int index) {
    //Note, this method is not intended
    // to be operational.  Rather, it
    // ...
    return 'a';//return dummy char
  }//end charAt method
}//end class

Answer and Explanation

8.  What output is produced by the following program?

public class Ap158{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap158

class Worker{
  void doIt(){
    char[] ref;
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref);
  }//end doIt()
}// end class Worker

Answer and Explanation

9.  What output is produced by the following program?

public class Ap159{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap159

class Worker{
  void doIt(){
    char[] ref = null;
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref);
  }//end doIt()
}// end class Worker

Answer and Explanation

10.  What output is produced by the following program?

public class Ap160{
  public static void main(
                        String args[]){
    new Worker().doIt();
  }//end main()
}//end class Ap160

class Worker{
  void doIt(){
    char[] ref = {'J','o','e'};
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref); 
  }//end doIt()
}// end class Worker

Answer and Explanation
 



Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java and XML. In addition to the many platform-independent benefits of Java applications, he believes that a combination of Java and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two.  He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin.richard@iname.com


What is Included?

According to the subset document,



Answers and Explanations

Answer 10

C.  Joe Tom

Back to Question 10

Explanation 10

This is an upgrade to the program from Question 9.

Success at last

The boldface code in the following fragment resolves the compilation problem from Question 8 and the runtime problem from Question 9.
 
  void doIt(){
    char[] ref = {'J','o','e'};
    System.out.print(ref);
    System.out.print(" ");
    ref[0] = 'T';
    ref[1] = 'o';
    ref[2] = 'm';
    System.out.println(ref); 
  }//end doIt()

Simply initializing the local reference variable named ref satisfies the compiler, making it possible to compile the program.

Initializing the local reference variable named ref with a reference to a valid array object eliminates the NullPointerException that was experienced in Question 9.

Printing the contents of the array object

The print statement passes the reference variable to the print() method.  The print() method finds that the reference variable refers to a valid object (instead of containing null as was the case in Question 9) and behaves accordingly.

The print statement causes the initialized contents of the array object to be displayed.  Then those contents are replaced with a new set of characters.  The println statement causes the new characters to be displayed.
 

Answer 9

B.  Runtime Error

Back to Question 9

Explanation 9

Purposely initializing a local variable

This is an update to the program from Question 8.  The boldface code in the following fragment solves the compilation problem identified in Question 8.
 
  void doIt(){
    char[] ref = null;

In particular, initializing the value of the reference variable named ref satisfies the compiler and makes it possible to compile the program.

A NullPointerException

However, there is still a problem, which causes a runtime error.

The following statement attempts to use the reference variable named ref to print something on the screen.  This results, among other things, in an attempt to invoke the toString() method on the reference.  However, the reference doesn't refer to an object.  Rather, it contains the value null.
 
    System.out.print(ref);

The result is a runtime error with the following infamous NullPointerException message appearing on the screen:

java.lang.NullPointerException
 at java.io.Writer.write(Writer.java:107)
 at java.io.PrintStream.write(PrintStream.java:245)
 at java.io.PrintStream.print(PrintStream.java:396)
 at Worker.doIt(Ap159.java:22)
 at Ap159.main(Ap159.java:15)
 

Answer 8

A.  Compiler Error

Back to Question 8

Explanation 8

Garbage in, garbage out

Earlier programming languages, notably C and C++ allowed you to inadvertently write programs that process the garbage left in memory by previous programs running there.  This happens when the C or C++ programmer fails to properly initialize variables, allowing them to contain left-over garbage from memory.

Member variables are automatically initialized to default values

That is not possible in Java.  All member variables in a Java object are automatically initialized to a default value if you don't write the code to initialize them to some other value.

Local variables are not automatically initialized

Local variables are not automatically initialized.  However, your program will not compile if you write code that attempts to fetch and use a value in a local variable that hasn't been initialized or had a value assigned to it.

Print an uninitialized local variable

The boldface statement in the following code fragment attempts to fetch and print a value using the uninitialized local variable named ref.
 
  void doIt(){
    char[] ref;
    System.out.print(ref);

As a result, the program refuses to compile, displaying the following error message under JDK 1.3.

Ap158.java:23: variable ref might not have been initialized
    System.out.print(ref);

Answer 7

See explanation below.

Back to Question 7

Explanation 7

The javadoc.exe program

When you download the JDK from Sun, you receive a program named javadoc.exe in addition to several other programs.

The purpose of the javadoc program is to help you to document the Java programs that you write.  You create the documentation by running the javadoc program and specifying your source file as a command-line parameter.  For example, you can generate documentation for this program by entering the following at the command line.

javadoc Ap157.java

Produces HTML files as output

This will produce a large number of related HTML files containing documentation for the class named Ap157.java.  The primary HTML file is named Ap157.html.

(As a labor saving device, you can also specify a group of input files to the javadoc program, using wildcard characters as appropriate, to cause the program to produce documentation files for each of the input files in a single run.)
Special documentation comments and directives

If you include comments in your source code that begin with /** and end with */ they will be picked up by the javadoc program and become part of the documentation.

In addition to plain comments, you can also enter a variety of special directives to the javadoc program as shown in the following program.
 
public class Ap157{
    
/**
* Returns the character at the 
* specified index. An index ranges from
* <code>0</code> to 
* <code>length() - 1</code>.
*
* @param  index  index of desired 
* character.
* @return  the desired character.
*/
  public char charAt(int index) {
    //Note, this method is not intended
    // to be operational.  Rather, it
    // is intended solely to illustrate
    // the generation of javadoc
    // documentation for the parameter
    // and the return value.
    return 'a';//return dummy char
  }//end charAt method
}//end class

The @param and @return directives

The @param and @return directives in the source code shown above are used by the javadoc program for documenting information about parameters passed to and information returned from the method named charAt().  The method definition follows the special javadoc comment.

The javadoc program output

Click here to view one of the html files produced by running the above program through javadoc.  Try to correlate the information in the javadoc comments and directives above with the contents of the documentation file.

(Note that this is only one of many related files produced in this documentation process.  To view all of the files, you will need to run the javadoc program yourself.  Note also that I changed the name of this file from AP157.html to JavaAP028a.htm to retain name consistency in the publishing process.  The output file name produced by the javadoc program was AP157.html.)

Answer 6

C.  OK

Back to Question 6

Explanation 6

Public classes in separate files

This program meets the requirement identified in Question 5.  In particular, this program defines two public classes.  The source code for each public class is stored in a separate file.  Thus, the program compiles and executes successfully, producing the text OK on the screen.

Answer 5

A.  Compiler Error

Back to Question 5

Explanation 5

Public classes in separate files

Java requires that the source code for every public class be contained in a separate file.  In this case, the source code for two public classes was contained in a single file.  The following compiler error was produced by JDK 1.3:

Ap155.java:18: class Ap155a is public, should be declared in a file named Ap155a.java
public class Ap155a{

Answer 4

This program produces both of the following: Back to Question 4

Explanation 4

The NoSuchElementException

This program defines, creates, and uses a very simple container object for the purpose of illustrating the NoSuchElementException.

The code in the following fragment shows the beginning of a class named MyContainer from which the container object is instantiated.
 
class MyContainer{
  private int[] array = new int[3];
  
  public void put(int idx, int data){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException()
;
    }else{
      array[idx] = data;
    }//end else
  }//end put()

A wrapper for an array object

This class is essentially a wrapper for a simple array object of type int.  An object of the class provides a method named put(), which can be used to store an int value into the array.  The put() method receives two parameters.  The first parameter specifies the index of the element where the value of the second parameter is to be stored.

Throw NoSuchElementException on index out of bounds

The put() method tests to confirm that the specified index is within the positive bounds of the array.  If not, it uses the throw keyword to throw an exception of the type NoSuchElementException.  Otherwise, it stores the incoming data value in the specified index position in the array.

(Note that a negative index will cause an ArrayIndexOutOfBoundsException instead of a NoSuchElementException to be thrown.)
The get method

An object of the MyContainer class also provides a get() method that can be used to retrieve the value stored in a specified index.
 
  public int get(int idx){
    if(idx > (array.length-1)){
      throw new 
              NoSuchElementException()
;
    }else{
      return array[idx];
    }//end else
  }//end put()

The get() method also tests to confirm that the specified index is within the positive bounds of the array.  If not, it throws an exception of the type NoSuchElementException.  Otherwise, it returns the value stored in the specified index of the array.

(As noted earlier, a negative index will cause an ArrayIndexOutOfBoundsException instead of a NoSuchElementException to be thrown.)
The NoSuchElementException

Thus, this container class illustrates the general intended purpose of the NoSuchElementException.

Instantiate and populate a container

The remainder of the program simply exercises the container.  The code in the following fragment instantiates a new container, and uses the put() method to populate each of its three available elements with the values 5, 10, and 15.
 
  void doIt(){
    MyContainer ref = 
                     new MyContainer();
    ref.put(0,5);
    ref.put(1,10);
    ref.put(2,15);

Get and display the data in the container

Then the code in the next fragment uses the get() method to get and display the values in each of the three elements, causing the following text to appear on the screen:

5 10 15
 
    System.out.print(ref.get(0)+" ");
    System.out.print(ref.get(1)+" ");
    System.out.print(ref.get(2)+" ");

One step too far

Finally, the code in the next fragment goes one step too far and attempts to get a value from index 3, which is outside the bounds of the container.
 
    System.out.print(ref.get(3)+" ");

This causes the get() method of the container object to throw a NoSuchElementException.  The program was not designed to handle this exception, so this causes the program to abort with the following text showing on the screen:

5 10 15 java.util.NoSuchElementException
 at MyContainer.get(Ap154.java:49)
 at Worker.doIt(Ap154.java:30)
 at Ap154.main(Ap154.java:15)

(Note that the values of 5, 10, and 15 were displayed on the screen before the program aborted and displayed the error message.)

Answer 3

This program can produce either of the following depending on the value produced by a random boolean value generator:


Back to Question 3

Explanation 3

Throwing an exception

This program illustrates the use of the throw keyword to throw an exception.

(Note that the throw keyword is different from the throws keyword.)
Throw an exception if random boolean value is true

A random boolean value is obtained.  If the value is true, the program throws an IllegalStateException and aborts with the following message on the screen:

java.lang.IllegalStateException
 at Worker.doIt(Ap153.java:29)
 at Ap153.main(Ap153.java:20)

If the random boolean value is false, the program runs to completion, displaying the text OK on the screen.

Instantiate a Random object

The following code fragment instantiates a new object of the Random class and stores the object's reference in a reference variable named ref.
 
  void doIt(){
    Random ref = new Random(
                 new Date().getTime());

I'm not going to go into a lot of detail about the Random class.  Suffice it to say that an object of this class provides methods, which will return a pseudo random sequence of values upon successive invocations.  You might think of this object as a random value generator.

Seeding the random generator

The constructor for the class accepts a long integer as the seed for the sequence.

(Two Random objects instantiated using the same seed will produce the same sequence of values.)
In this case, I obtained the time in milliseconds, relative to January 1, 1970, as a long integer, and provided that value as the seed.  Thus, if you run the program two times in succession, with a time delay of at least one millisecond in between, the random sequences will be different.

Get a random boolean value

The code in the next fragment invokes the nextBoolean() method on the Random object to obtain a random boolean value.
 
    if(ref.nextBoolean()){
      throw new IllegalStateException();

Throw an exception

If the boolean value obtained in the above fragment is true, the code instantiates a new object of the IllegalStateException class, and uses the throw keyword to throw an exception of this type.

Program aborts

The program was not designed to gracefully handle such an exception.  Therefore the program aborts, displaying the error message shown earlier.

Don't throw an exception

The code in the next fragment shows that if the boolean value tested above is false, the program will display the text OK and run successfully to completion.
 
    }else{
      System.out.println("OK");
    }//end else
  }//end doIt()

You may need to run the program several times to see both possibilities.

Answer 2

The answer is both of the following:


Back to Question 2

Explanation 2

Cast is allowable ...

It is allowable, but not necessary, to cast the type of an object's reference toward the root of the inheritance hierarchy.

It is also allowable to cast the type of an object's reference along the inheritance hierarchy toward the actual class from which the object was instantiated.

Cast is not allowable ...

However, (excluding interface type casts), it is not allowable to cast the type of an object's reference in ways that are not related in a subclass-superclass inheritance sense.  For example, you cannot cast the type of an object's reference to the type of a sibling of that object.

Two sibling classes

The code in the following fragment defines two simple classes named MyClassA and MyClassB.  By default, each of these classes extends the class named Object.  Therefore, neither is a superclass of the other.  Rather, they are siblings.
 
class MyClassA{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassA

class MyClassB{
  public String toString(){
    return "OK ";
  }//end test()
}//end class MyClassB

Instantiate one object from each sibling class

The code in the next fragment instantiates one object from each of the above classes, and stores references to those objects in reference variables of type Object.

Then the code causes the overridden toString() method of one of the objects to be invoked by passing that object's reference to the print() method.
 
  void doIt(){
    Object ref1 = new MyClassA();
    Object ref2 = new MyClassB();
    System.out.print(ref1);

The code in the above fragment causes the text OK to appear on the screen.

Try to cast to a sibling class type

At this point, the reference variable named ref1 holds a reference to an object of type MyClassA.  The reference is being held as type Object.

The statement in the next fragment attempts to cast that reference to type MyClassB, which class is a sibling of the class named MyClassA.
 
    MyClassB ref3 = (MyClassB)ref1;

A ClassCastException

The above statement causes a ClassCastException to be thrown, which in turn causes the program to abort.  The screen output is shown below:

OK java.lang.ClassCastException:MyClassA
 at Worker.doIt(Ap152.java:24)
 at Ap152.main(Ap152.java:14)

(Note that the text OK appeared on the screen before the program aborted and displayed diagnostic information on the screen.)

Answer 1

C.  OK OK

Back to Question 1

Explanation 1

Type conversion

This program illustrates type conversion up the inheritance hierarchy, both with and without a cast.

Store object's reference as type Object

The following fragment instantiates a new object of the class named MyClassA, and stores that object's reference in a reference variable of type Object.  This demonstrates that you can store an object's reference in a reference variable whose type is a superclass of the class from which the object was instantiated, with no cast required.
 
class Worker{
  void doIt(){
    Object refA = new MyClassA();

Cast object's reference to type Object

The code in the next fragment instantiates an object of the class named MyClassB, and stores the object's reference in a reference variable of type Object, after first casting the reference to type Object.  This, and the previous fragment demonstrate that while it is allowable to cast a reference to the superclass type before storing it in a superclass reference variable, such a cast is not required.
 
    Object refB = 
              (Object)(new MyClassB());

Type conversion and assignment compatibility

This is part of a larger overall topic commonly referred to as type conversion.  It also touches the fringes of something that is commonly referred to as assignment-compatibility.

Automatic type conversions

Some types of type conversions happen automatically.  For example, you can assign a value of type byte to a variable of type int and the type conversion will take place automatically.

Cast is required for narrowing conversions

However, if you attempt to assign a value of type int to a variable of type byte, the assignment will not take place automatically.  Rather, the compiler requires you to provide a cast to confirm that you accept responsibility for the conversion, which in the case of int to byte could result in the corruption of data.

Automatic conversions up the inheritance hierarchy

When working with objects, type conversion takes place automatically for conversions in the direction of the root of the inheritance hierarchy.  Therefore, conversion from any class type to type Object happen automatically.  However, conversions in the direction away from the root require a cast.

(Conversion from any class type to any superclass of that class also happens automatically.)
Polymorphic behavior

The code in the next fragment uses polymorphic behavior to display the contents of the two String objects.
 
    System.out.print(refA);
    System.out.print(refB);

No cast required

This works without the use of a cast because the print() method invokes the toString() method on any object's reference that it receives as an incoming parameter.  The toString() method is defined in the Object class, and overridden in the String class.  Polymorphic behavior dictates that in such a situation, the version of the method belonging to the object will be invoked regardless of the type of the reference variable holding the reference to the object.

When would a cast be required?

Had the program attempted to invoke a method on the reference that is not defined in the Object, class, it would have been necessary to cast the reference down the inheritance hierarchy in order to successfully invoke the method.



Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java and XML. In addition to the many platform-independent benefits of Java applications, he believes that a combination of Java and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects involving Java, XML, or a combination of the two.  He frequently provides onsite Java and/or XML training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Java Programming Tutorials, which has gained a worldwide following among experienced and aspiring Java programmers. He has also published articles on Java Programming in Java Pro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin.richard@iname.com

-end-