Questions
File JavaAP008.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, and successfully
complete, 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.
Hopefully, that will help you to take and successfully complete the
Advanced Placement Examinations.
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 lesson immediately
prior to this one was entitled Java Advanced Placement
Study Guide: Relational Operators, Increment Operator, and Control
Structures.
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?
- A. Compiler Error
- B. Runtime Error
- C. A
- D. B
- E. None of the above
public class Ap039{ public static void main( String args[]){ new Worker().doLogical(); }//end main() }//end class definition class Worker{ public void doLogical(){ int x = 5, y = 6; if((x > y) || (y < x/0)){ System.out.println("A"); }else{ System.out.println("B"); }//end else }//end doLogical() }//end class definition |
2. What output is produced by the following program?
- A. Compiler Error
- B. Runtime Error
- C. A
- D. B
- E. None of the above
public class Ap040{ public static void main( String args[]){ new Worker().doLogical(); }//end main() }//end class definition class Worker{ public void doLogical(){ int x = 5, y = 6; if((x < y) || (y < x/0)){ System.out.println("A"); }else{ System.out.println("B"); }//end else }//end doLogical() }//end class definition |
3. What output is produced by the following program?
- A. Compiler Error
- B. Runtime Error
- C. A
- D. B
- E. None of the above
public class Ap041{ public static void main( String args[]){ new Worker().doLogical(); }//end main() }//end class definition class Worker{ public void doLogical(){ int x = 5, y = 6; if(!(x < y) && !(y < x/0)){ System.out.println("A"); }else{ System.out.println("B"); }//end else }//end doLogical() }//end class definition |
4. What output is produced by the following program?
- A. Compiler Error
- B. Runtime Error
- C. true
- D. 1
- E. None of the above
public class Ap042{ public static void main( String args[]){ new Worker().doCast(); }//end main() }//end class definition class Worker{ public void doCast(){ boolean x = true; int y = (int)x; System.out.println(y); }//end doCast() }//end class definition |
5. What output is produced by the following program?
- A. Compiler Error
- B. Runtime Error
- C. 4 -4
- D. 3 -3
- E. None of the above
public class Ap043{ public static void main( String args[]){ new Worker().doCast(); }//end main() }//end class definition class Worker{ public void doCast(){ double w = 3.7; double x = -3.7; int y = (int)w; int z = (int)x; System.out.println(y + " " + z); }//end doCast() }//end class definition |
6. What output is produced by the following program?
- A. Compiler Error
- B. Runtime Error
- C. 4 -3
- D. 3 -4
- E. None of the above
public class Ap044{ public static void main( String args[]){ new Worker().doCast(); }//end main() }//end class definition class Worker{ public void doCast(){ double w = 3.5; double x = -3.499999999999; System.out.println(doIt(w) + " " + doIt(x)); }//end doCast() private int doIt(double arg){ if(arg > 0){ return (int)(arg + 0.5); }else{ return (int)(arg - 0.5); }//end else }//end doIt() }//end class definition |
7. What output is produced by the following program?
- A. Compiler Error
- B. Runtime Error
- C. 3.5/9/true
- D. None of the above
public class Ap045{ public static void main( String args[]){ new Worker().doConcat(); }//end main() }//end class definition class Worker{ public void doConcat(){ double w = 3.5; int x = 9; boolean y = true; String z = w + "/" + x + "/" + y; System.out.println(z); }//end doConcat() }// end class |
8. Which of the following best approximates the
output from this program?
- A. Compiler Error
- B. Runtime Error
- C. Dummy@273d3c
- D. Joe 35 162.5
public class Ap046{ public static void main( String args[]){ new Worker().doConcat(); }//end main() }//end class definition class Worker{ public void doConcat(){ Dummy y = new Dummy(); System.out.println(y); }//end doConcat() }// end class class Dummy{ private String name = "Joe"; private int age = 35; private double weight = 162.5; }//end class dummy |
9. Which of the following best approximates the
output from this program?
- A. Compiler Error
- B. Runtime Error
- C. C. Dummy@273d3c
- D. Joe Age = 35 Weight = 162.5
public class Ap047{ public static void main( String args[]){ new Worker().doConcat(); }//end main() }//end class definition class Worker{ public void doConcat(){ Dummy y = new Dummy(); System.out.println(y); }//end doConcat() }// end class class Dummy{ private String name = "Joe"; private int age = 35; private double weight = 162.5; public String toString(){ String x = name + " " + " Age = " + age + " " + " Weight = " + weight; return x; } }//end class dummy |
10. Which of the following best approximates
the output from this program when it is executed sometime during the year
2001? (Note the use of the constructor for the Date class that
takes no parameters.)
- A. Compiler Error
- B. Runtime Error
- C. Tue Feb 06 09:56:09 CST 2001
- 981474969593
- D. Thur Jan 01 00:00:00 GMT 1970
- 0
- None of the above
import java.util.*; public class Ap048{ public static void main( String args[]){ new Worker().doConcat(); }//end main() }//end class definition class Worker{ public void doConcat(){ Date w = new Date(); String y = w.toString(); System.out.println(y); System.out.println(w.getTime()); }//end doConcat() }// end class |
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.
What is Included?
According to the subset
document,
-
“Logical operations &&, ||, ! are part of the AP
CS subset. Students need to understand the “short circuit” evaluation of
the && and || operators.” -
“The numeric cast (int) is part of the AP CS subset.
Since the only tested fundamental types are int, double
and boolean, the only required numeric cast is the cast
(int).
Students are expected to understand its “truncation towards 0” behavior
as well as the fact that positive floating-point numbers can be rounded
to the nearest integer as (int)(x+0.5), negative numbers
as (int)(x-0.5)" -
“String concatenation + is part of the AP CS subset.. Students
are expected to know that concatenation converts numbers to strings and
invokes toString on objects.”
Answers and Explanations
Answer 10
C. Tue Feb 06 09:56:09 CST 2001
981474969593
Explanation 10
The noarg constructor for the Date class
The Date class has a constructor that takes
no parameters and is described in the documentation as follows:
“Allocates a Date object and initializes
it so that it represents the time at which it was allocated, measured to
the nearest millisecond.”
In other words, this constructor can be used to instantiate
a Date object that represents the current date and time according
to the system clock.
A property named time of type long
The actual date and time information encapsulated
in a Date object is apparently stored in a property named time
as a long integer.
(The AP CS test doesn’t test for long
integers, but this is one situation where you will need to know that they
exist, and that they have the ability to store a very wide range of values.)
Milliseconds since the epoch
The long integer encapsulated in a Date
object represents the total number of milliseconds for the encapsulated
date and time, relative to the epoch, which was Jan 01 00:00:00
GMT 1970.
Earlier dates are represented as negative values. Later dates
are represented as positive values.
An overridden toString method
An object of the Date class has an overridden toString()
method that converts the value in milliseconds to a form that is more useful
for a human observer, such as:
Tue Feb 06 09:56:09 CST 2001
Instantiate a Date object with the noarg constructor
This program instantiates an object of the Date class using the
constructor that takes no parameters.
Invoke the overridden toString method
Then it invokes the overridden
toString() method to populate
a String object that represents the Date object.
Following this, it displays that String object, producing the
output shown above. (The actual date and time will vary
depending on when the program is executed.)
Get the time property value
Then it invokes the getTime() method to get and display the value
of the time property.
This is a representation of the same date and time shown above, but
in milliseconds:
981474969593
Answer 9
D. Joe Age = 35 Weight = 162.5
Explanation 9
Upgraded program from Question 8
The program used for this Question is an upgrade to the program that
was used for Question 8.
Dummy class overrides the toString method
In particular, in this program, the class named
Dummy overrides
the toString() method in such a way as to return a String
representing the object that would be useful to a human observer.
The String that is returned contains the values of the instance
variables of the object: name, age, and weight.
Overridden toString method code
The overridden toString() method for the Dummy class is
shown below for easy reference.
public String toString(){ String x = name + " " + " Age = " + age + " " + " Weight = " + weight; return x; }//end toString() |
The code in the overridden toString() method is almost trivial.
The important thing is not the specific code in a specific overridden
version of the toString() method.
Why override the toString method?
Rather, the important thing is to understand why you should probably
override the toString() method in most new classes that you define.
In fact, you should probably override the toString() method in
all new classes that you define if a String representation of an
instance of that class will ever be needed.
The code will vary
The code required to override the toString() method will vary
from one class to another. The important point is that the code must
return a reference to a String object. The String object
should encapsulate information that represents the original object in a
format that is meaningful to a human observer.
Answer 8
C. Dummy@273d3c
Explanation 8
Display an object of the Dummy class
This program instantiates a new object of the
Dummy
class, and passes that object’s reference to the method named println().
The purpose of the println() method is
to display a representation of the new object that is meaningful to a human
observer. In order to do so, it requires a String representation
of the object.
The toString method
The class named Object defines a default
version of a method named toString().
All classes inherit the toString() method.
A child of the Object class
Those classes that extend directly from the class
named Object inherit the default version of the toString()
method.
Grandchildren of the Object class
Those classes that don’t directly extend the class
named Object also inherit a version of the toString() method.
May be default or overridden version
The inherited toString method may be the
default version, or it may be an overridden version, depending on whether
the method has been overridden in a superclass of the new class.
The purpose of the toString() method
The purpose of the toString() method defined
in the Object class is to be overridden in new classes.
The body of the overridden version should return
a reference to a String object, which represents an object of the
new class.
Whenever a String representation of an object
is required
Whenever a String representation of an
object is required for any purpose in Java, the toString() method
is invoked on a reference to the object.
The String that is returned by the toString()
method is taken to be a String that represents the object.
When toString has not been overridden
When the toString() method is invoked on
a reference to an object for which the method has not been overridden,
the default version of the method is invoked.
The default String representation of an object
The String returned by the default version
consists of the following:
- The name of the class from which the object was instantiated
- The @ character
-
A hexadecimal value that is the hashcode value for
the object
As you can see, this does not include any information
about the values of the data stored in the object.
Other than the name of the class from which the
object was instantiated, this is not particularly useful to a human observer.
Dummy class does not override toString method
In this program, the class named Dummy
extends the Object class directly, and doesn’t override the toString()
method.
Therefore, when the toString() method is
invoked on a reference to an object of the Dummy class, the String
that is returned looks something like the following:
Dummy@273d3c
Answer 7
C. 3.5/9/true
Explanation 7
More on String concatenation
This program illustrates String concatenation.
The plus (+) operator is what is commonly called an
overloaded operator.
What is an overloaded operator
An overloaded operator is an operator whose behavior depends on the
types of its operands.
Plus (+) as a unary operator
The plus operator can be used as either a unary operator or a binary
operator. However, as a unary operator, with only one operand to
its right, it doesn’t do anything useful. This is illustrated by
the following two statements, which are functionally equivalent.
x = y;
x = +y;
Plus (+) as a binary operator
As a binary operator, the plus operator requires two operands, one on
either side. (This is called infix notation.) When used
as a binary operator, its behavior depends on the types of its operands.
Two numeric operands
If both operands are numeric operands, the plus operator performs arithmetic
addition.
If the two numeric operands are of different types, the narrower operand
is converted to the type of the wider operand, and the addition is performed
as the wider type.
Two String operands
If both operands are references to objects of type String, the
plus operator creates and returns a new String object that contains
the concatenated values of the two operands.
One String operand and one of another type
If one operand is a reference to an object of type String and
the other operand is of some type other than String, the plus operator
causes a new String object to come into existence.
This new
String object is a String representation
of the non-String operand,
Then it concatenates the two String objects, producing another
new String object, which is the concatenation of the two.
How is the new String operand created?
The manner in which it creates the new String object that represents
the non-String operand varies with the actual type of the operand.
A primitive operand
The simplest case is when the non-String operand is one of the
primitive types. In these cases, the capability already exists to
produce a
String object that represents the value of the primitive
type.
A boolean operand
For example, if the operand is of type boolean, the new String
object that represents the operand will either contain the word true
or the word false.
A numeric operand
If the operand is one of the numeric types, the new String object
will be composed of some of the following:
- numeric characters
- a decimal point character
- minus characters
- plus character
- other characters such as E or e
These characters will be arranged in such a way as to represent the numeric
value of the operand to a human observer.
In this program …
In this program, a numeric double value, a numeric int
value, and a boolean value were concatenated with a pair of slash
characters to produce a String object containing the following:
3.5/9/true
When a reference to this String object was passed as a parameter
to the println() method, the code in that method extracted the character
string from the String object, and displayed that character string
on the screen.
The toString method
If one of the operands to the plus operator is a reference to an object,
the toString method is invoked on the reference to produce a string
that represents the object. The toString method may be overridden
by the author of the class from which the object was instantiated.
Answer 6
C. 4 -3
Explanation 6
A rounding algorithm
The method named doIt() in this program
illustrates an algorithm that can be used with a numeric cast operator
(int)
to cause double values to be rounded to the nearest integer.
Different than truncation toward zero
Note that this is different from simply truncating
to the next integer closer to zero (as was illustrated in Question 5).
Answer 5
D. 3 -3
Explanation 5
Truncates toward zero
When a double value is cast to an int, the fractional
part of the double value is discarded.
This produces a result that is the next integer value closer to zero.
This is true regardless of whether the double is positive or
negative. This is sometimes referred to as its “truncation toward
zero” behavior.
Not the same as rounding
If each of the values assigned to the variables named w and x
in this program were rounded to the nearest integer, the result would be
4 and -4, not 3 and -3 as produced by the program.
Answer 4
A. Compiler Error
Explanation 4
Cannot cast a boolean type
A boolean type cannot be cast to any other
type. This program produces the following compiler error:
Ap042.java:13: inconvertible types
found : boolean
required: int
int y = (int)x;
Answer 3
D. B
Explanation 3
The logical and operator
The logical and operator (&&)
performs an and operation between its two operands, which
must both be of type boolean. If both operands are true, the
operator returns true. Otherwise, it returns false.
The boolean negation operator (!)
The (!) operator is a unary operator,
meaning that it always has only one operand. That operand must be
of type boolean, and the operand always appears immediately to the
right of the operator.
The behavior of this operator is to change its
right operand from true to false, or from false to
true.
Evaluation from inside out
Now, consider the following code fragment from
this program.
int x = 5, y = 6; if(!(x < y) && !(y < x/0)){ System.out.println("A"); }else{ System.out.println("B"); }//end else |
The individual operands of the &&
operator are evaluated from the inside out.
Consider the left operand of the &&
operator, which reads !(x<y).
(x < y) is true
In this case, x is less than y,
so the expression inside the parentheses evaluates to true.
!(x < y) is false
This true result becomes the right operand for
the ! operator at this point.
You might think of the state of the evaluation
process at this point as being something like !true.
When the ! operator is applied
to the true result, the combination of the two become a
false
result.
Short-circuit evaluation applies
This, in turn, causes the left operand of the
&&
operator to be false.
At that point, the final outcome of the logical
expression has been determined. It doesn’t matter whether the right
operand is true or false. The final result will be false regardless.
No attempt is made to evaluate the right operand
Therefore, no attempt is made to evaluate the
right operand of the && operator in this case.
No attempt is made to divide the integer variable
x
by zero, no exception is thrown, and the program doesn’t terminate abnormally.
It runs to completion and displays a B on the screen.
Answer 2
C. A
Explanation 2
Short-circuit evaluation
Question 1 was intended to set the stage for this question.
This Question, in combination with Question 1, is intended to help you
understand and remember the concept of short-circuit evaluation.
What is short-circuit evaluation?
Logical expressions are evaluated from left to right. That is,
the left operand of a logical operator is evaluated before the right operand
of the same operator is evaluated.
When evaluating a logical expression, the final outcome can often be
determined without the requirement to evaluate all of the operands.
Once the final outcome is determined, no attempt is made to evaluate
the remainder of the expression. This is short-circuit evaluation.
Code from Question 1
Consider the following code fragment from Question 1:
int x = 5, y = 6; if((x > y) || (y < x/0)){ ... |
The (||) operator is the logical or operator.
Boolean operands required
This operator requires that its left and right operands both be of type
boolean.
This operator performs an inclusive or on its left and right operands.
The rules for an inclusive or are:
If either of its operands is true, the operator returns
true. Otherwise, it returns false.
Left operand is false
In this particular expression, the value of x is not greater
than the value of y. Therefore, the left operand of the logical
or operator is not true.
Right operand must be evaluated
This means that the right operand must be evaluated in order to determine
the final outcome.
Right operand attempts to divide by zero
However, when an attempt is made to evaluate the right operand, an attempt
is made to divide x by zero. This throws an exception, which
is not caught and handled by the program, so the program terminates as
described in Question 1.
Similar code from Question 2
Now consider the following code fragment from Question 2.
Note that the right operand of the logical or operator still
contains an expression that attempts to divide the integer x by
zero.
int x = 5, y = 6; if((x < y) || (y < x/0)){ System.out.println("A"); ... |
No runtime error in this case
This program does not terminate with a runtime error. Why not?
And the answer is …
In this case, x is less than y. Therefore,
the left operand of the logical or operator is true.
Remember the rule for inclusive or
It doesn’t matter whether the right operand is true or false.
The final outcome is determined as soon as it is determined that the left
operand is true.
The bottom line
Because the final outcome has been determined as soon as it is determined
that the left operand is true, no attempt is made to evaluate the right
operand.
Therefore, no attempt is made to divide x by zero, and no runtime
error occurs.
Short-circuit evaluation
This behavior is often referred to as short-circuit evaluation.
Only as much of a logical expression is evaluated as is required to
determine the final outcome.
Once the final outcome is determined, no attempt is made to evaluate
the remainder of the logical expression.
This is not only true for the logical or operator, it is also
true for the logical and (&&) operator.
Answer 1
B. Runtime Error
Explanation 1
Divide by zero
Whenever a Java program attempts to evaluate an expression requiring
that a value of one of the integer types be divided by zero, it will throw
an
ArithmeticException. If this exception is not caught and
handled by the program, it will cause the program to terminate.
Attempts to divide x by 0
This program attempts to evaluate the expression (y < x/0),
which attempts to divide the variable named x by zero. This
causes the program to terminate with the following error message when running
under JDK 1.3:
java.lang.ArithmeticException: / by zero
at Worker.doLogical(Ap039.java:13)
at Ap039.main(Ap039.java:6)
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.