25 Apr 2012

The final exam will be comprehensive. It will focus on concepts covered in the last half of the semester, but there's not really any way to avoid all the earlier stuff.

Here are the main concepts from the first half (see also the exam 1 review):

• Data and Expressions
• Using Classes and Objects
• Writing Classes
• Conditionals and Loops
• Arrays
• Recursion

The new concepts include:

• Interfaces and polymorphism
• Inheritance
• Abstract classes
• Event handling
• Exception handling
• I/O concepts
• Collection classes
• Iterator and Iterable interfaces (or more importantly the ideas behind why they're used)

You might want to review the following chapters in the book (chapter numbers might differ depending on the edition you're using):

• Object-oriented design (chapter 6)
• Inheritance (chapter 8)
• Polymorphism (chapter 9)
• Exceptions (chapter 10)
• Collections (chapter 12)

### Example exam problems

You'll be given information about any special classes and methods you need to know on the exam, but the questions below might not provide that information. For example, if you have to use an ArrayList on the exam, it will appear in a summary of useful classes, along with the methods you might have to use.

1. Given the class NumberList outlined below that keeps track of a list of numbers, create a subclass that represents a list that you're only allowed to add non-negative numbers to (if you try to add a negative number, it's just ignored). You should override the add method appropriately.

class NumberList {
// Add a number to the list.
...
}
// Get the number at entry i in the list.
int get(int i) {
...
}
...
}

2. Fill in the code below so that the program prints each unique number in the array at most once.

class Processor {
// Define instance variables and constructor ...
// Define process(int value) method ...
}

class Printer {
public static void main(String[] args) {
int[] numbers = { 1, 2, 1, 1, 3, 2, 5, 5, ... };
Processor p = new Processor();
for (int x : numbers) {
p.process(x);
}
}
}

3. What does the following code print?

class Test {
public static int divide(int n, int d) {
if (d == 0)
throw new IllegalArgumentException("Divisor is 0");
return n / d;
}

public static void main(String[] args) {
try {
System.out.println("Performing division:");
System.out.println( divide(5, 2) );
System.out.println( divide(5, 0) );
System.out.println( divide(5, 1) );
} catch (IllegalArgumentException ex) {
System.out.println("Caught exception");
} finally {
System.out.println("Done with division.");
}
}
}

4. Define a method that takes an array of Strings as input, and returns a Map<String, Integer> that stores the number of times that each unique string appears in the array.

5. What does the following program print?

class Printer {
public void print(String x) {
System.out.println(x);
}
}

class Underliner extends Printer {
@Override
public void print(String x) {
super.print(x);
for (int i = 0; i < x.length(); i++)
System.out.print("-");
System.out.println();
}
}

class Main {
public static void main(String[] args) {
Underliner u = new Underliner();
u.print("Hello!");
}
}

6. Working with the classes in #5, consider the following class below:

class ModifiedPrinter extends Printer {
Modifier mod;
public ModifiedPrinter(Modifier m) {
mod = m;
}

@Override
public void print(String x) {
super.print(mod.modify(x));
}
}


How would you define the Modifier interface? Define a class Doubler that implements the interface so the ModifiedPrinter.print method prints its input in all upper case when a Doubler instance is passed to the ModifiedPrinter constructor.