CPSC 124, Spring 2014
Sample Answers to Test #2

Question 1. Some short essay-type questions...

(a) The modifier "final" is used to make variables into named constants. Give two reasons for using named constants (as opposed to literal constant values).

(b) Suppose that Foo is the name of a class and that p and q are variables of type Foo. Carefully explain what is being tested and what is not being tested in a comparison using the operator "==", such as:    if ( p == q )

(c) What are "getters and setters" in the context of object-oriented programming, and why are they used?

Answer.

(a) By using a named constant such as INTEREST_RATE instead of a literal constant value such as 0.03, you make the program easier to read, since the symbolic name is more meaningful than the number. Furthermore, it is easier to change the value of a named constant (between runs of the program, of course): When using a named constant, there is only one place in the program where you have to change the value, the point where the named constant is declared. When using a literal constant, you would have to hunt down every place in the code where the value is used, and change each occurrence of the constant to the new value.

(b) Variables in Java such as p and q do not hold objects. They only hold pointers or references to objects. When you compare variables using == or !=, you are testing whether the values stored in the two variables are equal or not. That is, we are testing whether or not the two variables point to the same object. We are not testing the contents of the objects to which p and q point. That is, it is possible that p and q point to different objects but that all the data values in the two objects are identical. In that case, p == q is false, since they point to different objects, even though the contents of the two objects are equal.

(c) Getters and setters are instance methods in objects that allow the user to read and change the values of properties of the objects. Generally, the properties are private instance variables. The purpose is to give the user of the object some access to the variable while maintaining complete control over exactly what can be done with the variable. For example, a setter method can make sure that the value of a property can never be set to an illegal value.

Question 2. Suppose that A and B are variables of type int[] and that the contents of the array A are as shown. Fill in the contents of the array B after the given code is executed.

   B[0] = A[0];
   for (int i = 1; i < B.length; i++) {
        B[i] = B[i-1] + A[i];
   }

Answer.

B[0]:   3
B[1]:   4
B[2]:   6
B[3]:   11
B[4]:   13
B[5]:   23

(The first line just sets B[0] to be the same value as A[0], so the first item in B is 3. After that, the value of B[i] is computed as B[i-1]+A[i]. B[i-1] is the value before B[i] in the B array, while A[i] is the value next to B[i]. For example, B[1] = B[0]+A[1] = 3+1 = 4. And B[2] = B[1]+A[2] 4+2 = 6.)

Question 3. Write a definition for a static subroutine that satisfies the following description: The name of the subroutine is almostEqual. It has two parameters of type double, and it returns a boolean value. The return value is true if the absolute value of the difference of the parameters is less than 0.000005 and otherwise is false. (Absolute value can be computed with the function Math.abs.)

Answer.

public static boolean almostEqual( double x, double y) {
    if ( Math.abs( x - y ) < 0.000005 ) {
        return true;
    }
    else {
        return false;
    }
}

(The names of the parameters can be anything, "public" is optional, and the body of the routine can be written in other ways -- such as, "return (Math.abs(x-y)<0.000005);" -- but the "static boolean almostEqual" must be exactly as shown.)

Question 4. Write a static void subroutine with one parameter of type String. The subroutine should output a count of the number of times that each letter of the alphabet occurs in the string, formatted similarly to the sample output shown here. (Recall that you can use a variable of type char in a for loop.)

                    A: 4
                    B: 0
                    C: 1
                    D: 2
                    E: 11
                    F: 0
                      .
                      .
                      .
                    Z: 1

Answer.

public static void countLetters( String str ) {
    str = str.toUpperCase();  // so I only have to check upper case letters
    for (char ch = 'A'; ch <= 'Z'; ch++ ) {
        int count = 0;
        for ( int i = 0; i < str.length; i++ ) {
            if ( str.charAt(i) == ch ) {
                count++;
            }
        }
        System.out.println(ch + ": " + count);
    }
}

Question 5. Suppose that numbers is a variable of type double[]. Its value is an array that has already been created and filled with data. Write a code segment that will find the average of all the positive numbers (greater than zero) in the array. Ignore numbers that are less than or equal to zero. Note that you will have to count the positive numbers as well as add them up.

Answer.

double average;  // the average of the positive numbers in the array

double sum;  // sum of positive numbers in the array
int count;   // the number of positive numbers in the array.
sum = 0;
count = 0;

for (int i = 0; i < numbers.length; i++) {
    if (numbers[i] > 0) {
        count++;
        sum += numbers[i];
    }
}

average = sum/count;

(Note: If the number of positive numbers in the array is zero, then the average will be computed as Double.NaN. I did not expect you to detect or avoid this case.)

Question 6. The picture below shows three variables (pt1, pt2, and pt3) pointing to two objects. The variables are of type Point, where Point is the class shown on the left. Write a code segment that creates the situation shown in the picture. You need to declare the variables, create objects containing data as shown, and give pt1, pt2, and pt3 the values shown.

    public class Point {
        int x;
        int y;
    }

Answer.

     Point pt1, pt2, pt3;    // Declare the three variables.
     
     pt1 = new Point();  // Create an object for p1 to point to
     pt2 = pt1;          // Make p2 point to the same object
     pt3 = new Point();  // Create an object for p3 to point to

     pt1.x = 15;    // Assign values to instance variables in pt1
     pt1.y = 3;

     pt3.x = 17;    // Assign values to instance variables in pt3
     pt3.y = 42;

Question 7. Suppose that a class InventoryItem is defined as shown on the left below. Suppose that the variable inventory is defined as shown on the right below. And suppose that the inventory array has already been filled with 100 objects containing information about 100 inventory items. Write a code segment that will print the name of every inventory item for which the numberInStock

public class InventoryItem {     |  InventoryItem[] inventory;
    String name;                 |  inventory = new InventoryItem[100];
    int itemID;                  |
    int numberInStock;           |
}                                |  

Answer.

     for (int i = 0; i < 100; i++) {
         if ( inventory[i].numberInStock == 0 ) {
             System.out.println( inventory[i].name );
         }
     }

Question 8. What is the purpose of a paintComponent method in a GUI program, and how should it relate to the "state" of the program?

Answer. The job of paintComponent[] is to draw on the screen, basing the drawing on the current state.

In more detail: paintComponent is an instance method in a JPanel (or other GUI component) that is called by the system whenever the contents of the panel need to be drawn. (This happens when a window first appears on the screen or when repaint() is called.) Its purpose is to draw the contents of the panel. To do this, it uses the state of the program (that is the values of variables) to decide what to draw.

Question 9. Suppose that Foo is the name of a class. It is possible that both of the following lines of code are syntactically correct. Explain the difference.

     (a)  x = new Foo[10];            (b)  y = new Foo(10);

Answer. (b) creates an array of length 10 that can hold pointers to 10 objects of type Foo, but is initially filled with null values. (a) creates a new object of type Foo; the class Foo must have a constructor that takes one parameter of type int (or some other numeric type).

Question 10. A subroutine is a black box, but it can interact with the rest of the program through parameters, return values, and global variables. Explain these terms and explain how parameters, return values, and global variables are used for communication between subroutine and program.

Answer. A subroutine is a self-contained unit of code for performing some task, but in order for it to do anything useful, there has to be some communication between the subroutine and the rest of the program.

Usually, a task has inputs. For example, if the task is to draw a rectangle, then the task needs to know the position and size of the rectangle. Such inputs can be passed into the subroutine as parameters. Values for parameters are provided when a subroutine is called. For example, the statement g.drawRect(100,100,50,150); contains four "actual parameter" values. These values are passed into the subroutine and become the values of "dummy parameters" inside the subroutine.

In some cases, a subroutine needs to send some output value back to the rest of the program for further processing. The subroutine is said to "return" the value, and subroutines that return a value are called functions. For example, the function Math.sqrt(2) returns a value representing the computed square root of the parameter 2. This answer can, for example, be assigned to a variable or used in a more complicated expression.

Subroutines also have access to global variables, that is variables that are declared outside of any subroutine. Global variables store the "state" of the program -- information that persists between calls to subroutines. It is possible for one subroutine to change the value of a global variable, and then other subroutines will be able to see that value. It can be reasonable for subroutines to manipulate the global state of the program, but it should not be done simply to pass information between subroutines that could be sent as parameter values or return values.