Java Advanced Placement Study Guide:  Logical Operations, Numeric Cast, String Concatenation, and the toString() Method

Sample question:  What is the algorithm for rounding floating values to the nearest integer?

Published: February 4, 2002
By Richard G. Baldwin

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?
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

Answer and Explanation

2.  What output is produced by the following program?

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

Answer and Explanation

3.  What output is produced by the following program?

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

Answer and Explanation

4.  What output is produced by the following program?

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

Answer and Explanation

5.  What output is produced by the following program?

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

Answer and Explanation

6.  What output is produced by the following program?

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

Answer and Explanation

7.  What output is produced by the following program?

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

Answer and Explanation

8.  Which of the following best approximates the output from this program?

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

Answer and Explanation

9.  Which of the following best approximates the output from this program?

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

Answer and Explanation

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.)

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

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.  Tue Feb 06 09:56:09 CST 2001
      981474969593

Back to Question 10

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

Back to Question 9

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

Back to Question 8

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:

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

Back to Question 7

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:

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

Back to Question 6

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

Back to Question 5

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

Back to Question 4

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

Back to Question 3

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

Back to Question 2

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

Back to Question 1

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)



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-