Published: March 20, 2002
By Richard G. Baldwin
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: Method Overloading.
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.
public class Ap090{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = NewClass(); System.out.println(obj); }//end makeObj() }// end class class NewClass{ public String toString(){ return "An Object"; }//end toString() }//end NewClass |
2. What output is produced by the following program?
public class Ap091{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(); System.out.println(obj); }//end makeObj() }// end class Class NewClass{ public String toString(){ return "An Object"; }//end toString() }//end NewClass |
3. What output is produced by the following program?
public class Ap092{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(); System.out.println(obj); }//end makeObj() }// end class class NewClass{ public String toString(){ return "An Object"; }//end toString() }//end NewClass |
4. What output is produced by the following program?
public class Ap093{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(); System.out.println(obj); }//end makeObj() }// end class class NewClass{ private int x = 2; public NewClass(int x){ this.x = x; }//end constructor public String toString(){ return "Object containing " + x; }//end toString() }//end NewClass |
5. What output is produced by the following program?
public class Ap094{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ Subclass obj = new Subclass(); System.out.println(obj); }//end makeObj() }// end class class Superclass{ private int x; public Superclass(int x){ this.x = x; }//end constructor public String toString(){ return "Object containing " + x; }//end toString() public void setX(int x){ this.x = x; }//end setX() }//end Superclass class Subclass extends Superclass{ public Subclass(){ setX(2); }//end noarg constructor }//end Subclass |
6. What output is produced by the following program?
public class Ap095{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(5); System.out.println(obj); }//end makeObj() }// end class class NewClass{ private int x = 2; public NewClass(){ }//end constructor public NewClass(int x){ this.x = x; }//end constructor public String toString(){ return "Object containing " + x; }//end toString() }//end NewClass |
7. What output is produced by the following program?
public class Ap096{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(); System.out.println(obj); }//end makeObj() }// end class class NewClass{ private int x; private double y; private boolean z; public String toString(){ return "Object containing " + x + ", " + y + ", " + z; }//end toString() }//end NewClass |
8. What output is produced by the following program?
public class Ap097{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(5); System.out.println(obj.getX()); }//end makeObj() }// end class class NewClass{ private int x = 2; public NewClass(){ }//end constructor public NewClass(int x){ this.x = x; }//end constructor public int getX(){ return x; }//end getX() }//end NewClass |
9. What output is produced by the following program?
public class Ap098{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(); obj.setX(10); System.out.println(obj.getX()); }//end makeObj() }// end class class NewClass{ private int y; public void setX(int y){ this.y = y; }//end setX() public int getX(){ return y; }//end getX() }//end NewClass |
10. What output is produced by the following program?
public class Ap099{ public static void main( String args[]){ new Worker().makeObj(); }//end main() }//end class definition class Worker{ public void makeObj(){ NewClass obj = new NewClass(5); obj.x = 10; System.out.println(obj.x); }//end makeObj() }// end class class NewClass{ private int x = 2; public NewClass(){ }//end constructor public NewClass(int x){ this.x = x; }//end constructor public void setX(int x){ this.x = x; }//end setX() public int getX(){ return x; }//end getX() }//end NewClass |
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.
"Classes: Students are expected to construct objects with the new operator, to supply construction parameters, and to invoke accessor and modifier methods. For the A exam, students are expected to modify existing classes (by adding or modifying methods and instance variables). For the AB exam, students are expected to design their own classes."
The code in the following fragment attempts to
ignore the setter and getter methods and directly access
the private instance variable named x in the object referred
to by the reference variable named obj.
obj.x = 10; System.out.println(obj.x); |
This produces a compiler error. The compiler error produced by JDK 1.3 is reproduced below.
Ap099.java:19: x has private access in
NewClass
obj.x = 10;
^
Ap099.java:20: x has private access in
NewClass
System.out.println(obj.x);
^
This is a very simple program that uses a setter (modifier or mutator) method named setX() to set the value 10 in a property named x that just happens to be stored in an instance variable named y in an object instantiated from the class named NewClass..
The program also uses a getter (accessor) method named getX() to get and display the value of the property named x.
For reasons that I won't go into here, good object-oriented design principles state that in almost all cases where an instance variable is not declared to be final, it should be declared private. (A final variable behaves like a constant.)
What is private access?
When an instance variable is declared private, it is accessible only by methods of the class in which it is defined. Therefore, the only way that the "outside world" can gain access to a private instance variable is by going through an (usually public) instance method of the object.
Accessor, modifier, mutator, setter, and getter methods
Historically, methods that have been defined for the purpose of exposing private instance variables to the outside world have been referred to as accessor and modifier methods. (Modifier methods are also sometimes called mutator methods.)
(Note that since the advent of Sun's JavaBeans Component design patterns, these methods have also come to be known as getter methods and setter methods in deference to the design-pattern naming conventions for the methods.)A private instance variable with an initializer
The class named NewClass declares a private
instance variable named x and initializes its value to 2, as shown
in the following code fragment:
private int x = 2; |
Two constructors
The class contains both a noarg constructor
and a parameterized constructor as shown in the following fragment:
public NewClass(){ }//end constructor public NewClass(int x){ this.x = x; }//end constructor |
Invoking the noarg constructor
If an object of the class is instantiated by invoking the noarg constructor, the initial value of 2 remains intact, and that object contains an instance variable with an initial value of 2.
Invoking the parameterized constructor
If an object of the class is instantiated by invoking
the parameterized constructor, the initial value of 2 is overwritten by
the value of the incoming parameter to the parameterized constructor.
In this case, that value is 5, because the object is instantiated by the
following code fragment, which passes the literal value 5 to the parameterized
constructor. Thus, the initial value of the instance variable in
that object is 5.
NewClass obj = new NewClass(5); |
A getter method
Because the instance variable named x is private, it cannot be accessed directly for display by the code in the makeObj() method of the Worker class. However, the NewClass class provides the following getter or accessor method that can be used to get the value stored in the instance variable.
(The name of this method complies with JavaBeans design patterns. If you examine the name carefully, you will see why Java programmers often refer to methods like this as getter methods.)
public int getX(){ return x; }//end getX() |
Invoking the getter method
Finally, the second statement in the following
code fragment invokes the getter method on the NewClass object to
get and display the value of the instance variable named x.
NewClass obj = new NewClass(5); System.out.println(obj.getX()); |
The purpose of this question is to confirm that you understand the default initialization of instance variables in an object when you don't write code to cause the initialization of the instance variable to differ from the default.
(Although I don't believe that the AP CS exam covers default initialization, I believe that you should understand it anyway if you plan to write Java programs.)
By default, all instance variables in a new object are initialized
with default values if you don't provide a constructor (or other mechanism)
that causes them to be initialized differently from the default.
This program illustrates the straightforward use of a parameterized constructor.
The class named NewClass defines a parameterized constructor that requires an incoming parameter of type int.
(For good design practice, the class also defines a noarg constructor, even though it isn't actually used in this program. This makes it available if needed later when someone extends the class.)Both constructors are shown in the following code fragment.
public NewClass(){ }//end constructor public NewClass(int x){ this.x = x; }//end constructor |
The parameterized constructor stores its incoming parameter named x in an instance variable of the class, also named x.
(The use of the keyword this is required in this case to eliminate the ambiguity of having a local parameter with the same name as an instance variable. Although this syntax is apparently not covered on the AP CS exam, this is very common Java syntax that you should recognize and understand.)Invoke the parameterized constructor
The following code fragment invokes the parameterized
constructor, passing the literal int value of 5 as a parameter.
NewClass obj = new NewClass(5); |
Hopefully you will have no difficulty understanding the remaining code in the program that causes the value stored in the instance variable named x to be displayed on the computer screen.
The discussion for a previous question explained that if you define any constructor in a new class, you must define all constructors that will ever be needed for that class. When you define one or more constructors, the default noarg constructor is no longer provided by the system on your behalf.
The previous question illustrated a simple manifestation of a problem arising from the failure to define a noarg constructor that would be needed later. The reason that it was needed later was that the programmer attempted to explicitly use the non-existent noarg constructor to create an instance of the class.
A more subtle problem
The problem in this program is more subtle. Unless you (or the programmer of the superclasses) specifically write code to cause the system to behave otherwise, each time you instantiate an object of a class, the system automatically invokes the noarg constructor on superclasses of that class up to the class named Object. If one or more of those superclasses don't have a noarg constructor, unless the author of the subclass constructor has taken this into account, the program will fail to compile.
Invoking a non-existing noarg constructor
This program attempts to instantiate an object of a class named Subclass, which extends a class named Superclass. By default, when attempting to instantiate the object, the system will attempt to invoke a noarg constructor on the superclass.
Superclass has no noarg constructor
The Superclass class defines a parameterized constructor that requires a single incoming parameter of type int. However, it does not also define a noarg constructor. Because the parameterized constructor is defined, the default noarg constructor does not exist. As a result, JDK 1.3 produces the following compiler error:
Ap094.java:40: cannot resolve symbol
symbol : constructor Superclass ()
location: class Superclass
public Subclass(){
Java uses the following kinds of constructors:
You are not required to define a constructor when you define a new class.
If you don't define a constructor for your new class, a default constructor
will be provided on your behalf. This constructor requires no argument,
and it is typically used in conjunction with the
new operator to
create an instance of the class using statements such as the following:
NewClass obj = new NewClass(); |
The default constructor
The default constructor typically does the following:
As long as you are satisfied with the default initialization of all instance variables belonging to the object, there is no need for you to define a constructor of your own.
However, in the event that you have initialization needs that are not satisfied by the default constructor, you can define your own constructor. Your new constructor may or may not require arguments. (In case you have forgotten, the name of the constructor is always the same of the name of the class in which it is defined.)
A non-default noarg constructor
If your new constructor doesn't require arguments, you will typically write code that performs initialization in ways that differ from the default initialization. For example, you might decide that a particular double instance variable needs to be initialized with a random number each time a new object is instantiated. You could do that with a constructor of your own design that doesn't take arguments by defining the constructor to get initialization values from the random() method of the Math class.
A parameterized constructor
If your new constructor does take arguments, (a parameterized constructor) you can define as many overloaded versions as you need. Each overloaded version must have a formal argument list that differs from the formal argument list of all of the other overloaded constructors for that class.
(The rules governing the argument list for overloaded constructors are similar to the rules governing the argument list for overloaded methods, which were discussed in a previous lesson.)Use parameter values for initialization
Typically you will define your parameterized constructors to initialize some or all of the instance variables of the new object using values passed to the constructor as parameters.
What else can a constructor do?
You can also cause your new constructor to do other things if you so choose. For example, if you know how to do so, you could cause your constructor (with or without parameters) to play an audio clip each time a new object is instantiated. You could use a parameter to determine which audio clip to play in each particular instance.
The punch line
So far, everything that I have said is background information for this program. Here is the punch line insofar as this program is concerned.
If you define any constructor in your new class, you must define all constructors that your new class will ever need.If you define any constructor, the default constructor is no longer provided on your behalf. If your new class needs a noarg constructor (and it probably does, but that may not become apparent until later when you or someone else extends your class) you must define the noarg version in addition to the other overloaded versions that you define.
A violation of the rule
This program violated the cardinal rule shown
above. It defined the parameterized constructor for the class named
NewClass
shown below
public NewClass(int x){ this.x = x; }//end constructor |
However, the program did not also define a noarg constructor for the NewClass class.
Invoking the noarg constructor
The code in the makeObj() method of the
Worker
class attempted to instantiate a new object using the following code:
NewClass obj = new NewClass(); |
Since the class definition didn't contain a definition for a noarg constructor, the following compiler error was produced by JDK 1.3.
Ap093.java:18: cannot resolve symbol
symbol : constructor NewClass
()
location: class NewClass
NewClass obj = new
NewClass();
Did you identify the errors in the previous two programs before looking at the answers?
This program declares the class named NewClass correctly and uses the new operator correctly in conjunction with the default noarg constructor for the NewClass class to create a new instance of the class (an object).
Making the class public
One of the things that I could do differently
to make this program more consistent with the intent of the AP CS exam
would be to make the declaration for the NewClass class public
(as
shown in the following code fragment).
public class NewClass{ public String toString(){ return "An Object"; }//end toString() }//end NewClass |
I am a little lazy
The reason that I didn't declare this class public (and haven't done so throughout this series of lessons) is because the source code for all public classes and interfaces must be in separate files. While that is probably a good requirement for large programming projects, it is overkill for simple little programs like I am presenting in this series of tutorial lessons.
Dealing with multiple files
Therefore, in order to avoid the hassle of having to deal with multiple source code files for every program, I have been using package access for class definitions other than the controlling class (the controlling class is declared public). Although I won't get into the details at this point, when a class is not declared public, it is common to say that it has package access instead of public access.
Java keywords must be written exactly as specified. The keyword class cannot be written as Class, which is the problem with this program.
The inappropriate use of the upper-case C in the keyword Class caused the following compiler error.
Ap091.java:25: 'class' or 'interface' expected
Class NewClass{
The solution to the problem
This problem can be resolved by replacing the first character in the
keyword class in the following code fragment with a lower-case character.
Class NewClass{ public String toString(){ return "An Object"; }//end toString() }//end NewClass |
There are several ways to instantiate an object in Java:
What you cannot do!
You cannot instantiate a new object using code like the following code
fragment that was extracted from this program.
NewClass obj = NewClass(); |
This program produces the following compiler error:
Ap090.java:18: cannot resolve symbol
symbol : method NewClass ()
location: class Worker
NewClass obj = NewClass();
The solution to the problem
This problem can be solved by inserting the new operator to the
left of the constructor as shown in the following code fragment.
NewClass obj = new NewClass(); |
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.
-end-