CPSC 124, Fall 2011
Test #2

Question 1. What is void, in the context of this course?

Answer. void is used in the definition of a subroutine to indicate that the subroutine does not return a value. It is used in place of a return type. For example:

public static void processData() { ...

Question 2. The following "modifiers" can be applied to the declarations of member variables and subroutines. Explain what each one means. (The last one requires a longer explanation!)

a) public
b) private
c) final
d) static


a) public: Indicates that the member variable or subroutine can be used outside the class in which it is defined.

b) private: Indicates the the member variable or subroutine can only be used within the class where it is defined.

c) final: Indicates that the value of a variable cannot be changed after the value has been initialized. This makes it possible to define "symbolic constants."

d) static: Indicates that the member variable or subroutine is part of the class itself. Non-static member variables and subroutines, on the other hand, are not really part of the class; instead, they are part of a "blueprint" for creating objects. Thus, there is only one copy of a static member, while there is a copy of each non-static member for each object that has been created from the class. To use a static member all you need is the class. To use a non-static member, the class is not enough; you need an object. (Note: The correct names for non-static variables and subroutines are instance variable and instance methods.)

Question 3. We say that subroutines and classes can be black boxes. Explain what this means and why it is important

Answer. A black box has an interface and an implementation. The implementation is what goes on inside the box. The interface is what connects the insides to the rest of the world; the interface is how the black box is used. It is possible to use a black box if you understand the interface. You do not need to understand the implementation. On the other hand, the implementation can be designed and built without understanding all the details of how the black box will be used in a larger system.

Subroutines are modules because you can use a subroutine without understanding the code inside the subroutine. You only need to understand the "contract" of the subroutine, which specifies how it interacts with the rest of the program. Similarly, a class is a black box since you can use it without understanding the private part of the class or the code in its subroutines. You only need to understand the public interface of the class.

This is important because black boxes can be used as modules in the construction of complex systems. Modularity is a major tool for managing complexity.

Question 4. Write a subroutine that has one parameter of type String and also has a return type of String. The returned string should consist of all the upper-case letters ('A' to 'Z') from the parameter, and nothing else. For example, if the subroutine is called with actual parameter "John Q. Doe", then the return value is the string "JQD".


public static String extractUpperCase(String str) {
   String answer = "";
   for (int i = 0; i < str.length(); i++) {
      char ch = str.charAt(i);
      if ( ch >= 'A' && ch <= 'Z' ) {
         answer = answer + ch;
   return answer;

Question 5 A common task is to read an integer from the user (using TextIO) that is within a given range of values, from some specified minimum to some specified maximum. Write a subroutine that does this. The minimum and maximum values are parameters, and the return value is the input number from the user. Use a while loop to ensure that the number is valid.


public static int readIntegerInRange( int min, int max ) {
   if ( max < min )
      throw new IllegalArgumentException("maximum can't be less than minimum!");
   int input;
   while (true) {
      System.out.print("Enter an integer in the range " + min
                              + " to " + max + " (inclusive): ");
      input = TextIO.getlnInt();
      if (input >= min && input < max) {
      System.out.println("Input is not in the specified range.  Try again.");
   return input;

Question 6. This question is based on subroutines from the Mosaic class that was used in lab. Recall that Mosaic.setColor(r,c,color) sets the color of the square at row r, column c to r and that Mosaic.getRows() and Mosaic.getCols() tell you the number of rows and columns. Write a code segment that will set 100 randomly selected squares to Color.red. (Don't worry about the fact that some of the squares that you select might be duplicates.)


for (int i = 0; i < 100; i++) {
   int row = (int)( Math.random() * Mosaic.getRows() );
   int col = (int)( Math.random() * Mosaic.getCols() );
   Mosaic.setColor( row, col, Color.RED );

Question 7. Consider the class Vec defined below. Write a Java code segment that will produce the picture shown below when it is executed. That is, declare three variables named v1, v2, and v3. Then create some objects, with the end result as shown in the picture.

public class Vec {
   public int x, y, z;
   public Vec(int a, int b, int c) {
      x = a;
      y = b;
      z = c;


Vec v1, v2, v3;        // Declare the variables.
v1 = new Vec(3, 4, 5); // Call the constructor to create an object.
v2 = new Vec(7, 2, 8); // Call the constructor to create another object.
v3 = v2;               // Make v3 point to the same object as v2.

Question 8. Consider the class shown below. An object of type Employee represents some information about one employee at some company.

public class Employee {

   private String name;
   private double salary;
   private int idNumber;

   public Employee(String s, int i) {
      name = s;
      idNumber = i;

   public String getName() {
      return name;

   public int getIdNumber() {
      return idNumber;

   public double getSalary() {
      return salary;

   public void setSalary(double x) {
      salary = x;

a) Write a code segment to declare a variable of type Employee and to create an object of type Employee, referred to by the variable, and set the salary of the employee to be 87500.

b) Suppose that staff is a variable of type ArrayList<Employee> that already contains a list of employees. Write a Java statement to add the new employee that you created in part a) to the list.

c) Write a code segment that will give every employee in the staff list a 3% raise. That is, the current salary of each employee should be multiplied by 1.03.


a)     Employee emp;
       emp = new Employee("John Q. Doe", 2376409); 
b)     staff.add(emp);

c)     for ( int i = 0; i < staff.size(); i++ ) {
           Employee person = staff.get(i); // get one employee from list
           double currentSalary = person.getSalary();
           double newSalary = currentSalary * 1.03;
           person.setSalary( newSalary );

Question 9. Given your new knowledge of objects, explain why two String variables str1 and str2, should generally be compared using str1.equals(str2) rather than str1 == str2.

Answer. Usually when we test strings for equality, we want to test whether the two strings contain the same characters. That's what .equals does. However, it is not what == does.

Strings are objects. The value stored in a String variable is just a pointer to an object. When string variables are compared with ==, it is the values in the variables that are compared, so str1 == str2 can only be true if str1 and str2 point to the very same object (or are both null). If str1 and str2 point to different objects that both contain the same string of characters, str1 == str2 will be false, while str1.equals(str2) will be true.

Question 10. Write an essay discussing the role of subroutines, objects, and classes in program development. That is, explain how these concepts can be used when a programmer is developing a program to perform some specified task. At a minimum, your essay should mention top-down design, bottom-up design, how subroutines are used in design, and how classes are designed and used. This is an essay question. You should write a well-organized response using full sentences and paragraphs.

Answer. Programs are complex systems that need to be carefully developed and designed. Traditional approaches to development include top-down design and bottom-up design.

In top-down design, the programmer starts with a large task to be performed, and breaks down that task into smaller tasks. Any smaller tasks that still present significant problems can be broken down again into still smaller tasks, and this can continue until all remaining tasks are easy to program. (Pseudo-code and step-wise refinement are important tools in the development process.) Subroutines are useful here because a subroutine represents a task. A subroutine consist of the code for performing some tasks, treated as a unit. In top-down design, you can write a subroutine for each of the tasks, large or small.

In bottom-up design, the programmer starts by designing simple components that can be used to perform basic tasks relevant to the problem at hand. These components can then be combined into larger, more complex components, which can then in turn be used in further development. The goal in the end is to obtain a solution to the overall problem. Again, subroutines can represent the components that are used and created in the development process. Furthermore, bottom-up design can often make use of more general-purpose, reusable subroutines that are made available as part of a toolbox or API. Using existing APIs can cut down on the amount of work needed to write the program.

Objects come into the picture when newer "object-oriented" techniques are used. In object-oriented design, classes can be created to represent and mimic actual entities in the problem domain. Instance variables represent properties of those entities, while instance methods represent behaviors. By mimicing interactions between entities in the real world, this is supposed to make the development of the program conceptually easier. This is a kind of bottom-up design, but now data comes into the picture as well as tasks.

In any case, subroutines, classes, and objects are "modules": components that comunicate with each other in straightforward, easy-to-understand ways, and that can be put together to create complex systems. Using a modular design breaks the problem into more manageable pieces that can be worked on separately, at least to some degree. This can lead to programs that are easier to write, easier to debug, easier to understand, and easier to maintain.