How Java Actually Runs
Java is written twice: once by you in English-ish text, once by the compiler into a robot language — and only the robot version ever runs.
Shop floorYou write the work order (Main.java). javac is the shop foreman who reads it, screams if a word is misspelled, and stamps out a metal punch card (Main.class). The JVM is the machine that eats punch cards. The machine never reads your handwriting — only the card.
public class Main {
public static void main(String[] args) {
System.out.println("Hello, Boilermakers!");
}
}javac Main.java // makes Main.class java Main // runs it — NO .class on the end
Trap
The file name must exactly match the public class name, capital letters and all. public class Main must live in Main.java. And main must be spelled public static void main(String[] args) — miss static and it compiles fine, then dies at runtime with "Main method not static".
Variables & The Eight Primitives
A variable is a box of a fixed size with a fixed shape — the type decides both, and Java checks the shape before it lets anything in.
Shop floorA parts bin labeled int is exactly 32 slots wide and only holds whole numbers. Pour in a number too big and it doesn't overflow onto the floor — it wraps around the odometer and comes out negative. That's not a bug in Java; that's the bin being honest about its size.
| Type | Bits | Holds | Literal you write |
|---|---|---|---|
| byte | 8 | −128 … 127 | (byte) 100 |
| short | 16 | −32,768 … 32,767 | (short) 5000 |
| int | 32 | ±2.1 billion | 42 |
| long | 64 | ±9.2 quintillion | 42L |
| float | 32 | ~7 decimal digits | 3.14f |
| double | 64 | ~15 decimal digits | 3.14 |
| char | 16 | one character | 'A' (single quotes!) |
| boolean | 1* | true / false | true |
int count = 42; // whole number double gpa = 3.87; // decimal char grade = 'A'; // ONE char, single quotes boolean passed = true; // widening: safe, automatic (small bin -> big bin) double d = count; // 42.0 // narrowing: dangerous, needs a CAST (big bin -> small bin) int chopped = (int) 3.99; // 3 <- truncates, never rounds byte wrapped = (byte) 130; // -126 <- odometer wrapped final int MAX_STUDENTS = 300; // final = welded shut, cannot reassign
Trap
(int) 3.99 is 3, not 4. Casting to int chops the decimal off — it never rounds. If you want rounding, Math.round(3.99) gives 4.
Also: 'A' is a char. "A" is a String. They are not the same thing and swapping the quotes is a compile error.
Operators & The Integer Division Trap
Java evaluates an expression in a fixed order, innermost first — and if both sides of a / are whole numbers, the answer is forced to be a whole number too.
Shop floor5 / 2 is 2, not 2.5. Java is a machine that only outputs whole crates when both inputs are whole crates — the leftover half is swept into the bin. % (modulo) is the sweeper: it hands you exactly what was left over. 5 % 2 == 1.
int a = 5 / 2; // 2 <- integer division double b = 5 / 2; // 2.0 <- STILL 2! divided before converting double c = 5.0 / 2; // 2.5 <- one double makes it all double double d = (double) 5 / 2; // 2.5 <- cast one side first int rem = 17 % 5; // 2 <- remainder boolean even = (n % 2 == 0); int i = 5; System.out.println(i++); // prints 5, THEN i becomes 6 System.out.println(++i); // i becomes 7, THEN prints 7 int x = 10; x += 3; // x = x + 3 -> 13 x /= 2; // x = x / 2 -> 6 (integer division again!)
int a = 12; // 1100 int b = 10; // 1010 a & b // 8 1000 AND — 1 only where BOTH are 1 a | b // 14 1110 OR — 1 where EITHER is 1 a ^ b // 6 0110 XOR — 1 where they DIFFER ~a // -13 NOT — flips every bit a << 2 // 48 shift left = multiply by 2 each place a >> 2 // 3 shift right = divide by 2 each place -8 >> 1 // -4 keeps the sign -8 >>> 1 // huge >>> fills with 0, so negatives go positive // & and | are BITWISE. && and || are logical AND short-circuit. if (x != null & x.size() > 0) // evaluates BOTH sides -> can throw if (x != null && x.size() > 0) // stops if the left is false -> safe
() → ++ -- → * / % → + - → < > <= >= → == != → && → || → =. When in doubt, put parentheses. Nobody has ever lost points for extra parentheses.Trap
double avg = sum / count; where both are int gives you a truncated answer even though the box is a double. The division already happened in int-land before the value was copied over. Fix: (double) sum / count.
Strings Are Frozen
A String can never be edited — every "change" secretly builds a brand-new String and quietly abandons the old one.
Shop floorA String is a name stamped into a steel plate. You cannot un-stamp a letter. To get "CS18" from "CS1" the shop stamps a whole new plate and throws the old one in the scrap bin. That's why building a String inside a big loop is slow — you're stamping thousands of plates.
String s = "Boilermaker";
s.length() // 11
s.charAt(0) // 'B' <- char, not String
s.substring(0, 5) // "Boile" <- start inclusive, end EXCLUSIVE
s.indexOf("maker") // 6 <- -1 if not found
s.toUpperCase() // "BOILERMAKER" <- returns NEW string, s unchanged
s.trim() // strips whitespace off both ends
s.equals("boilermaker") // false — case matters
s.equalsIgnoreCase("BOILER..") // true
s.split(",") // String[] pieces
s.contains("make") // true
s.isEmpty() // false
// s is STILL "Boilermaker" — none of those changed it.
s = s.toUpperCase(); // you must catch the return valueString a = "Purdue";
String b = "Purdue";
String c = new String("Purdue");
a == b // true — both point to the SAME pooled plate
a == c // false — 'new' forces a fresh plate
a.equals(c) // true — compares the LETTERS
// Rule: == compares addresses. .equals() compares contents.
// For Strings, ALWAYS use .equals().Trap
s.toUpperCase(); on a line by itself does nothing. It computes a new String and throws it away. You must write s = s.toUpperCase();.
substring(2, 5) gives characters at index 2, 3, 4 — the end index is not included. Length of the result is always end - start.
Conditionals
An if/else if chain is a row of gates the value falls through — the first gate that opens is the only one that ever runs.
Shop floorParts roll down a chute past a line of trapdoors. The first trapdoor whose test says yes swallows the part. Nothing below it is even checked. That's why order matters: if you test score >= 60 first, an A student falls through the D door and never reaches the A door.
if (score >= 90) {
grade = 'A';
} else if (score >= 80) { // only reached if score < 90
grade = 'B';
} else if (score >= 70) {
grade = 'C';
} else {
grade = 'F';
}
// switch — good for exact matches, not ranges
switch (day) {
case 1:
case 2:
System.out.println("Lecture");
break; // WITHOUT break it falls into the next case
case 3:
System.out.println("Lab");
break;
default:
System.out.println("No class");
}
// short circuit: if arr is null, Java never evaluates the right half
if (arr != null && arr.length > 0) { ... } // safe
if (arr.length > 0 && arr != null) { ... } // NullPointerExceptionTrap
if (x = 5) is assignment, not comparison — for int it won't even compile in Java (good), but for boolean flags if (done = true) compiles and silently sets it. Use ==, or just if (done).
A missing break in a switch makes every case below it run too. Purdue exams love this.
Loops
A for loop is three separate promises on one line: where to start, when to quit, how to move — and the quit test is checked before every single pass.
Shop floorA fence with 5 posts has 4 gaps. Loops break because people count posts when they meant gaps. i < n runs n times (0…n−1). i <= n runs n+1 times — one post too many, and on an array that's a crash.
// 1. counting for-loop: start; test; update
for (int i = 0; i < 5; i++) {
System.out.println(i); // 0 1 2 3 4 -> five passes
}
// 2. while: test first, may run ZERO times
int n = 0;
while (n < 5) { n++; }
// 3. do-while: body first, ALWAYS runs at least once
int tries = 0;
do {
tries++;
} while (tries < 5);
// 4. for-each: every element, no index, cannot modify the array slot
for (int score : scores) {
total += score;
}
// nested: the inner loop finishes completely on every outer pass
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 4; c++) { // runs 3 x 4 = 12 times total
System.out.print(r + "," + c + " ");
}
System.out.println();
}
break; // leave the loop entirely, right now
continue; // skip to the next passTrap
for (int i = 0; i <= arr.length; i++) — the last pass uses index arr.length, which does not exist. Instant ArrayIndexOutOfBoundsException. The valid indices are 0 through length - 1.
Forgetting i++ inside a while gives you an infinite loop and a very quiet terminal.
Arrays
An array is a row of identical boxes, numbered from zero, whose length is welded shut the moment it is built.
Shop floorA wall of mailboxes bolted in place. Numbering starts at 0, so 5 mailboxes are numbered 0, 1, 2, 3, 4 — there is no box 5. Reaching for box 5 doesn't get you nothing; it gets you thrown out of the post office (an exception).
int[] nums = new int[5]; // 5 boxes, all 0 by default
int[] primes = {2, 3, 5, 7, 11}; // literal, length locked at 5
String[] names = new String[3]; // 3 boxes, all null by default
nums[0] = 42; // first box
nums[nums.length - 1] = 9; // LAST box, always this expression
int len = nums.length; // FIELD, no parentheses (String uses length())
// walk it
for (int i = 0; i < nums.length; i++) {
System.out.println(i + ": " + nums[i]);
}
// for-each: read-only view of the values
for (int v : nums) {
total += v; // v is a COPY; v = 0 does not clear the array
}
// defaults: int 0 | double 0.0 | boolean false | char ' ' | objects null
Arrays.sort(nums); // import java.util.Arrays;
System.out.println(Arrays.toString(nums)); // [2, 3, 5, 7, 11]Trap
arr.length has no parentheses. str.length() has them. Mixing these up is the most common compile error in the course.
Arrays cannot grow. arr[5] = x on a length-5 array throws ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5. If you need it to grow, you need module 17.
2D Arrays
A 2D array is not really a grid — it is an array whose boxes each hold another array, which is why the first index is the row.
Shop floorA filing cabinet. grid[2][3] means "open drawer 2, then take folder 3". Drawer first, always. That's why grid.length is the number of drawers (rows) and grid[0].length is the folders in the first drawer (columns).
int[][] grid = new int[3][4]; // 3 rows, 4 columns
int[][] seats = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
seats[1][2] // 7 -> row 1, column 2
seats.length // 3 -> number of ROWS
seats[0].length // 4 -> columns in row 0
// the standard nested walk
for (int r = 0; r < seats.length; r++) {
for (int c = 0; c < seats[r].length; c++) { // seats[r], not seats[0]
System.out.print(seats[r][c] + " ");
}
System.out.println();
}
// jagged: rows may have different lengths
int[][] tri = new int[3][];
tri[0] = new int[1];
tri[1] = new int[2];
tri[2] = new int[3];Trap
Use seats[r].length for the inner loop, not seats[0].length. On a jagged array the hard-coded row 0 will run off the end of a shorter row.
new int[3][4] is 3 rows of 4, not 4 rows of 3. Rows first.
Methods & The Call Stack
Calling a method stacks a fresh tray of local variables on top, and that tray — with everything on it — is thrown away the instant the method returns.
Shop floorThe stack is a cafeteria tray dispenser. Every call drops a new tray on top holding its own copy of the arguments. When the method finishes, the top tray is yanked out and burned. Last in, first out. That's why a variable declared inside a method vanishes when it ends, and why main is always the tray at the very bottom.
// modifier return-type name (parameter list)
public static int triple(int n) {
return n * 3; // must return an int on EVERY path
}
public static void greet(String who) { // void = returns nothing
System.out.println("Hi " + who);
}
// OVERLOADING: same name, DIFFERENT parameter list
public static int add(int a, int b) { return a + b; }
public static double add(double a, double b) { return a + b; }
public static int add(int a, int b, int c) { return a + b + c; }
// changing ONLY the return type is not overloading -- it will not compilepublic static void bump(int x) {
x = x + 100; // changes only the local COPY
}
int a = 5;
bump(a);
System.out.println(a); // 5 <- unchanged!
public static void bump(int[] arr) {
arr[0] = 999; // follows the ticket to the SAME array
}
int[] nums = {5};
bump(nums);
System.out.println(nums[0]); // 999 <- changed!
public static void swap(int[] arr) {
arr = new int[]{0, 0}; // repoints the local COPY of the ticket
} // caller's array is untouchedTrap
Java passes a copy of the value. For an int that's a copy of the number. For an object it's a copy of the address — so you can change what's inside the object, but reassigning the parameter itself changes nothing for the caller.
A static method cannot call an instance method directly. If main is static and helper() is not, you need an object: new Main().helper().
Classes & Objects
A class is a blueprint; an object is one machine built from it — every machine gets its own copy of the fields, except the ones marked static, which are bolted to the wall and shared.
Shop floorThe blueprint for a boiler is not a boiler. new Boiler() is the moment the shop actually welds one. Each boiler has its own pressure gauge (instance field). But the shop's single serial-number counter on the wall belongs to the blueprint, not to any one boiler — that's static.
public class Boiler {
// 1. FIELDS -- private, always
private String name;
private int psi;
private static int builtCount = 0; // ONE copy, shared by all boilers
// 2. CONSTRUCTOR -- same name as the class, NO return type
public Boiler(String name, int psi) {
this.name = name; // this.name is the field, name is the parameter
this.psi = psi;
builtCount++;
}
public Boiler(String name) { // overloaded constructor
this(name, 0); // calls the other one; must be line 1
}
// 3. GETTERS / SETTERS -- the only doors into a private field
public String getName() { return name; }
public int getPsi() { return psi; }
public void setPsi(int psi){ this.psi = psi; }
// 4. BEHAVIOR
public void raise(int amount) { psi += amount; }
public static int getBuiltCount() { return builtCount; } // static: no 'this'
// 5. toString -- what println prints for this object
@Override
public String toString() {
return name + " @ " + psi + " psi";
}
}Boiler a = new Boiler("Old Gold", 120);
Boiler b = new Boiler("Special");
a.raise(30);
System.out.println(a); // Old Gold @ 150 psi (toString)
System.out.println(a.getPsi()); // 150
System.out.println(Boiler.getBuiltCount()); // 2 <- called on the CLASSTrap
A constructor has no return type. Writing public void Boiler(...) makes it an ordinary method, Java hands you a default constructor instead, and your fields are never set.
Inside a static method there is no this — no object exists yet. That is the real reason main can't touch instance fields directly.
References & Memory
A variable of object type never holds the object — it holds a ticket, and two tickets can point at the same crate.
Shop floorCoat check. Your pocket (the stack) holds a small paper ticket. The coat hangs in the back room (the heap). Copy the ticket to a friend and there is still exactly one coat — if they cut a sleeve off, your coat is missing a sleeve. == asks "same ticket number?" .equals() asks "same coat?"
Boiler a = new Boiler("A"); // heap: one crate. stack: ticket 'a'
Boiler b = a; // COPY OF THE TICKET -- still one crate
b.setName("Z");
System.out.println(a.getName()); // "Z" <- same crate!
Boiler c = new Boiler("Z"); // a SECOND crate that happens to match
a == c // false -- different ticket numbers
a.equals(c) // false too, UNLESS you override equals()
a = null; // ticket torn up; crate unreachable -> garbage collected
a.getName(); // NullPointerException: Cannot invoke ... because "a" is null@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Boiler other = (Boiler) o;
return psi == other.psi && name.equals(other.name);
}| Lives on the stack | Lives on the heap |
|---|---|
| Local variables, parameters, the 8 primitives, and ticket numbers (references) | Every new — objects, arrays, Strings — plus each object's instance fields |
| Popped automatically when the method returns | Freed by the garbage collector, once nothing points at it |
Trap
NullPointerException means you called a method on a ticket pointing at nothing. It almost always comes from an uninitialized object field, or from an array of objects — new String[3] gives you three nulls, not three empty Strings.
Inheritance & Polymorphism
A subclass is everything the parent had, plus extras — and when you call a method, Java searches upward from the object's real class until it finds one.
Shop floorA Locomotive is a Vehicle with a boiler welded on. Shout "MOVE!" at a yard full of vehicles and each one moves its own way — the locomotive hauls, the handcar pumps. You gave one order; the object picked the behavior. That's polymorphism.
public class Vehicle {
protected String id; // protected = visible to subclasses
public Vehicle(String id) { this.id = id; }
public void move() { System.out.println(id + " rolls."); }
public void horn() { System.out.println("beep"); }
}
public class Locomotive extends Vehicle {
private int cars;
public Locomotive(String id, int cars) {
super(id); // MUST be first -- builds the parent part
this.cars = cars;
}
@Override // optional keyword, but it catches typos
public void move() {
super.move(); // run the parent version first (optional)
System.out.println("...hauling " + cars + " cars.");
}
public int getCars() { return cars; }
}Vehicle v = new Locomotive("Boiler Special", 12);
v.move(); // Locomotive's move() runs <- decided at RUNTIME by the object
v.horn(); // Vehicle's horn() runs <- inherited, not overridden
// v.getCars(); COMPILE ERROR -- the ticket says Vehicle, so only
// Vehicle's methods are visible
((Locomotive) v).getCars(); // downcast to reach the extras
if (v instanceof Locomotive loco) { // safe check + cast in one
loco.getCars();
}=) decides which methods you're allowed to call. The object type (right of new) decides which version actually runs. Compile-time vs run-time.Trap
Overriding means an identical name and parameter list. Change the parameters and you've silently written an overload instead — the parent version keeps running and nothing warns you. That is exactly why you write @Override.
Every constructor calls super() first, whether you write it or not. If the parent has no no-arg constructor, you must call super(...) yourself.
Interfaces & Abstract Classes
An interface is a list of promises with no bodies; anything that signs it must implement every one, and can then be used anywhere that interface is accepted.
Shop floorAn interface is a bolt pattern. Any part with those four holes in those four spots can mount on the machine — the machine doesn't care what the part is. An abstract class is different: it's a half-built chassis. It already has wheels welded on, but no engine, so you can't drive it — you must extend it and finish the job.
public interface Shape {
double area(); // no body, implicitly public abstract
double perimeter();
default String describe() { // default method HAS a body (Java 8+)
return "area " + area();
}
}
public class Circle implements Shape {
private double r;
public Circle(double r) { this.r = r; }
@Override public double area() { return Math.PI * r * r; }
@Override public double perimeter() { return 2 * Math.PI * r; }
}
// a class may implement MANY interfaces, but extend only ONE class
public class Rect extends Polygon implements Shape, Comparable { ... } public abstract class Vehicle {
protected String id;
public Vehicle(String id) { this.id = id; } // abstract classes DO have constructors
public abstract void move(); // no body -- subclass MUST write it
public void horn() { // concrete -- inherited as-is
System.out.println("beep");
}
}
// Vehicle v = new Vehicle("x"); COMPILE ERROR: cannot instantiate
Vehicle v = new Locomotive("Special", 12); // legal: a finished subclass| interface | abstract class | |
|---|---|---|
| Keyword to join | implements | extends |
| How many? | many | exactly one |
| Can hold state (fields)? | constants only | yes, any fields |
| Can be instantiated? | no | no |
| Use it when | unrelated classes share an ability | related classes share code plus a gap |
Trap
If a class implements an interface and misses even one method, it will not compile — unless you mark the class abstract too and pass the obligation down to its subclass.
Exceptions
When something breaks, Java abandons the rest of the method immediately and climbs back down the stack looking for someone who agreed to catch this kind of problem.
Shop floorThe try block is a chute. When a part jams, a trapdoor opens under it — everything below in the chute is skipped, and the part drops into the first basket (catch) labeled for that kind of jam. finally is the janitor who sweeps up either way, jam or no jam.
try {
int result = 10 / divisor; // may throw
System.out.println(result); // SKIPPED if it throws
} catch (ArithmeticException e) { // most specific FIRST
System.out.println("Divide by zero: " + e.getMessage());
} catch (Exception e) { // catch-all LAST
System.out.println("Something else: " + e);
} finally {
System.out.println("always runs"); // even after a return
}
// throwing your own
if (psi < 0) {
throw new IllegalArgumentException("psi cannot be negative");
}
// checked exception: the compiler forces you to handle OR declare it
public static void read(String path) throws FileNotFoundException {
Scanner in = new Scanner(new File(path));
}| Kind | Examples | Compiler forces handling? |
|---|---|---|
| Unchecked (RuntimeException) | NullPointerException, ArrayIndexOutOfBounds, ArithmeticException, NumberFormatException | No — these are bugs you should prevent |
| Checked | FileNotFoundException, IOException, InterruptedException | Yes — try/catch it or add throws |
Trap
Order your catches most specific first. Putting catch (Exception e) above catch (ArithmeticException e) is a compile error — the second one is unreachable.
A variable declared inside the try block does not exist inside the catch block. Declare it above the try if both need it.
File I/O
Reading and writing files happens one line at a time through a buffer — and if you never close the stream, the last things you wrote may never reach the disk.
Shop floorWriting is a loading dock: boxes pile up on the dock (the buffer) and only get on the truck when the dock is full or you shout "GO" (close() / flush()). Forget to shout, and the last few boxes are still sitting on the dock when the shop closes — your file ends up empty or truncated.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public static void main(String[] args) throws FileNotFoundException {
Scanner in = new Scanner(new File("data.txt"));
while (in.hasNextLine()) { // ask BEFORE you read
String line = in.nextLine();
System.out.println(line);
}
in.close();
}
// keyboard input is the same class
Scanner kb = new Scanner(System.in);
int n = kb.nextInt();
kb.nextLine(); // <- eats the leftover newline. ALWAYS needed
String name = kb.nextLine();import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = br.readLine()) != null) { // null means end of file
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Could not read: " + e.getMessage());
}
// try-with-resources: the ( ) closes it for you, even if it throwsimport java.io.PrintWriter;
PrintWriter out = new PrintWriter("out.txt"); // overwrites the file
out.println("Boiler up");
out.printf("%s scored %.2f%n", name, gpa);
out.close(); // <- WITHOUT THIS THE FILE MAY BE EMPTY
// append instead of overwrite
PrintWriter app = new PrintWriter(new FileWriter("out.txt", true));Trap
nextInt() leaves the newline sitting in the pipe, so the very next nextLine() returns an empty string. Fix: an extra kb.nextLine(); right after the number, or read everything with nextLine() and use Integer.parseInt(...).
new PrintWriter("out.txt") erases the file the second it opens. Pass new FileWriter(path, true) to append.
Recursion
A recursive method solves a big problem by calling itself on a smaller one, and it only ever stops because of the base case.
Shop floorRussian dolls. To count them you open one and ask the doll inside "how many are you?" — then add one. The smallest doll doesn't open; it just says "1". That's the base case. No smallest doll = you open forever = StackOverflowError, the stack of trays hits the ceiling.
public static int factorial(int n) {
if (n <= 1) { // 1. BASE CASE -- stops the recursion
return 1;
}
return n * factorial(n - 1); // 2. RECURSIVE CASE -- must shrink n
}
// factorial(4) -> 4 * factorial(3) -> 4*3*factorial(2) -> 4*3*2*factorial(1)
// -> 4*3*2*1 = 24
public static int fib(int n) {
if (n <= 1) return n; // base: fib(0)=0, fib(1)=1
return fib(n - 1) + fib(n - 2); // two calls -> a TREE, not a line
}
public static String reverse(String s) {
if (s.isEmpty()) return "";
return reverse(s.substring(1)) + s.charAt(0);
}
public static int sum(int[] arr, int i) {
if (i == arr.length) return 0; // walked off the end
return arr[i] + sum(arr, i + 1);
}Trap
Every recursive call must move toward the base case. factorial(n) calling factorial(n) — or forgetting the - 1 — piles trays until the JVM throws StackOverflowError.
A negative n skips the base case entirely. if (n <= 1) is safer than if (n == 1).
ArrayList
An ArrayList is an array that quietly moves house — when it fills up, it allocates a bigger array and copies everything over.
Shop floorA shelf with 10 slots. Add an 11th part and the shop doesn't stretch the shelf — it builds a shelf half again as long, carries every part over, and scraps the old one. You never see it happen, which is why adding is usually instant and occasionally slow.
import java.util.ArrayList; ArrayListnames = new ArrayList<>(); // <> must hold an OBJECT type ArrayList nums = new ArrayList<>(); // Integer, NOT int names.add("Sharvil"); // append names.add(0, "First"); // insert at index, shifts everything right names.get(1); // read (arrays use names[1]) names.set(1, "Other"); // overwrite names.remove(0); // delete + shift left names.size(); // count (arrays use .length) names.contains("Sharvil"); // true / false names.indexOf("Sharvil"); // -1 if absent names.isEmpty(); names.clear(); for (String n : names) { System.out.println(n); } nums.add(5); // autoboxing: int 5 -> Integer.valueOf(5) int first = nums.get(0); // unboxing back to int
ArrayListnums = new ArrayList<>(); nums.add(10); nums.add(20); nums.add(30); nums.remove(1); // removes INDEX 1 -> [10, 30] nums.remove(Integer.valueOf(10)); // removes the VALUE 10 -> [30] // removing while looping forward SKIPS elements: for (int i = 0; i < list.size(); i++) { if (bad(list.get(i))) list.remove(i); // BUG: shifts under you } // loop BACKWARD instead: for (int i = list.size() - 1; i >= 0; i--) { if (bad(list.get(i))) list.remove(i); // safe }
Trap
ArrayList<int> does not compile. Generics only take object types: Integer, Double, Character, Boolean.
Size vs length vs length(): list.size(), arr.length, str.length(). Three different spellings for the same idea, and Java will not forgive you.
Threads & Race Conditions
Two threads sharing one variable will interleave in a different order every run, and count++ is not one step — it is read, add, write.
Shop floorTwo workers, one clipboard. Worker A reads "17", and before A can write "18", worker B also reads "17". Both write 18. One count vanished. synchronized is a single key to the clipboard room — only the worker holding the key may go in.
// A. implement Runnable (preferred -- leaves you free to extend something else)
public class Counter implements Runnable {
private Shared s;
public Counter(Shared s) { this.s = s; }
@Override
public void run() { // the work
for (int i = 0; i < 200; i++) s.bump();
}
}
Thread t1 = new Thread(new Counter(shared));
Thread t2 = new Thread(new Counter(shared));
t1.start(); // start() spawns a NEW thread and calls run() there
t2.start();
// t1.run(); <- calling run() directly just runs it on the CURRENT thread
t1.join(); // wait here until t1 finishes
t2.join();
System.out.println(shared.get()); // only now is the total trustworthy
// B. extend Thread
public class Worker extends Thread {
@Override public void run() { ... }
}
new Worker().start();public class Shared {
private int count = 0;
public synchronized void bump() { // one thread at a time in this method
count++; // read, add, write -- now atomic
}
public int get() { return count; }
}
// or lock a smaller region:
synchronized (this) {
count++;
}Trap
t.run() compiles and does the work — on the current thread. Nothing runs in parallel and no bug appears in testing. Only t.start() creates a thread.
Without join(), main races ahead and prints the counter before the workers finish. The answer will be wrong and different every run.
Network I/O
A socket is a pipe with a program on each end — and once it is open, you read and write it with the exact same Scanner and PrintWriter you already use on files.
Shop floorA ServerSocket is a phone that can only ring. accept() is picking up the receiver — and it waits there forever until someone calls. What you get back is the actual call (a Socket), and both sides can talk on it at once.
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket listener = new ServerSocket(4242); // claim the port
System.out.println("waiting...");
Socket client = listener.accept(); // BLOCKS here until someone connects
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
// ^^^^ autoflush
String line;
while ((line = in.readLine()) != null) { // null = the other side hung up
out.println("echo: " + line);
}
client.close();
listener.close();
}
}Socket s = new Socket("localhost", 4242); // dial
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(s.getInputStream()));
out.println("Boiler up");
System.out.println(in.readLine()); // "echo: Boiler up"
s.close();Trap
accept() and readLine() both block. A single-threaded server can serve exactly one client and then sits there — which is why this topic comes right after threads: real servers hand each accepted socket to its own Thread.
Without true for autoflush (or an explicit out.flush()) your message sits in the buffer and the other side waits forever. Same loading-dock bug as module 15.
GUIs & The Event Loop
A GUI program never runs top to bottom — it builds the window, then sits in a loop doing nothing, and your code only runs when a user does something.
Shop floorYou don't stand at the door waiting for visitors. You wire up a doorbell and go do something else. addActionListener is wiring the bell; the method inside it is what happens when it rings. Nobody rings it in your code — the user does.
import javax.swing.*;
import java.awt.*;
public class Counter {
private int count = 0;
public Counter() {
JFrame frame = new JFrame("Boiler Counter"); // the window
JPanel panel = new JPanel(); // holds components
JLabel label = new JLabel("count: 0");
JButton button = new JButton("Press me");
// wire the doorbell: this runs LATER, only when clicked
button.addActionListener(e -> {
count++;
label.setText("count: " + count);
});
panel.add(label);
panel.add(button);
frame.add(panel); // add BEFORE showing
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 120);
frame.setVisible(true); // must be LAST
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Counter()); // build on the EDT
}
}| Layout | How it places things | The exam detail |
|---|---|---|
| FlowLayout | left to right in a row, wrapping to the next row | the default for a JPanel |
| BorderLayout | five regions: NORTH, SOUTH, EAST, WEST, CENTER | add(c) with no constraint goes to CENTER; one component per region |
| GridLayout | new GridLayout(2, 3) = 6 equally sized cells, 2 rows × 3 cols | fills row by row; every cell is the same size |
FlowLayout puts things in a row and wraps. BorderLayout gives you NORTH/SOUTH/EAST/WEST/CENTER. GridLayout(r, c) makes equal cells. A JPanel inside a JPanel is how you nest layouts.Trap
The listener body runs on the Event Dispatch Thread. Put a long loop or a blocking readLine() in there and the entire window freezes — no repaint, no clicks. Long work belongs on its own thread (module 18).
setVisible(true) goes last. Components added after it may not appear until the window is resized.
Linked Structures
A linked list has no indices at all — each node knows only the one thing that comes after it, and the list is nothing more than a reference to the first node.
Shop floorA scavenger hunt. An array is a wall of numbered mailboxes — you can jump straight to box 400. A linked list is a chain of clues: each box holds a slip of paper with the address of the next box. To reach the 400th you must open all 399 before it. The last slip says null: stop.
public class Node {
int data;
Node next; // a Node that holds a Node. this is the whole trick.
public Node(int data) {
this.data = data;
this.next = null;
}
}Node head = null; // an empty list IS just null
// 1. add to the front -- O(1), no walking
public void addFirst(int v) {
Node n = new Node(v);
n.next = head; // point the new node at the old front
head = n; // then move head. THIS ORDER, or you lose the list.
}
// 2. walk it -- O(n), the pattern for every linked-list question
public void print() {
Node cur = head; // never move head itself
while (cur != null) { // null is the stop sign
System.out.println(cur.data);
cur = cur.next;
}
}
// 3. add to the end -- O(n), you must walk to the last node
public void addLast(int v) {
Node n = new Node(v);
if (head == null) { head = n; return; } // empty-list case FIRST
Node cur = head;
while (cur.next != null) { // stop ON the last node, not past it
cur = cur.next;
}
cur.next = n;
}| Array / ArrayList | Linked list | |
|---|---|---|
| Get the i-th item | instant — arr[i] | walk i nodes |
| Insert at the front | shift everything right | instant |
| Grow | copy to a bigger array | just make a node |
| Memory per item | the value | the value + a reference |
Trap
Write n.next = head; before head = n;. Reverse those two lines and the new node points at itself — every other node becomes unreachable and the whole list is garbage collected.
Walk with cur.next != null when you need the last node, and cur != null when you need to visit every node. Using the wrong one is either a NullPointerException or an off-by-one.
Searching & Sorting
Every sort in this course is the same two moves — compare a pair, then swap or shift — and the only thing that differs is which pair you look at next.
Shop floorSorting a hand of cards. Bubble keeps sweeping left to right swapping neighbours until a whole sweep changes nothing — the biggest card "bubbles" to the end each pass. Selection scans for the smallest card and puts it in slot 0, then the next smallest in slot 1. Insertion is how people actually do it: pick up the next card and slide it back into place among the ones already sorted.
// BUBBLE -- sweep, swapping neighbours, until a clean pass
public static void bubbleSort(int[] a) {
boolean swapped = true;
while (swapped) {
swapped = false;
for (int i = 0; i < a.length - 1; i++) { // note length - 1
if (a[i] > a[i + 1]) {
int t = a[i]; a[i] = a[i + 1]; a[i + 1] = t;
swapped = true;
}
}
}
}
// SELECTION -- find the smallest remaining, put it in place
public static void selectionSort(int[] a) {
for (int i = 0; i < a.length - 1; i++) {
int min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) min = j;
}
int t = a[i]; a[i] = a[min]; a[min] = t; // one swap per pass
}
}
// INSERTION -- slide each card back into the sorted part
public static void insertionSort(int[] a) {
for (int i = 1; i < a.length; i++) { // starts at 1, not 0
int key = a[i], j = i - 1;
while (j >= 0 && a[j] > key) { // j >= 0 FIRST, or you fall off
a[j + 1] = a[j];
j--;
}
a[j + 1] = key;
}
}// LINEAR -- works on ANY array. O(n).
public static int linearSearch(int[] a, int target) {
for (int i = 0; i < a.length; i++) {
if (a[i] == target) return i;
}
return -1; // the standard "not found" answer
}
// BINARY -- only valid on a SORTED array. O(log n).
public static int binarySearch(int[] a, int target) {
int lo = 0, hi = a.length - 1;
while (lo <= hi) { // <= , not < : the last window is one element
int mid = (lo + hi) / 2;
if (a[mid] == target) return mid;
else if (a[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}| Algorithm | Cost | What it needs | Swaps |
|---|---|---|---|
| Bubble | O(n²) | nothing | many |
| Selection | O(n²) | nothing | exactly n−1 |
| Insertion | O(n²), fast when nearly sorted | nothing | shifts, not swaps |
| Linear search | O(n) | nothing | — |
| Binary search | O(log n) | a sorted array | — |
Trap
Binary search on an unsorted array does not throw — it quietly returns a wrong answer. Arrays.binarySearch(new int[]{4,1,3}, 3) returns 2 on a JDK 26 run, which happens to look plausible and is meaningless. Sort first, always.
Insertion's inner test must be j >= 0 && a[j] > key in that order. Flip it and you read a[-1] before the bounds check and crash.
The Test Out
The proficiency exam is a different animal from the course exams — pure multiple choice, no partial credit, and you may miss only 11 of 75.
You write a Java program. This is the official word.
Purdue CS states it directly on the proficiency exam page:
“The exam is a combination of multiple choice questions and writing a Java program. It is based on CS 18000 final exams.”
A Fall 2025 first-hand report (below) describes that sitting as pure multiple choice, 75 questions. One student, one sitting — worth reading, but it does not outrank the department's own page. The asymmetry decides it: preparing for a program you never face costs you nothing; meeting one you never practised burns your single attempt.
“Based on CS 18000 final exams” is a measurable pointer. The Final is 4 programming questions worth 110 of its 200 points — more than half. Weight your prep accordingly: Written Practice and the programming questions are the main event, not the supplement.
Stakes
One attempt, ever — roughly a 10% pass rate, and it is a waiver, not credit: CS majors still make up the hours with an additional 300-level course. The value is sequencing — it unlocks the CS 180 → 182 → 240 → 250 → 251 chain a full semester early.
It runs the week before or the first week of classes, your advisor must release the Qualtrics request form, and anyone already enrolled in CS 18000 past Week 4 is ineligible.
Source: a first-hand write-up by someone who sat and passed it in Fall 2025 (the CS 180 test-out guide), building on Optimizing Purdue CS. That is one sitting, reported by one student — the format can change, so confirm before you commit. Past papers: cs.purdue.edu/homes/cs180/exams.html.
| What they said to know | Where it is here |
|---|---|
Threads and synchronized | 18 · Threads |
| Networking | 19 · Network I/O |
| GUIs, and Swing layouts (border / flow / grid) | 20 · GUIs & Events |
switch without break falls through | 05 · Conditionals |
Checked vs unchecked, throws, extraneous throws | 14 · Exceptions |
| Interfaces vs abstract classes | 13 · Interfaces & Abstract |
length vs size(); negative indices; array init syntax | 07 · Arrays · 17 · ArrayList |
| Overloading | 09 · Methods |
| Bitwise operations | 03 · Operators |
Their four sample questions
Written by the author to resemble what they saw. I compiled and ran all four on JDK 26 — three match, and one published answer is wrong. That one is the most instructive question here, so read its explanation even if you get it right.
Exam Simulator
Knowing the material and passing at 85% with 96 seconds a question are two different skills. This drills the second one.
Question bank: — questions. 64 are verbatim from Purdue's own archived CS 180 papers (Exam 1, Exam 2 and the Final, Fall 2008), graded against the official answer keys published alongside them (exam archive). The rest are written to cover what those 2008 papers barely touch but the test-out leans on — threads, networking, GUIs and bitwise — with every code-output answer compiled and run on JDK 26. Those papers are old: treat them as style and coverage, not as a promise about your sitting.
Written Practice
These are not my questions. Every one is lifted verbatim from a Purdue CS 180 paper, and most carry the marking rubric the graders actually used.
Source: the six Spring 2010 / Spring 2011 papers published "with solutions" in Purdue's exam archive (Prof. Chris Clifton). 88 questions, 262 points in total. Each card shows the paper, section number, the recommended time and the point value. Unlike the multiple-choice bank these could not be split reliably into question and answer, so they are reproduced whole — question, official solution, and where present the Scoring: rubric. Read the question, cover the rest of the card, and write it out on paper before you scroll.
2 ptMethod Signatures and Overloading
Given the following class:
public class BaseClass
{
double add(int a, int b) { return a + b; }
int add(int a, int b) { return a + b; } // I.
double add(double a, double b) { return a + b; } // II.
float add(int a, int b) { return a + b; } // III.
int add(int a, int b, int c) { return a + b + c; } // IV.
int add(double a, double b, double c) { return (int)(a + b + c); } // V.
}
Not all of the methods are acceptable - some are proper overloading of the add routine, but others are not
compatible and will result in an error. Which of I., II., III., IV., and V. must be removed for the above
class to compile and be usable.
A III, V
B IV, V
C I, III
D I, II, III
E I, II, III, IV
The signature of a method is based on the name and the number and type of the parameters (but not the type
of the result). Two methods of the same name, but with different number or type of parameters, are different
methods (overloaded).2 ptInheritance
What is the output of the following code:
public class BaseClass
{
public void TheMethod() { System.out.println("In base class"); }
}
public class ChildClass extends BaseClass
{
public void TheMethod() { System.out.println("In child class"); }
}
public class Driver
{
public static void main(String[] args)
{
BaseClass c = new ChildClass();
c.TheMethod();
}
}
A In base class
B In child class
C In base class
In child class
D In child class
In base class
E "BaseClass c = new ChildClass();" will cause a compile error because the type is different.
The (non-static) method in the child class overrides the one in the parent class; any use of that instance uses
the method from the child class.1 ptInheritance/interfaces
Which of the following is true:
A A child class can access all public, protected and private variables and methods of the base class.
B Let "Queue" be an interface, "Queue q = new Queue();" creates an instance of the Queue interface.
C The "super" keyword is used to access variables and methods of the base class.
D The "this" keyword can be used in a static method.
E A static method cannot access an instance variable.
A static method can be called without an instance being created. In such case, accessing the instance variable
wouldn't make sense.
4 Primitive Types (1 minute, 1 point)
Which of the following is NOT a primitive type:
A double
B String
C int
D byte
E All are primitive types.
A primitive type is held directly in the variable; it is small and of fixed size. Strings are variable size and
thus not primitive.1 ptConcurrency
To create and use a new thread in a program we:
A Create a class that inherits from the Thread class.
B Override the run() method of the Thread class.
C Use the start() method to start the thread.
D Use the join() method to wait for the thread to exit.
E All of the above.2 ptInterfaces
The following definition of an abstract "light switch" data type will be used for questions 6 and 7.
interface LightSwitch {
boolean ON = true;
boolean OFF = false;
void turnOn(); // Turn the light on.
void turnOff(); // Turn the light off.
boolean isOn(); // return ON if the light is on, OFF if it is off.
}
The following variables have also been declared:
LightSwitch light;
boolean status;
At some later point in the code (after variables have been instantiated, some method calls have been
made, etc.), you see the following statements. Which one can you be certain will not work (will always cause
either a compile or run-time error):
A light.turnOn();
B if (status == light.ON) { System.out.println("status is ON."); }
C light = new LightSwitch();
D LightSwitch l = light;
It is not possible to create an instance of an interface - this wouldn't make sense, since it isn't implemented.
7 Implementing Interfaces (4 minutes, 3 points)
The following class is a special light switch that supports dimming the light; full on is intensity 1, off is
intensity 0.
class DimmerSwitch implements LightSwitch {
double intensity = 0.0; // Invariant: 0.0 <= intensity <= 1.0
public void dim(double intensity) {
// If the given intensity is legal, set the intensity to the given value.
if (0.0 <= intensity && intensity <= 1.0)
this.intensity = intensity;
}
public void turnOn() { // Turn the light on.
intensity = 1.0;
}
public boolean isOn() { // return ON if the light is on, OFF if it is off.
if (intensity == 0) return OFF;
else return ON;
}
}
The above code will not compile. This is because:
A There is no constructor defined for the class.
B The method dim is not part of the interface.
C The method turnOff has not been defined.
D The method turnOn is not needed, we could just use dim(0.).
E This is a trick question, the code will compile.
To implement an interface, you must implement all of the methods included in the interface.2 ptClass/Instance Variables
Given the following code:
public class MyClass
{
private int time = 1;
public static void main(String[] args)
{
}
}
Which of the following code is correct to put in the main() method.
A System.out.println(time);
B System.out.println(MyClass.time);
C MyClass inst = new MyClass();
System.out.println(time);
D MyClass inst = new MyClass();
System.out.println(inst.time);
E MyClass inst = new MyClass();
System.out.println(MyClass.time);
Static functions cannot access instance variables. Instance variables don't exist until the instance is created.
Short Answer
Write your answers in the space provided.
9 Programming with Generics, Inheritance (16 minutes)
This builds on the Boolean Circuits class hierarchy we discussed in lecture. (Concurrent Programming
sections 7.1 and 7.4). Hint: If you think you need to look at the book to solve this, you are missing the point
of data abstraction. The only thing you need to know is the inheritance hierarchy:
Gate
UnaryOperator BinaryOperator
Not And Or
A QuadOperator is like a BinaryOperator, but it takes four inputs. Four-input AND and OR gates can
be built (schematically) as follows:
Quad−Input AND gate Quad−Input OR gate
a a
b b
o o
c c
d d
A partial implementation of QuadOperator is:
class QuadOperator<T extends BinaryOperator> extends Gate {
// Builds a four-input gate corresponding to the gate type T.
T top, bottom, right; // Upper, lower, and right gates as in preceding diagram.
public QuadOperator () {
super("Quad");
// Additional code to instantiate top, bottom, right --
// don't worry about how this is done.
right.setOperand1(top);
right.setOperand2(bottom);
}
public void setOperands(Gate a, Gate b, Gate c, Gate d) {
top.setOperand1(a);
// Code for the rest
}
public boolean getValue() {
return right.getValue();
}
}
You will need to perform some operations involving QuadOperators. If you aren't sure, give your best
guess - there will be partial credit. Note that even if you get one part wrong, you can get the other parts
right.
Hint: You really don't need to understand boolean circuits to answer these questions.3 ptVariable Declaration
Write the code to declare (e.g., int i; a variable qand that is a four-input AND gate, and a variable qor that
is a four-input OR gate.
QuadOperator<AND> qand;
QuadOperator<OR> qor;
Scoring: 1 for QuadOperator, 1 for <AND> / <OR>, 1 for syntactically correct.3 ptInstance Creation
Write the code to create an instance of a four-input AND gate and assign it to the variable qand.
qand = new QuadOperator<AND>();
Scoring: 1 for calling constructor, 1 for <AND>, 1 for getting everything correct.3 ptUse of an instance
You are given four gates a, b, c, and d:
Gate a,b,c,d;
a = new // ... Assume a, b, c, and d have been instantiated, don't worry about how.
Write code that uses the four-input AND gate qand to compute a && b && c && d, and assign the result
to a boolean variable o. You should assume that the Gate, AND, and QuadOperator classes are completely
implemented and work properly.
qand.setOperands(a,b,c,d);
boolean o = qand.getValue();
Scoring: 1 for calling setOperands, 1 for calling getValue, 1 for getting all details right (boolean o = , ...)
10 Fields and Inheritance (12 minutes)
Given the following code:
class Parent { class Child extends Parent {
private String s = "ParentString"; private String s = "ChildString";
public void printS () { // Several methods implemented, but there is
System.out.println(s); // NO implementation of printS().
} }
// Several other method implemented as well.
}2 ptInheritance and fields
Does the statement Parent p = new Child(); result in one string or two? Explain.
Two. Instantiating a child class creates the fields (and enables methods) of both child and
parent classes. While methods can be overridden, fields are not.
Scoring: One point for getting it right (two), one for explaining that this creates an instance that has
both parent and child fields. Possibly one point for the wrong answer but solid description of overriding.2 ptInheritance and fields
What would be the output of the following? Explain what is happening.
Parent p = new Child();
p.printS();
ParentString . Since the child class does not override the printS() method, this uses the
parent's printS() method. Since fields are not overridden, it uses the string s from the parent.
Scoring: 1 for correct answer (ParentString), 1 for explanation either noting that fields are not overridden,
or (incorrectly) describing the mechanism of overriding.3 ptField access
Suppose that in a method in class Child, you would like to change the value of the String s in class Parent.
Either describe a way this could be done, or explain why it cannot be done.
Since the field is is private, we can't use super.s to access the field. Instead, we would need
to call methods in Parent that would modify s (if such exist.)
Scoring: 1 for (improper) use of super, 2 for noting that because is private, it can't be accessed directly,
2-3 for suggesting use of methods in Parent.2 ptTypes
Which of the following is not a legal statement (or sequence of statements). Circle only one.
A boolean b;
b = true;
B String s;
s = true;
C int i = 3;
D String s = "3";
E double f;
f = 3;
Only B is not legal - the boolean value true cannot be assigned to a String.2 ptCalling a Method
Assume you are calling it from another method in the same class. One of the following statements might
not compile; all the others do.
Circle the one that might be incorrect.
A if ( longerThan ("abc", 3) > 0 )
System.out.println("The String abc is longer than 3");
B System.out.println(longerThan(abc, 3));
C int a = 2 * longerThan("abc", 2);
D longerThan("a", 4);
B is correct. If you showed evidence that you noticed the argument wasn't a String, then
any answer consistent with your answer to 2.2 is acceptable.2 ptCalling a Method part 2
Explain your answer to 2.1. For full credit, describe conditions under which it would compile.
B will only compile if abc is declared as a variable of type String (String abc = "";)
If you noted that longerThan takes a string, not a String, there are many other acceptable answers.
Scoring: 1 point for showing evidence you knew why it might not compile, 1 for conditions under which
it would.2 ptCalling a Method part 3
Assume that you had a main method in the same class as the longerThan method. I claim that none of the
statements in question 2.1 could be used in the main method. Explain why.
You cannot call a non-static method without having an object.
Main is static, so it is not running in an object. Hence a call to longerThan would not have
an object.
Again, if you noted that longerThan takes a string, not a String, there are many other acceptable answers.2 ptCode Execution
What is the value of sum after executing the above code (circle only one)?
A 0
B 4
C 5
D 9
E 102 ptProper Use of Loops
The above for loop is a poor style for using a for loop. Explain why (briefly). The variable modified in the third part of the for should be the variable that is checked for termination (1 point), the variable i should not be modified elsewhere (otherwise a while loop would be more appropriate) (1 point), variables other than that used to check termination of the loop should not be modified in the for statement (1 point), and the variable modified in the for statement should not be used after the loop (1 point).
3 ptBetter Style
Rewrite the above loop (you may use a for, while, or do-while) in a better style. sum should have the same
value when the loop is complete as the above code.
sum = 0;
int i = 0;
while ( i < 10 ) {
i = i + 2;
sum++;
}
or
sum = 0;
for ( int i = 0; i < 10; i = i + 2)
sum++;
Scoring: One point for having the same outcome using a loop to increment sum; one point each for
correcting style errors mentioned part 3.2.
4 Data Abstraction (2 minutes)
Which of the following statements are true regarding interfaces and data abstraction (circle all that are
true)? You will receive one point for each correct answer circled, and lose one point for each incorrect answer
circled.
A An interface can define the body of the functions within it.
B An interface can be used to provide an abstraction of some functionality.
C Defining a class which describes the attributes and behavior of a student is an example
of data abstraction.
D Data abstraction requires an interface to be designed and implemented.
5 Classes and Interfaces (5 minutes)
Consider the following interface and class signatures:
public interface I public class A implements J
{ {
public void f(); //
public void g(); }
}
public class B implements I
public interface J {
{ //
public void p(); }
public void q();
}2 ptShort Answer: Implementing an Interface
Minimally, how many methods must be written inside class A? Name the methods.
2 methods (1 point), p and q (1 point).
5.2 Multiple Choice: Creating Objects with Classes and Interfaces (2 minutes)
Which of the following declaration, object instantiation, and assignments are valid. (Circle all that are legal;
you get one point for each correct, and lose one point for each wrong one.)
A I i = new I();
B I i = new B();
C J j = new A();
D A a = new J();
E B b = new B();
B, C, and E are correct.16 ptChess Program
For the next few questions, you will work with the following program that
simulates a chess board. You don't have to know how to play chess to do
this (and if you do, forget what you know, as our chess will have simplified
rules.)
A chessboard has rows and columns. The columns are named with letters.
(e.g., 'a' or 'b'). The rows are numbered starting with 1.
public interface ChessPiece
{
boolean move(char toColumn, int toRow);
/* If toColumn and toRow is a legal place
* for this piece to move to, move it there
* and return true. Otherwise don't move,
* and return false. */
void showPosition();
// Print the current position on System.out
}
public class Pawn implements ChessPiece
{
private char atColumn;
private int atRow;
public Pawn(char startingColumn)
{
atRow = 2; // Pawns always start in row 2.
atColumn = startingColumn;
}
public void showPosition()
{
System.out.println("Pawn is at " + atColumn + atRow);
}
}
public class PlayChess
{
public static void main( String args[] )
{
ChessPiece qp = new Pawn('d');
if ( qp.move('d', 3) )
System.out.println("You made a legal move");
else
System.out.println("Bad move");
// Done
}
}2 ptMultiple Choice: Compilation
When you try to compile the above code, it gives the following error: A variable qp might not have been initialized B incompatible types. found: int, required: boolean C Pawn is not abstract and does not override abstract method D move(char,int) in ChessPiece cannot be applied to (int,int) E cannot find symbol : constructor Pawn(char,int) All are plausible errors, but only C occurs in the given code. For example, the constructor "Pawn(char,int)" doesn't exist, but since nobody tries to call such a constructor, it doesn't matter. A: 1; B, C: 0
2 ptMultiple Choice: Objects
Assume the error in Question 6.1 has been fixed, and the program compiles and runs without errors. When the program reaches the line "// Done" in the main method, what objects are there in the system? A No objects have been created. B 1: a ChessPiece object. C 1: a Pawn object. D 2: a ChessPiece object and a Pawn object. E 3: a ChessPiece object, a PlayChess object, and a Pawn object. ChessPiece is an interface, you can't create an object for an interface.
3 ptShort Answer: Using Interfaces
Assume that I have written a Knight class that implements the ChessPiece interface. I have also created a
knight object kk. Write a statement that will move the object kk to column f row 3. Hint: You do not write
any code that goes in the Knight class - that is already written, and you just have to use it. For full credit,
you should also check if this was a legal move and print a message if it was not.
if (! kk.move('f ',3) ) System.out.println("Not a legal move.");
Scoring: 1 for using the kk object, 1 for correct arguments, 1 for checking result.9 ptCode: Implementing Interfaces
The Pawn class does not have the move method that is required by the ChessPiece interface. Write that
method. Assume that a pawn only moves one space forward at a time; that is, it always stays in the same
column, and moves to the next row (e.g., if a pawn is at column d row 2, it can only move to column d row
3 ; an attempt to move it anywhere else is not allowed.) Everything else you need to know is contained in
the code above.
public boolean move(char toColumn, int toRow)
{
if ( toColumn == atColumn && toRow == atRow + 1 ) {
atRow = toRow;
return true;
}
else
return false;
}
Scoring: 1 for a "move" method, 1 for public, 1 for correct return type, 1 for correct arguments, 1 for
check on column, 1 for check on row, 1 for returning boolean, 1 for updating row, 1 for logically correct.
A common error was to use "toColumn.equals(atColumn)". Since a char is a primitive type, and not an
object, you cannot call a method on it.2 ptExceptions and Inheritance
Assume we have defined the following exceptions:
public class AException extends Exception { }
public class BException extends AException { }
public class CException extends BException { }
and we use them in the following program:
public static void main(String[] args) static void FuncA(boolean x) throws AException
{ {
try { try {
FuncA(true); if ( x ) throw new CException();
System.out.print("1"); System.out.print("4");
} } catch(BException ex) {
catch(AException ex) { System.out.print("5");
System.out.print("2"); throw new AException();
} } catch(AException ex) {
System.out.print("6");
System.out.print("3"); }
}
System.out.print("7");
}
What should the output of the program be?
A 413
B 523
C 5673
D 54213
E 564713
Remember that after an exception is thrown, the first matching catch is executed. Once that block is done,
processing continues outside the try/catch context - it never returns to the try block.
2 Constructing Windows (3 minutes, 2 points)
When constructing a window using a JFrame, you add objects to a JPanel. Which two of the following are
true statements (you get one point for each true statement you mark, but lose a point for each false statement
you mark):
A Each object added must be a different class.
B Multiple components in a window can share the same instance implementing ActionLis-
tener.
C You must create an instance of a component before adding it to the JPanel.
D Each object added must have its own event handler (ActionListener).
E There can only be one instance of an object for each class that implements the ActionListener interface.1 ptThreads
Which of the following statements about programming with threads is true?
A After a call to start() a thread, the next statement must be a call to join() that thread or the thread
will not execute.
B Threads can only be used on multiprocessor machines.
C Different threads can call methods of the same object at the same time.
D Once a program starts a thread, it cannot do anything else until that thread has finished running.2 ptSynchronization
Given the following code:
public class Vertical {
private int alt;
public synchronized void up() {
++alt;
}
public void down() {
--alt;
}
public synchronized void jump() {
up();
down();
}
}
Which two of the following are correct (you get one point for each one you get right, but you lose a point
for each incorrect one you mark):
A The code will fail to compile.
B Separate threads can execute the up() method concurrently on the same object.
C Separate threads can execute the down() method concurrently on the same object.
D One thread can execute up() on an object concurrently with another executing down()
on the same object.
E Two threads can both execute up() at the same time on the same object, both execute down() at the
same time on the same object, and one can execute up() while the other executes down() on the same
object.
Registration System
Questions 5 through 9 concern a hypothetical "registration kiosk": A computer with multiple screens and
keyboards. Each screen starts up with a "Register for CS18000" window:
When a student walks up and clicks "Register for CS18000", the program brings up an "Enter name" window:
When the student clicks "OK", the registration is complete. This means that an instance of class Student
has been created, and the number of students registered (the class variable totalStudents in class Student)
has been updated.
If a student walks up to the kiosk and clicks "Register for CS18000", but the class is full (totalStudents
≥ MAXSTUDENTS), the student instead sees a "Class full" message.
Code fragments covering the following questions are given at the end of the test (Appendix A). However,
you should read the questions first. The questions concern basic design principles of graphical user interfaces
and concurrent systems; you may be able to answer them without looking at the code at the end of the test.
It is best if you read the question and answer choices first, then if you are unsure, look at the code.1 ptEvent handling
When we run the program, the "Register for CS18000' window pops up on each screen (we see the button
shown above), but when users click on "Register for CS18000" nothing happens. Which of the following is
a likely fix for the problem?
A Create an instance of Student for each kiosk screen.
B Call the RegisterAction.actionPerformed() method.
C Add the RegisterAction listener to the "Register for CS18000" button.
D Add a try/catch block with "join" statements at the end of the main method, as the program now
ends as soon as the screens are set up. Name: 4
E Add the "Register for CS18000" button to a JPanel.1 ptConcurrency
Assume we have fixed the preceding problem. We now get all the screens set up properly, and if one person
walks up and registers, it works. But if a second person clicks "Register for CS18000" while the first person
is registering, nothing happens until the first student clicks "OK". This is happening because:
A ActionListeners are not concurrent; the next action is not performed until the previous
action has completed.
B The class variable totalStudents is shared by all Student instances, so once one starts, no other can
run.
C Even though we have multiple screens, there is only one processor, so it isn't possible for the program
to handle inputs from two users.
D The JFrames have to be used in the same order they were created in the main method.
E The try-catch block in actionPerformed only allows one thread to execute at one time.2 ptThreads
Realizing we need concurrency, we make class Student extend class Thread. This requires we implement a
run method; since the other methods already do everything we need, we simply make it:
public void run() { return; }
We then rewrite the event handler for the "Register for CS18000" button (method actionPerformed() )
to include:
Student s = new Student(screen);
s.start();
try { s.join(); }
catch ( InterruptedException ie ) { }
// Save s into appropriate variables
Running this gives the same behavior as before - nothing seems to have changed. In hindsight, we realize
this couldn't have worked because:
A It won't compile, we haven't defined a start() and join() method for Student.
B The only thing executed concurrently is the run() method; the hangup is in the construc-
tor for Student.
C When another user clicks a button, it causes an InterruptedException; we need to create a new Student
in the catch block.
D The only place we can start a new thread is in the main method.
8 Managing Concurrency (5 minutes, 2 points)
Name: 5
We manage to fix all of the above problems - we now have multiple threads running so that several people
can use the kiosk at once, and all get a quick response. Unfortunately, we seem to be ending up with too
many students in class (i.e., we end up with totalStudents > MAXSTUDENTS.) This is because:
A After we throw the ClassFull exception, we continue to register the student. We need to put a return
after the throw.
B Each thread has its own copy of totalStudents, so each can have MAXSTUDENTS.
C The value of totalStudents is initialized to 0 every time we create a new instance of Student, so
totalStudents is always 0 when it is checked.
D We have a race condition: The check if there is room happens before we update the
number of students, and this can happen concurrently.
Short Answer
Write your answers in the space provided. The space provided should be sufficient, but if you need more,
use the back of the sheet.5 ptSynchronization
If you are unsure about your answer to Question 8, you should make sure you have done
everything else before you do this one. We fix the "too many students" problem of the preceding
question with a simple (one word) change to class Student. However, in doing this fix we lose concurrency:
only one person is able to register at a time.
Part 1 (1 point): What did we do to fix the problem? Make Student a synchronized method. Technically
this isn't possible in Java 1.5, as Constructors can't be synchronized - there were other acceptable answers,
as long as you got across the point that the entire method was synchronized.
Part 2 (4 points): Rewrite the Student method to fix this. (It is okay if you don't rewrite everything, as
long as it is quite clear what your solution does.)
One solution:
synchronized(totalStudents) {
if ( totalStudents >= MAXSTUDENTS ) throw new ClassFull();
else totalStudents++; // Reserve a place for us before unsynchronizing.
}
name = JOptionPane.showInputDialog(
//... as before.
if ( name == null ) { // User pressed cancel button
synchronized(totalStudents) {
totalStudents--; // Free up the space we reserved.
}
throw new StudentCancelled();
}
Scoring: 1 point for synchronizing check on totalStudents, 1 for synchronize on a class variable (totalStudents
or other), 1 point for moving check and update together, 1 point for making sure that totalStudents isn't
increased if the student cancels / class is full. Alternate credit for pointing out that this wouldn't solve the
problem, since the handler still isn't concurrent: 2 for pointing out the problem, 1 for a reasonable start at
a fix, 1 for noting need for synchronization, up to a total of five points.2 ptException processing
The following code will fail to compile. You can assume that all methods and variables in this fragment are
properly defined; the error is entirely in the code block below.
int i;
try {
i = divide(a, b); // May throw a DivideByZeroException
} catch (DivideByZeroException dbz) {
System.err.println("Divide by zero attempted.");
}
System.out.println(i);
Explain briefly why it fails (1 point) and a way to fix it (1 point).
If divide throws an exception, then the System.out.println(i) would have i uninitialized. The compiler will
not allow this to happen. The solution is to move the System.out.println(i) into the try block.
Initializing i is not a good solution. While it fixes the compile error, it means that dividing a number by
0 gives a valid output - a logical error in the program.9 ptInheritance
Given the following classes:
class Person {
public Person() {
System.out.println("Person constructor");
}
public void showClassName() {
System.out.println("Person");
}
public void printSomething() {
System.out.println("In printSomething");
}
}
class Employee extends Person {
public Employee() {
this("Calling this");
System.out.println("Employee constructor");
}
public Employee(String s) {
System.out.println(s);
}
public void showClassName() {
System.out.println("Employee");
}
}
For each of the following statements, show the output. Assume the statements are executed in the order
given (note that you should be able to figure out the later ones even if you aren't sure about the earlier
ones.)
Scoring: 1 point each
Person p1 = new Person();
Person constructor
p1.showClassName();
Person
Employee e1 = new Employee();
Person constructor
Calling this
Employee constructor
e1.showClassName();
Employee
e1.printSomething();
In printSomething
p1 = e1;
Nothing (one point for stating "nothing" or for leaving it blank.)
p1.showClassName();
Employee
Person e2 = new Employee("e2");
Person constructor
e2
e2.showClassName();
Employee2 ptGenerics
Given a Set class (partially shown below):
public class Set<E> {
// Fields and other methods here...
void insert(E value) {
// Code to do insert here
}
}
Using the Person and Employee classes from question 1, we do the following:
Set<Person> ps = new Set<Person>();
Employee e1 = new Employee();
ps.insert(e1);
Is the last statement ( ps.insert(e1); ) legal? (that is, will it compile and run?) Briefly explain your
answer. You may assume that Set is implemented correctly and that the first two statements compile and
run.
Yes, it will. since e1 is an Employee, and Employee extends Person, e1 can be used anyplace
a Person object is needed. Since ps is a set of Person, e1 can be inserted into the set.
Scoring: 1 point for "yes", 1 for showing understanding of inheritance.2 ptRecursion
Given the following class:
public class Recurse
{
public static int fun(int n)
{
if (n <= 1)
return 1;
else
return fun(n - 1) + n ;
}
}
What is returned by Recurse.fun(3) ?
Scoring: (2 points)5 ptExceptions
The sqrt function in the java Math class takes a double value as an argument, and returns the special double
value "NaN" (Not a Number) if the argument is negative. We'd like to instead use a NegativeSqrtException
exception to handle this case:
public class NegativeSqrtException extends Exception
{
}
Without using exceptions, your function looks like:
public static double mySqrt(double n)
{
return Math.sqrt(n);
}2 ptProper use of exceptions
Should the NegativeSqrtException be thrown by mySqrt, or should mySqrt contain a try/catch block?
Explain.
As a "library method", it's better to throw the exception to notify the caller of the method
that he has supplied an illegal argument. Try/catching would be forced to return an ambiguous
value (probably an arbitrary negative number) which still has to be interpreted.
Scoring: 1 point for correct answer, 1 point for explanation. If explanation was unclear, looked to answer
to question 4.2 for clarification.3 ptWriting the code
Write the mySqrt function that makes proper use of the NegativeSqrtException.
Solution:
public static double mySqrt(double n) throws NegativeSqrtException
{
if (n < 0)
throw new NegativeSqrtException();
return Math.sqrt(n);
}
Scoring: -1 if the method signature does not contain "throws". -2 if the "conditional + throw" is incorrect.
If previous section was incorrect, combined partial credit was given based on overall validity of the answer.2 ptArray vs. Linked List
An instructor using this class should have the ability to add students (when they sign up for the class) and
remove students (if they drop the course) as necessary. Should the gradebook hold the collection of students
using an array-based implementation or a linked list implementation? Justify your choice.
Either is acceptable. If you assume all students are added to the book at once and
there is minimal students dropping the course, then an array-based implementation (e.g.,
java.util.Vector) may be preferred for easy indexing and fast iteration. If you assume the
size of the gradebook is very fluid, then a linked list implementation may be preferred for
fast addition/subtraction from the gradebook. It is not correct to say that the linked list
implementation is resizable and the array is not (it is only easier to be resized).
Scoring: 1 point for making a choice or saying either, 1 point for a justification that correctly supports
the answer given.3 ptSuperclasses/Subclasses
All students must be either an UndergradStudent or GradStudent; we would never actually create an object
that was just a Student. However, we do need a Student class, since this is what the gradebook holds;
UndergradStudent and GradStudent will be subclasses of Student.
Note that while undergrads and grad students have much in common, there are some differences. For
example, a GradStudent should have a "thesisTitle" field; and UnderGrad should have a "classYear". How-
ever, both have common attributes and methods such as "transcript", "addCourseGrade()", and "com-
puteGPA()".
Should the Student class be (choose one):
A an Interface,
B an Abstract class, or
C a regular class .
Briefly justify your answer
Student should be an abstract superclass. There's no point in a Student object being made,
so it should be abstract. Student should be a class instead of an interface in order to declare
similar fields and accessors/mutators which can be inherited.
Scoring: 0 points for interface, 1 point for regular class and noting that this allows you to share common
methods, 3 points for saying abstract class and noting that this allows you share common methods (we
assumed by selecting abstract class that you understand an instantiation won't be possible.11 ptLinked Data Structures
class OrderedList {
private int value;
private OrderedList next;
// Invariant: value < next's value. That is, !next.lessThan(value);
public OrderedList(int data, OrderedList next) {
value = data;
this.next = next;
}
private boolean lessThan (int val) {
// True if val < my value
// Note that another object of the same class may use an object's private method.
if (val < value) return true;
else return false;
}
public void insert(int val) {
// Put val at it's proper place in the list
/* Line A (for parts 3 and 4) */
if ( next.lessThan(val) ) {
/* Line B (for parts 3 and 4) */
OrderedList temp = new OrderedList(val, next);
next = temp;
} else {
/* Line C (for parts 3 and 4) */
next.insert(val);
/* Line D (for parts 3 and 4) */
}
/* Line E (for parts 3 and 4) */
}
}5 ptSuccessful Insert
Assume OrderedList ol; is the following list:
ol
−22 −7 7 17 42
Show what the above list will look like after running the statement:
ol.insert(4);
Solution:
ol
−22 −7 4 7 17 42
Scoring: Minus one point for each of not having a new node, not having 4, not correctly pointing to the
next node, not correctly pointing the previous to the next, not having ol pointing to the right place, and not
null-terminating the list. But at least one point for having one of these things right.2 ptFailed Insert
If you do an ol.insert(78); the code will fail to do what it should. This is because:
A There is no base case for val > value.
B There is no base case for next == null.
C There is no recursive case for val > value.
D There is no recursive case for next == null.
Scoring: 1 point for A or D, 2 points for B.2 ptCorrecting insert of large items
Fix the code so that an insert of a large item (e.g., ol.insert(78); will work correctly. You can do this by
writing two or three lines of code that go at A, B, C, D, or E above - just give the code and state where it
goes. (You can also fix it by changing one line of the code - either answer is acceptable.)
One solution (at A):
if ( next == null )
next = new OrderedList(val, null);
else
Scoring: One point for null check, one for creating new node. Putting this at a location other than A
will result in a null pointer exception in the first if ( next.lessThan(val) ), although you still received credit
as long as everything else was right.
Another common answer was to replace the if with if ( next == null || next.lessThan(val) ) {
. This is correct. If you put them the other way around, it would try next.lessThan(val) before checking
if next==null, resulting in a null pointer exception (again, you still received full credit for getting this the
wrong way, but you should remember that the order matters.)2 ptRemaining problem
Insert will still fail to work properly in some cases. Explain briefly or give an example where it fails (1 point)
and provide code to fix the problem (1 point).
If an item belongs at the beginning of the list (e.g., ol.insert(-30)), it will instead be placed
after the first item. (1 point) This will result in an out-of-order list.
Fixing this is a bit tricky, as we can't change the node ol points to. Instead, we have to
change the value in that node. Put the following at line A, at the beginning.
if ( lessThan(val) ) { // If the new value goes in front of me,
next = new OrderedList(value, next); // put my value in a new node,
value = val; // And put the new value in me.
} else
1 point. Minor mistakes allowed, as long as you have it basically correct.
6.5 Non-Bonus question (0 points)
I claim the OrderedList class, even after fixing the insert method, is useless. Why? This won't count for
anything - don't answer this unless you are done with the exam and want to show off...
Since we can't see what is in the list, or even check if an item is there, it won't have any
value. The only public method or field is insert, which doesn't return a value or change the
value of its arguments, so no matter what it does, we don't see anything. Assuming, of course,
you've fixed things so it doesn't end up giving a null pointer exception.2 ptConstructors and Inheritance
Given the following classes:
class A { class C extends B {
public A() { public C() {
System.out.print("1"); System.out.print("3");
} }
} }
class B extends A { public class TestOne{
public B() { public static void main(String args[]){
System.out.print("2"); C c = new C();
} }
} }
What is the result when TestOne is executed?
A 3
B 1
C 321
D 1232 ptInheritance and overriding
Given the following code:
public class SimpleCalc {
public int value = 0;
public void calculate() { value += 7; }
}
public class MultiCalc extends SimpleCalc {
public int value = 0;
public void calculate(){ value = value - 3; }
public void calculate(int multiplier) {
calculate();
super.calculate();
value = value * multiplier;
}
public static void main(String args[]) {
MultiCalc calculator = new MultiCalc();
calculator.calculate(2);
System.out.println("Value is: " + calculator.value);
}
}
What is the result when the above is run (that is, the main method is called)?
A Compilation fails
B Value is: -6
C Value is: 12
D Value is: -12
E The code runs with no output3 ptThreads
public class TestOne implements Runnable {
public static void main(String args[]) throws Exception {
Thread t = new Thread(new TestOne());
t.start();
System.out.print("Started");
t.join();
System.out.print("Complete");
}
public void run() {
for(int i = 0; i < 4; i++){
System.out.print(i);
}
}
}
Given the above code, which of the following is a possible result?
A Compilation fails
B An exception is thrown at runtime
C The code executes and prints "StartedComplete"
D The code executes and prints "StartedComplete0123"
E The code executes and prints "Started0123Complete"
4 Overloading / signatures (4 minutes, 1 point)
Which of the following would overload this method:
double add(int a, int b) { return a + b; }
I. int add(int a, int b) { return a + b; }
II. double add(double a, double b) { return a + b; }
III. int add(double a, double b) { return (int)(a + b); }
IV. double add(int a, int b) { return a + b; } in a child class.
V. int add(int a, int b) { return a + b; } in a child class.
A I, II
B I, III
C II, III
D IV, V
E IV only2 ptArrays
What is the output of the following program:
public class MyProgram2 {
public static int id;
public MyProgram2(int d) {
id = d;
}
public int getID() {
return id;
}
public static void main(String[] args) {
MyProgram2[] prog = new MyProgram2[5];
for(int i = 0; i < prog.length; i++) prog[i] = new MyProgram2(i);
for(int i = 0; i < prog.length; i++) System.out.print(prog[i].getID());
}
}
A 01234
B 55555
C 44444
D 43210
E 00000
6 Arrays vs. Linked Lists (3 minutes, 2 points)
Which of the following operations would be faster with an array than with a linked-list data structure:
A Adding an element in between existing elements.
B Changing the value of the first element.
C Getting the value of an element in the middle.
D Removing an element from the middle.
E None of these would be faster using arrays.1 ptLayout Managers
Which of the following will create the Window shown above?
A setLayout(new FlowLayout());
add(new JLabel("a"));
add(new JLabel("b"));
JPanel j = new JPanel();
j.setLayout(new GridLayout(2,2));
j.add(new JLabel("c"));
j.add(new JLabel("d"));
j.add(new JLabel("e"));
add(j);
B The following is the correct answer. This was pretty easy for people who put a lot of
extra work in Project 4 (for which they didn't get much credit.)
setLayout(new GridLayout(2,4));
add(new JLabel("a"));
add(new JLabel("b"));
add(new JLabel("c"));
add(new JLabel("d"));
add(new JLabel(""));
add(new JLabel(""));
add(new JLabel("e"));
C setLayout(new BorderLayout());
JPanel i = new JPanel();
i.add(new JLabel("a"));
i.add(new JLabel("b"));
JPanel j = new JPanel();
j.setLayout(new GridLayout(2,2));
j.add(new JLabel("c"));
j.add(new JLabel("d"));
j.add(new JLabel("e"));
i.add(j);
add(i, BorderLayout.CENTER);
D Both A and C
E A, B, and C would all create the window as shown.2 ptExceptions
Assume we have defined the following exceptions:
public class AException extends Exception {}
public class BException extends AException {}
public class CException extends BException {}
and we use them in the following program:
public static void main(String[] args) static void FuncA(boolean x) throws Exception
{ {
try { try {
FuncA(true); if(x) throw new BException();
System.out.print("1"); }
} catch(CException ex) {
catch(AException ex) { System.out.print("5");
System.out.print("2"); throw new AException();
} }
catch(Exception ex) { System.out.print("6");
System.out.print("3"); }
}
System.out.print("4");
}
What should the output of the program be?
A 24
B 134
C 524
D 5124
E None of the above.1 ptUsing exceptions
The exceptions in question 8 give no information other than the class of the exception. However, it is possible
to put more information in an exception. Which of the following would NOT be an appropriate use of an
exception carrying extra information:
A To write a function that always returns two values (since "return" only lets us return
one.)
B To give a message about what caused an error.
C When in an unusual situation, we want to return an item of a different type from the normal return.
D When the object to be returned has a problem that prevents it from being used normally, but we still
want to give it to the calling method.3 ptRecursion
What does method recur do, when called as recur(x, x.length) ?
//Precondition: x is an array of n integers
public static int recur (int[] x, int n) {
if (n == 1) return x[0];
else {
int t = recur(x, n - 1);
if(x[n-1] > t) return x[n-1];
else return t;
}
}
A It finds the largest value in x and leaves x unchanged.
B It finds the smallest value in x and leaves x unchanged.
C It sorts x in ascending order and returns the largest value in x.
D It sorts x in descending order and returns the largest value in x.
E It returns x[0] or x[n-1], whichever is larger.2 ptRecursion basics
A recursive program must have: A An Array to operate on. B At least one base case and at least one recursive case. C A Linked-List data structure to operate on. D A counter to decide how many times to recurse. E At least one for loop.
4 ptThreads
class MyProgram extends Thread {
static Object lock = new Object();
int id;
boolean pause;
public MyProgram(int d) {
this.id = d;
this.pause = false;
}
public void setPause(boolean newPause) {
this.pause = newPause;
}
public void run() {
for(int i = 0; i < 4; i++) {
synchronized(lock) {
try {
System.out.print(id);
if(pause) lock.wait();
} catch(InterruptedException ex) { }
}
sleep(500);
}
}
public static void main(String[] args) {
MyProgram[] prog = new MyProgram[3];
for(int i = 0; i < prog.length; i++)
(prog[i] = new MyProgram(i)).start();
sleep(500);
for(int i = 0; i < prog.length; i++)
prog[i].setPause(true);
System.out.print("@");
synchronized(lock) {
prog[0].setPause(false);
lock.notifyAll();
}
try {
for(int i = 0; i < prog.length; i++) prog[i].join();
} catch(InterruptedException ex) {
System.out.print("$");
}
}
static void sleep(int time) {
try {
Thread.sleep(time);
} catch(InterruptedException ex) {
System.out.print("#");
}
}
}
Which of the following is a possible output of the above program
A 0120@12020121
B 02112@20100
C 012012@012#012
D 012#000$
E 2012@01201201$2 ptFailure to Terminate
When the code in Question 12 is run, it does produce output, but it never completes. This is because:
A The for loop at the beginning of main() starts the first thread, then waits for it to finish and is unable
to start the next.
B When a thread executes lock.wait(), it is in the synchronized block on lock, and so main() cannot enter
the synchronized block to run notifyAll().
C When notifyAll() is called, threads other than prog[0] will call lock.wait() again.
D When notifyAll() is called, it picks only one thread to leave the wait().
E Trick question, the program will complete normally.2 ptErrors
Other than the problem in question 13, which of the following type of error would be most likely to occur
with the code of question 12?
A Equivalence testing errors
B Out-of-bounds errors
C Scope errors
D Precision errors
Doubly Linked List
Questions 15 through 18 make use of the following code:
public class DLLNode<E> {
// Single node of a doubly-linked list.
private DLLNode previous;
private E value;
private DLLNode next;
public DLLNode(E value) {
previous = null;
this.value = value;
next = null;
}
private DLLNode(DLLNode previous, E value, DLLNode next) {
this.previous = previous;
this.value = value;
this.next = next;
}
public DLLNode insertBefore(E value) {
DLLNode newNode = new DLLNode<E>(previous, value, this);
previous = newNode;
return newNode;
}
public DLLNode insertAfter(E value) {
DLLNode newNode = new DLLNode<E>(this, value, next);
next = newNode;
return newNode;
}
public DLLNode deleteGetAfter() {
if (previous != null) previous.next = next;
if (next != null) next.previous = previous;
return next;
}
public DLLNode deleteGetBefore() {
if (previous != null) previous.next = next;
if (next != null) next.previous = previous;
return previous;
}
public E getValue() {
return value;
}
}
public class Stack<E> {
DLLNode top = null;
public void push(E value) {
if (top == null) top = new DLLNode<E>(value);
else top = top.insertBefore(value);
}
public E pop() throws NullPointerException {
if (top == null) throw new NullPointerException();
else {
E result = (E)top.getValue();
top = top.deleteGetAfter();
return result;
}
}
}
and the following code fragment (assume that variables exam1-5 are declared and instantiated; i.e., they are
not null.)
Stack<Exam> s = new Stack<Exam>();
s.push(exam1);
s.push(exam2);
s.pop().gradeIt();
s.push(exam3); Name: 10
s.push(exam4);
s.push(exam5);
s.pop().gradeIt();
s.pop().gradeIt();3 ptStack Operations
In what order will the exams be graded given the above code fragment? (I.e., the order calls to .gradeIt() will occur) A exam1 exam2 exam3 exam4 exam5 B exam5 exam4 exam3 exam2 exam1 C exam1 exam2 exam3 D exam2 exam4 exam3 E exam2 exam5 exam4 Short Answer Write your answers in the space provided. The space provided should be sufficient, but if you need more, use the back of the sheet.
5 ptBox and Pointer Diagrams
Below find a box-and-pointer diagram for the state of the data structure after the first two lines of the code
fragment on page 9 (s has been created, s.push(exam1).) Complete the diagram showing the state of the
data structure after the end of the code fragment (after the final s.pop().gradeIt();).
top
prev value next
exam1 (exam1)
Added to the above diagram will be a second prev/value/next box, and an exam3 box. Top
will point to the box pointing to exam 3, next will point to the box pointing to exam1, prev
from that will point back to the exam 1.
Scoring: 1 for exam3, 1 for exam3 only, 1 for pointer 1 to 3, 1 for pointer 3 to 1, 1 for appropriate
nulls
17 Stack Search (8 minutes, 4 points)
Name: 11
We would like to be able to search the stack, i.e., we want a method for Stacks as follows:
boolean search(E item); // Return true if and only if item is in the stack
Please write such a method for the class Stack on page 9. Note that it should not make any changes to the
stack, only return true/false as appropriate.
Solution code:
class SearchableStack<E> extends Stack<E> {
public boolean search(E item) {
return recursiveSearch(item, top)
}
private boolean recursiveSearch(E item, DLLNode position) {
if (position == null) return false;
else if (position.getValue().equals(item)) return true;
else return recursiveSearch(item, position.getNext());
}
}
Scoring: 1 point for true if found, 1 for false if not found, 1 for getting termination right, 1 for false
if empty list, 1 for recursive solution, 1 point for noting difficulty given lack of access to previous/next in
DLLNode, 1 for writing as a class extending stack (up to 4).6 ptQueue
We would like a queue similar to stack, except that the first item put in should be the first item to come
out. It should have operations:
void enQueue(E item); // Put item at the end of the queue
E deQueue() throws NullPointerException(); // Get the first item in the queue.
Please give the code for such a class, using the DLLNode data structure.
A possible solution is:
public class Queue<E> {
DLLNode head, tail;
public void enQueue(E item) {
if (tail == null) {
DLLNode newNode = new DLLNode<E>(item);
tail = newNode;
head = newNode;
} else
tail.insertAfter(item);
}
public E deQueue() throws NullPointerException {
if (head == null) throw new NullPointerException();
else {
E result = (E)head.getValue();
head = head.deleteGetAfter();
return result;
} Name: 12
}
}
Scoring: 1 for correct class definition and methods, 1 for enQueue inserts, 1 for enQueue sets point-
ers correctly, 1 for deQueue gets right result, 1 for deQueue sets pointers correctly, 1 for proper deQueue
exception.3 ptI/O
A programmer wrote the following code to read an array of integers from a file.
String filename = "mydata";
DataInputStream stream = new DataInputStream(new FileInputStream(filename));
int[] data = new int[10000];
for(int i = 0; i < data.length; i++)
data[i] = stream.readInt();
You notice it takes a long time to read the data from the file. Explain why it slow, and suggest a way to
make it faster (for full credit, give the code to solve the problem.)
Data reading is not buffered, every read goes to the disk. Fix: change the first line to
use BufferedInputStream, i.e., new DataInputStream(new BufferedInputStream(new FileIn-
putStream(filename)));
Scoring: 1 point for buffered, 1 point for start at solution, 1 point for coded solution.4 ptPointers
class Node {
public int value;
public Node next;
}
Given a linked list of integers defined using the above class, write a recursive function that returns the
maximum value in the linked-list. (A non-recursive solution will receive at most two points.)
The following is a possible solution:
int Max(Node head) {
if(head == null)
throw new NullPointerException("head is a null pointer.");
else if(head.next == null)
return head.value;
else {
int t = Max(head.next);
if(t > head.value) return t;
else return head.value;
}
}
Scoring: 1 for proper base case, 1 for recursive case, 1 for proper calculation in recursive case, 1 for
dealing with null head.
21 Synchronization (5 minutes, 2 points)
Name: 13
public class Chess extends Thread {
private long id;
public Chess(long id){
this.id = id;
}
public void run(){
move(id);
}
// INSERT FRAGMENT HERE
System.out.print(id + " ");
System.out.print(id + " ");
}
public static void main(String[] args) {
Chess ch1 = new Chess(2);
Chess ch2 = new Chess(4);
ch1.start();
ch2.start();
}
}
Given the above and the following two code fragments:
1) void move(long id) {
2) synchronized void move(long id) {
Either give an example of output that is possible with fragment 1 but not possible with fragment 2, or
explain why any possible result of fragment 1 is also possible with fragment 2.
A synchronized method will ensure that no other process is using the current object. In
other words, when thread ch1 is started, no other thread can run the move method for object
ch1. But since the second thread is running move for object ch2, any interleaving is possible
- the synchronization has no effect on these two threads, so fragments 1 and 2 are essentially
the same.
Scoring: 1 point for any result that interleaves 2s and 4s (good idea, but not correct), 2 points for pointing
out that they synchronize on different objects, so synchronization has no effect.2 ptLooping Constructs
Given the following for loop:
int sum = 0;
for ( int i=1; i<4; i++ ) {
if ( i != 3 )
sum += i;
}
A programmer has converted the above for loop into the following while loop:
int i = 1;
int sum = 0;
while ( i < 4 ) {
if ( i != 3 ) {
sum += i;
i++;
}
}
Does the converted while loop produce the same result as the for loop? Explain your answer.
No. The result of sum after for loop is 3. However, the while loop enters an infinite loop
when i increases to 3.
Scoring: 1 for No, 1 for reasonable explanation matching answer.3 ptOverriding
Given the following two objects:
Parent p = new Parent();
Child c = new Child();
For each of the following code fragments, which of the fun() methods are executed, the one in the class
Child, the one in the class Parent, or both (and in which order)?
• Part 1: p.fun();
A fun() in Parent is executed.
B fun() in Child is executed.
C fun() in Child is called, then fun() in Parent.
D fun() in Parent is called, then fun() in Child.
• Part 2: c.fun();
A fun() in Parent is executed.
B fun() in Child is executed.
C fun() in Child is called, then fun() in Parent.
D fun() in Parent is called, then fun() in Child.
• Part 3: p = c; p.fun();
A fun() in Parent is executed.
B fun() in Child is executed.
C fun() in Child is called, then fun() in Parent.
D fun() in Parent is called, then fun() in Child.2 ptCalling Parent class
In writing the method disneyland in class Child, you want to call the fun() methods in class Child and
class Parent. Show both calls.
fun();
super.fun();
Scoring: 1 point for each as long as reasonably close.2 ptAbstract Classes
Assume Parent is an abstract class (and at least one of its methods is abstract). What changes would need
to be made to Child and why?
The Child class must implement any methods declared as abstract in the Parent class.
Scoring: 1 point for "none", 2 for "implement any abstract methods" or "none because all abstract
methods implemented".1 ptErrors
The above code will lead to a compilation error. Why?
methodA throws an exception that methodB doesn't throw or catch.
Scoring: 1 for missed exception.2 ptCorrect Use
Rewrite methodB() in two different ways so that the code compiles.
A public void methodB() throws CS180Exception {
B try {
methodA();
} catch (CS180Exception e) { }
Scoring: 1 point for getting a try/catch, 1 for throwing.1 ptInheritance
Consider the following class definitions:
public class A {
public A() { System.out.println("A"); }
public A( String str ) { System.out.println(str); }
}
public class B extends A {
public B() { System.out.println("B"); }
public B( String str ) { System.out.println(str); }
}
Which code segment would produce output different from the rest:
A new B(); new A();
B new B("B"); new A();
C new A(); new B("B");
D new B("B"); new A("A");
Answer: C (A,B,D produces ABA while C produces AAB)2 ptPart 1
public class Point {
public int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Q1 {
public static void increasePoint(Point p, String str) {
str = "new point is :";
p.x = p.x+1;
p.y = p.y+1;
}
public static void main(String[] args) {
String str = "old point is";
Point p = new Point(1,1);
System.out.println(str+"("+p.x+","+p.y+")");
increasePoint(p,str);
System.out.println(str+"("+p.x+","+p.y+")");
}
}
old point is(1,1)
old point is(2,2)
Scoring: 1 for "old point is" for both, 1 for 1,1 followed by 2,2.2 ptPart 2
public class Q2 {
public static void increment(int x) {
x=x+1;
}
public static void main(String[] args) {
int x = 0;
while(x<5) {
increment(x);
System.out.println(x);
}
}
}
This enteres an infinite loop printing 0.
Scoring: 1 for 0, 1 for infinite loop.2 ptPart 3
public class Q3 {
static int x = 0;
static int y = 0;
public static void increment(int x)
{
x = x+1;
y = y+1;
}
public static void main(String[] args)
{
increment(x);
System.out.println(x);
System.out.println(y);
}
}
Scoring: 1 for 0, 1 for 1.2 ptLinked Data Structures
import java.util.LinkedList;
public class Element {
public int value;
public void addToList( LinkedList<Element> linkList ) {
Element e = new Element();
for ( int i=0; i<10; i++ ) {
e.setValue(i);
linkList.add(e);
}
}
public void setValue( int value ) {
this.value = value;
}
}
If addToList is invoked, I claim that all 10 'Elements' in linkList will have the same 'value' 9. True
or False? Explain. (Answer valid only with correct explanation) Hint: You don't have to worry about how
java.util.LinkedList works - the answer is the same with any reasonable implementation of a LinkeList, such
as those shown in class. And yes, this does compile.
Only a single Element object is created, and it is inserted into the list multiple times. Since
the setValue is operating on that one object, each time it sets the value, it essentially changes
the value of everything in the list.
Scoring: 2 for catching idea that only one element, 1 for showing reasonable understanding of linked list
in another way.1 ptUse of Inherited classes
What will be the result of attempting to compile and run the following program?
public class Polymorphism {
public static void main(String[] args) {
A ref1 = new C();
B ref2 = (B) ref1;
System.out.println(ref2.f());
}
}
class A { int f() { return 0; } }
class B extends A { int f() { return 1; } }
class C extends B { int f() { return 2; } }
Select the one correct answer:
A The program will fail to compile.
B The program will compile without error, but will throw a ClassCastException when run.
C The program will compile without error and print 1 when run.
D The program will compile without error and print 2 when run.10 ptCreating a Data Abstraction
In this question, you will create parts of a GradeBook class and methods. A GradeBook contains assignments, for each assignment there is a score for each student. You will have to decide what data types / data structures to use. Note: There is a lot of partial credit available for even getting small pieces right, so try to write even a partial answer every part even if you know your entire answer isn't correct.
3 ptClass Definition
Write the basic class definition, with fields to hold the assignments. For full credit, your definition should
not limit how many assignments a GradeBook can have. If you want to define multiple classes, that is okay
- but you should at least have a GradeBook class.
public class GradeBook {
float grades[][];
}
Scoring: 1 for basic definition, 1 for field(s) for assignments, 1 for holding students.4 ptConstructor
Create a constructor that takes the number of assignments and number of students as arguments, and creates
the objects needed for your GradeBook to store the assignment grades. (Note that it would be nice if the
GradeBook wasn't limited to the provided number of assignments, but it is okay if it is.)
public GradeBook(int asn, int stud) {
grades = new float[asn][stud];
}
Scoring: 1 for proper constructor, 1 for arguments, 2 for instantiating fields as appropriate (1 if partially
done.)3 ptCalculation
Create a method mean in your GradeBook class that takes an assignment number as an argument, and
returns the average (mean) score on that assignment.
public float mean(int asn) {
float sum = 0.0f;
for ( int i=0; i<grades[asn].length; i++ )
sum += grades[asn][i];
return sum / grades[asn].length;
}
Scoring: 1 for method with proper argument, 1 for proper return type, 1 for use of objects.5 ptRecursion
Given the following recursive methods:
public int f( int x ) public int g( int x )
{ {
if ( x == 1 ) if ( x == 0 )
return 1; return 0;
else else
return x * f(x-1); return f(x) + g(x-1);
} }3 ptUnderstanding the code
What is returned by g(4); ? If you aren't certain, showing your work may get you partial credit even if you
get the wrong answer.
This is a sum of factorials, 4! + 3! + 2! + 1! = 24 + 6 + 2 + 1 = 33.
Scoring: 3 for correct (or clearly understands but arithmetic error), 2 for showing correct understanding
of one method, 1 for showing some understanding of recursion.1 ptIdentifying code problems
The above code will fail with some inputs. Give an example input x where g(x) will fail.
g applied to a negative number does not terminate.
Scoring: 1 for any negative example.1 ptFixing problems
Revise the code of method f or g to prevent the failure you identified in 9.2.
The first line of g should be changed to: if ( x <= 0 )
Scoring: 1 for any legal check for < 0 in g, or if they came up with a different issue in previous question,
a solution to their issue.6 ptLinked Data Structures
A circular linked list is a list in which the link field of the last node is made to point to the start/first node
of the list. The diagram at the right shows a CircularLinkedList with nodes added in the order E0, E1, E2,
E3. To help you to implement this class, we provide you the following class definitions:
class Node<E> {
public E info;
public Node<E> next; E2
public Node (E info, Node<E> next) startNode
{
this.info = info; E3 E1
this.next = next;
}
}
E0
public class CircularLinkedList<E> {
private Node<E> startNode;
public CircularLinkedList () {
startNode = null;
}
public void insert(E item) {
/* item E is inserted at the position of the startNode and becomes
the new start of the circular linked list. This new start
node's next attribute should point to the original startNode.
Be sure that after inserting, the list still a valid circular list. */
// Solution below.
Node<E> temp = new Node<E>(item, startNode);
if ( startNode == null )
temp.next = temp;
else {
temp.next = startNode;
Node<E> current = startNode;
while ( current.next != startNode ) current = current.next;
current.next = temp;
}
startNode = temp;
// Solution ends here.
}
}
Your task is to implement the insert method of the CircularLinkedList class (fill in the insert method.)
Hint: You should consider two possible cases: when the list is empty and when it has at least one element.
Scoring: For each case (empty list, non-empty list), you can get 1 point for creating a new node with the
correct value, 1 for having startNode point to the new node, and 1 for the tail pointing to this new node. If
this doesn't add up to six, you may receive up to two points for a generally correct structure that shows an
understanding of linked lists.3 ptFactorButtonListener
At Part 1, finish the implementation of FactorButtonListener, which will be the ActionListener when the
factorsButton JButton is pressed. When the button is pressed, the number can be retrieved from the
numberField JTextField with the getText method of JTextField (you'll have to convert the text to the
integer yourself). For simplicity, you may assume that the text will always contain an integer.
Scoring: 1 point for defining ActionPerformed, 1 for getting text and performing any attempt at converting
to integer, 1 for starting thread.2 ptRegister Listener
At Part 2, add code which registers an instance of your FactorButtonListener as the ActionListener to
factorsButton.
Scoring: 1 for adding listener, 1 for creating instance of FactorButtonListener.2 ptConcurrency
Write a thread class ConcurrentFactorsThread which computes the factors of its given number and prints
them out on the console.
Solution:
public class ConcurrentFactorsThread extends Thread
{
private int num;
public ConcurrentFactorsThread(int num)
{
this.num = num;
}
@Override
public void run()
{
for (int i=1; i<=num; i++)
{
if (num % i == 0)
System.out.printf("%d is a factor of %d\n", i, num);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
Scoring: 1 each for reasonable definition of class/constructor, 1 for reasonable definition of run method.9 ptFile I/O
Write a program that reads in lines from the file "input.txt", and writes the lines to the file "output.txt" in
the opposite order (last line in input.txt is the first in output.txt, 2nd to last in input.txt is 2nd in output.txt,
etc.)
For example, if the file "input.txt" contains:
CS180 is awesome
CS180 is very awesome
CS180 is very very awesome
then your program should create a file "output.txt" containing:
CS180 is very very awesome
CS180 is very awesome
CS180 is awesome
For full credit (worth one point), you should have a class with a method
void reverse(Scanner in, PrintWriter out) . You can ignore exception handling - it is okay to assume
that none of the methods you call throw exceptions.
Hints: Scanner has a method String nextLine() and boolean hasNextLine(), PrintWriter has a
method
void println(String x). Both have constructors that take a File or InputStream object as an argument;
a File can be constructed with a String argument (the name of the file.) Given this information, there is
a very simple recursive solution.
Solution follows:
import java.util.*;
import java.io.*;
public class Reverse {
public static void reverse(Scanner in, PrintWriter out) {
if ( in.hasNextLine() ) {
String line = in.nextLine();
reverse(in, out);
out.println(line);
}
}
public static void main(String args[]) {
try {
PrintWriter out = new PrintWriter(new File("output.txt"));
reverse(new Scanner(new File("input.txt")), out);
out.close();
} catch (FileNotFoundException e) { }
}
}
Scoring: 1 for reverse method, 1 for constructing Scanner/Printwriter (or InputStream/OutputStream)
objects, 1 for constructing properly from given file names, 1 for appropriate reading and/or writing, 1-3 for
quality of "reverse" logic (1 for idea, 2 for workable idea, 3 for correct), 1 for having class, 1 for main()The Trap Sheet
If you read nothing else the night before the exam, read this.
| You wrote | Java heard | Fix |
|---|---|---|
| 5 / 2 | 2 — integer division | 5.0 / 2 or (double) 5 / 2 |
| (int) 3.99 | 3 — chops, never rounds | Math.round(3.99) |
| s1 == s2 | same address? usually false | s1.equals(s2) |
| s.toUpperCase(); | computed, thrown away | s = s.toUpperCase(); |
| arr.length() | compile error | arr.length (no parens) |
| str.length | compile error | str.length() |
| list.length() | compile error | list.size() |
| i <= arr.length | one pass too many | i < arr.length |
| substring(2, 5) | indices 2,3,4 — end excluded | length is end - start |
| case 3: no break; | falls into every case below | break; on every case |
| public void Boiler() | a method, not a constructor | public Boiler() |
| ArrayList<int> | compile error | ArrayList<Integer> |
| nextInt() then nextLine() | empty string | extra kb.nextLine(); |
| PrintWriter without close() | empty / truncated file | out.close(); |
| t.run() | runs on the current thread | t.start(); |
| catch (Exception) first | unreachable catch, compile error | specific to general |
| bump(x) on an int | caller unchanged — copy | return the new value |
| new String[3] | three nulls, not "" | fill before use |
| super(...) not first | compile error | super(...) on line 1 |
| overriding with new params | silent overload | @Override catches it |
Programming Questions
The multiple choice is 40 of the 100 points. The rest is you writing Java on paper — so practise it on paper.
Format, from Purdue's own published papers: Exam 1 is 20 MCQ at 2 points (40) plus 3 programming questions worth 60. The final is 30 MCQ at 3 points (90) plus 4 programming questions worth 110. Sources: Exam 1 key · Final key. These are the archived papers; some semesters add fill-in-the-blank and short answer, so confirm with your instructor.
20 pts Write countVowels(String s) — return how many vowels the string contains, ignoring case.
public static int countVowels(String s) {
int count = 0;
String vowels = "aeiou";
for (int i = 0; i < s.length(); i++) {
char c = Character.toLowerCase(s.charAt(i));
if (vowels.indexOf(c) != -1) { // -1 means "not found"
count++;
}
}
return count;
}Marks come from: using s.length() with parentheses, charAt returning a char (not a String), handling case, and returning on every path. The indexOf trick avoids a five-way || chain.
20 pts Write secondLargest(int[] a) — return the second largest value. Assume the array has at least two elements.
public static int secondLargest(int[] a) {
int first = Integer.MIN_VALUE;
int second = Integer.MIN_VALUE;
for (int i = 0; i < a.length; i++) {
if (a[i] > first) {
second = first; // the old champion slides down
first = a[i];
} else if (a[i] > second && a[i] != first) {
second = a[i];
}
}
return second;
}Marks come from: one pass, not sorting; seeding with Integer.MIN_VALUE rather than 0 (negative arrays); and demoting first into second in the right order. Sorting a copy also earns full marks unless the question forbids it.
20 pts Given the Node class from module 21, write sum(Node head) — total of every value in the list.
public static int sum(Node head) {
int total = 0;
Node cur = head;
while (cur != null) { // null is the stop sign
total += cur.data;
cur = cur.next;
}
return total;
}public static int sum(Node head) {
if (head == null) return 0; // base case: empty list
return head.data + sum(head.next); // shrink toward the base case
}Marks come from: never moving head itself, stopping on null rather than on cur.next == null, and handling the empty list. Either version is full marks.
30 pts Write a class Account with a private balance, a constructor, deposit, a withdraw that refuses to overdraw, and toString.
public class Account {
private String owner;
private double balance;
public Account(String owner, double balance) {
this.owner = owner;
this.balance = balance;
}
public double getBalance() { return balance; }
public void deposit(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("deposit must be positive");
}
balance += amount;
}
public void withdraw(double amount) {
if (amount > balance) {
throw new IllegalArgumentException("insufficient funds");
}
balance -= amount;
}
@Override
public String toString() {
return owner + ": $" + balance;
}
}Marks come from: private fields with public accessors, a constructor with no return type using this. to disambiguate, validating before mutating, and @Override on toString. Losing marks here is almost always public void Account(...) or public fields.
Trace Quiz
Read the code, commit to an answer, then click. Guessing and checking teaches nothing.