EECS2030Z Test 2

PRACTICE


Question 1

Implement the utility class described by this API. You do not have to include javadoc comments.

package test2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Utility2P {

	private Utility2P() {
		
	}
	
	public static String hello(String name) {
		return "Hello, " + name;
	}
	
	public static String toString(List<Character> t) {
		if (t.isEmpty()) {
			throw new IllegalArgumentException();
		}
		String s = "";
		for (Character c : t) {
			s += c;
		}
		return s;
	}
	
	public static List<Character> shuffle(List<Character> t) {
		int n = t.size();
		List<Character> result = new ArrayList<>();
		for (int i = 0; i < n / 2; i++) {
			result.add(t.get(i));
			result.add(t.get(i + n / 2));
		}
		return result;
	}
	
}

Question 1

Starting with the code given below, implement the constructors for the class described by this API. Use constructor chaining where possible when implementing your constructors. You do not have to include javadoc comments.

package test2;

import java.awt.Color;

public class Circle {

	/**
	 * The radius of the circle.
	 */
	private double radius;
	
	/**
	 * The color of the circle.
	 */
	private Color color;

	
}
package test2;

import java.awt.Color;

public class Circle {

	/**
	 * The radius of the circle.
	 */
	private double radius;
	
	/**
	 * The color of the circle.
	 */
	private Color color;

	
	public Circle() {
		this(1.0, Color.BLUE);
	}
	
	public Circle(double radius, Color color) {
		if (radius < 0.0) {
			throw new IllegalArgumentException();
		}
		this.radius = radius;
		this.color = color;
	}

Question 3

Create a text file named answers.txt (use File->New-> Untitled text file in eclipse). Type your answer to the following question in the text file.

A.

Consider the field Utility2P.TEST_VERSION. What does the keyword final mean when used to modify a field?

final when used to modify a field means that the field can only be assigned a value once; it does not necessarily mean that the field is a constant.

B.

Suppose a client writes a main method that includes the following two lines of Java code:

List<Character> aList = Arrays.asList('g', 'o', 'o', 'd', 'b', 'y', 'e');
Utility2P.shuffle(aList);

The first line of code creates the list ['g', 'o', 'o', 'd', 'b', 'y', 'e'], and the second line of code calls the shuffle method from Question 1.

The memory diagram illustrating the state of memory for the two lines of code is shown below. What suitable values of a, b, and c would complete the memory diagram?

          ---------------------
          |    main method    |
          ---------------------
aList  100|        a?         |
          ---------------------
          |                   |
          |                   |
          ---------------------
      b?  |    List object    |
          ---------------------
          |                   |
          |                   |
          ---------------------
          | Utility2P.shuffle |
          ---------------------
    t  500|         c?        |
          ---------------------

The address of the List object can be any positive integer value greater than 100 and less than 500; let's pick the value 300. Then we have:

b = 300
a = 300a
c = 300a

In other words, aList and the parameter t (from shuffle) both refer to the same list object which resides at address 300.

C.

Consider the method Utility2P.hello(String) from Question 1. What precondition does the method have? Suppose that as the implementer, you wanted to remove the precondition from Utility2P.hello(String); how could you change your implementation to remove the precondition?

The precondition is stated in the documentation for the parameter name: name must not be equal to null.

Removing the precondition means that the implementer is willing to account for the case that name == null; this usually means that the implementation will first check if name == null and then do the appropriate thing to satisfy the postconditions of the methods. For example, the implementer might choose to state that the postcondition when name == null is to return the string "Hello, stranger".

D.

Provide 3 test cases for the method Utility2P.toString(List<Character>). Make sure that each test case tests a different feature of the method (i.e., don't provide 3 test cases that all check if the correct string was returned). For each test case, provide a one sentence explanation of what the test case is testing.

A test case must state what inputs will be used to run the method, and what the expected results are of running the method with the stated inputs. The question also asks to test different features of the method so you use test cases that test if the correct string is returned, if an exception is thrown when the input list is empty, if an exception is not thrown when the input list is not empty, and if the input list is not modified. It might also be useful to test a boundary case which for this method would be a list of size 1. Five possible test case examples would be:

input: ['a', 'b', 'c']
expected result: string "abc" is returned
explanation: Tests if the expected string is returned for a typical input.

input: the empty list
expected result: IllegalArgumentException is thrown
explanation: Tests if an exception is thrown for an empty list.

input: ['a', 'b', 'c']
expected result: no exception is thrown
explanation: Tests if no exception is thrown for a non-empty list.

input: ['a', 'b', 'c']
expected result: input list is equal to ['a', 'b', 'c'] (after the method is run)
explanation: Tests if the input list remains unchanged.

input: ['a']
expected result: string "a" is returned
explanation: Tests if the expected string is returned for a boundary case.

E.

Consider the following implementation of equals(Object) for the Circle class in Question 2:

	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (this.getClass() != obj.getClass()) {
			return false;
		}
		Circle other = (Circle) obj;
		if (!this.color.equals(other.color)) {
			return false;
		}
		if (Double.doubleToLongBits(this.radius) != Double
				.doubleToLongBits(other.radius)) {
			return false;
		}
		return true;
	}

What is missing from the implementation shown above compared to how equals is normally implemented? Explain whether or not the implementation shown above still satisfies the equals contract.

The first thing most equals implementations do is check that this == obj:

if (this == obj) { return true; }

The implementation still satisfies the equals contract because the only thing that the missing if statement does is check if this and obj are references to the same object; in other words, it ensures that statements like x.equals(x) returns true. The given implementation still ensures that x.equals(x) returns true because it returns true when the color and radius of this circle are equal to the color and radius of the circle obj.