oop Lesson 9 22 min read

Capstone Review and APE Preparation

Connecting all 10 weeks — from types to objects

Reading: Reges & Stepp: Ch. 1–10 (review)

After this lesson, you will be able to:

  • Trace a multi-class Java program from file input through object creation, sorting, and output
  • Identify which concept (types, control flow, arrays, I/O, OOP) applies to a given problem
  • Write a complete integration program that combines all 10 weeks of material
  • Prepare strategically for the final exam and the Advanced Proficiency Exam (APE)

Ten Weeks in One Question

Suppose someone hands you a CSV file of student records and says: “Read this data, sort the students by GPA, and write a formatted report to a new file.” To solve that, you need every single concept from this course: types to parse the data, control flow to loop through lines, arrays or ArrayLists to store objects, file I/O to read and write, classes to model a Student, and Comparable to define the sort order.

That is the point of this lesson. Not a single new concept — just the skill of combining everything you already know into a working program. This is what the final exam tests, what the APE tests, and what real-world programming demands.

From CSCD 110: In CSCD 110, you could read a file, loop through lines, split strings, and print output — all in about 15 lines of Python. Java requires more ceremony (type declarations, try/catch, class definitions), but the underlying logic is identical. The journey from Python to Java was never about learning new ideas. It was about learning to express the same ideas within a stricter type system. You now have that skill.


The Complete Toolkit: Quick Reference

Every major concept from Weeks 1–10 in one table. Use this as a checklist when studying.

Theme Concepts Key Syntax Common Traps
Types int, double, boolean, char, String int x = 5; int division truncates; String is a reference
Casting Widening (auto), narrowing (explicit) (double) x, (int) y (double)(a/b) truncates first
Comparison Primitives: ==; doubles: epsilon; Strings: .equals() Math.abs(a - b) < 1e-9 == on Strings compares addresses
Conditionals if/else, switch, ternary, &&/|| if (x > 0) { } Chained comparisons invalid; missing break in switch
Loops for, while, do-while for (int i = 0; i < n; i++) Off-by-one; fencepost errors
Methods Parameters, return types, overloading, scope public static int foo(final int n) Pass-by-value; scope dies at }
Arrays Fixed-size, typed, 0-indexed int[] a = new int[10]; No .add(); ArrayIndexOutOfBoundsException
ArrayList Dynamic size, generic type ArrayList<String> list = new ArrayList<>(); Cannot hold primitives directly; use wrapper types
File I/O Scanner + File, PrintStream new Scanner(new File("data.txt")) Must handle FileNotFoundException
Exceptions try/catch, checked vs unchecked try { } catch (Exception e) { } Catching too broadly hides bugs
Classes Fields, constructors, getters, toString, equals public class Point { } Forgetting this.; public fields break encapsulation
Interfaces Contracts, Comparable<T>, compareTo implements Comparable<Student> Return int, not boolean; sign matters
Sorting Collections.sort(), Arrays.sort() Collections.sort(list); Class must implement Comparable
References Stack vs heap, aliasing, null Point p = new Point(3, 4); == compares references; NullPointerException

Theme 1: The Type System

The type system is the foundation of everything in Java. Every variable, every parameter, every return value has a declared type that the compiler enforces.

Primitives vs References:

Primitives (store values directly):    References (store addresses):
  int x = 42;                           String s = "hello";
  double d = 3.14;                      int[] arr = new int[5];
  boolean done = false;                 Student stu = new Student("Alice", 3.8);
  char c = 'A';

The three comparison rules (these appear on every exam):

  1. Primitives (int, double, char, boolean): use ==
  2. Floating-point precision: use Math.abs(a - b) < epsilon
  3. Objects (String, arrays, your classes): use .equals()

Casting: Widening happens automatically (int to double). Narrowing requires an explicit cast and truncates: (int) 3.99 produces 3, not 4.

Check Your Understanding
What does double result = (double)(7 / 2); assign to result?</p>
A3.5
B3.0
C3
DCompiler error
The parentheses force 7 / 2 to evaluate first as integer division, producing 3. Then (double) 3 widens to 3.0. To get 3.5, cast before dividing: (double) 7 / 2.
--- ## Theme 2: Control Flow Every program beyond "Hello, World" needs decisions and repetition. **Conditionals** choose a path: `if/else`, `switch`, ternary. **Loops** repeat work: `for` (known count), `while` (unknown count), `do-while` (at least once). **The six accumulator patterns** show up constantly: | Pattern | Init | Update | Example Use | |---------|------|--------|-------------| | Counter | `int count = 0;` | `count++` | How many even numbers? | | Sum | `int sum = 0;` | `sum += value` | Total of all scores | | Product | `int prod = 1;` | `prod *= value` | Factorial | | Max | `int max = Integer.MIN_VALUE;` | `if (v > max) max = v;` | Highest score | | Min | `int min = Integer.MAX_VALUE;` | `if (v < min) min = v;` | Lowest score | | Flag | `boolean found = false;` | `found = true;` | Does a target exist? | **Methods** encapsulate logic. Every method has a return type, a name, and parameters. Java is pass-by-value: a method gets a *copy* of each argument, so modifying a parameter inside a method does not change the caller's variable. --- ## Theme 3: Data Structures **Arrays** are fixed-size, typed containers. You declare the size at creation and cannot change it: ```java int[] scores = new int[30]; // 30 slots, all initialized to 0 scores[0] = 95; // first element scores[scores.length - 1] = 88; // last element ``` **ArrayList** is a resizable alternative that wraps an array internally: ```java ArrayList names = new ArrayList<>(); names.add("Alice"); names.add("Bob"); names.remove(0); // removes "Alice" System.out.println(names.size()); // 1 ``` Arrays use `[]` and `.length`. ArrayLists use `.get()`, `.set()`, `.add()`, `.remove()`, and `.size()`. Arrays can hold primitives directly; ArrayLists require wrapper types (`Integer`, `Double`). --- ## Theme 4: File I/O and Exceptions Reading from a file uses `Scanner` with a `File` object. Writing uses `PrintStream`. Both require handling `FileNotFoundException`: ```java // Reading Scanner input = new Scanner(new File("data.txt")); while (input.hasNextLine()) { String line = input.nextLine(); // process line } input.close(); // Writing PrintStream output = new PrintStream(new File("report.txt")); output.println("Header"); output.close(); ``` **Exception handling** uses `try/catch`. The method signature declares checked exceptions with `throws`. Inside the method, `try` wraps risky code and `catch` handles failures gracefully instead of crashing. --- ## Theme 5: Object-Oriented Programming A **class** is a blueprint. An **object** is an instance of that blueprint. Encapsulation means fields are `private` and accessed through `public` methods (getters/setters). Key methods every class should have: - **Constructor:** initializes fields - **toString():** returns a human-readable representation - **equals():** compares logical equality (not reference identity) - **compareTo():** defines natural ordering (if the class implements `Comparable`) **Interfaces** define a contract. `Comparable` requires a `compareTo` method that returns a negative integer, zero, or a positive integer. Once a class implements `Comparable`, you can sort collections of it with `Collections.sort()`. --- ## The Integration Example: Student Roster Application This is the capstone pattern: **read from file, create objects, sort, generate output**. Every piece of the course contributes. ### The Data File (`students.csv`) ``` Alice,1001,3.8 Bob,1002,3.2 Charlie,1003,3.5 Zoe,1005,3.8 Diana,1004,3.9 ``` ### The Student Class ```java public class Student implements Comparable { private String name; private int id; private double gpa; public Student(final String name, final int id, final double gpa) { this.name = name; this.id = id; this.gpa = gpa; } // Sort by GPA descending, then by name ascending as tiebreaker public int compareTo(final Student other) { int gpaResult = Double.compare(other.gpa, this.gpa); if (gpaResult != 0) { return gpaResult; } return this.name.compareTo(other.name); } public String getName() { return name; } public int getId() { return id; } public double getGpa() { return gpa; } @Override public String toString() { return String.format("%s (ID: %d, GPA: %.2f)", name, id, gpa); } } ``` Notice what this class uses: - **Encapsulation:** private fields, public getters - **`Comparable`:** the interface contract - **`compareTo`:** multi-field sorting (GPA first, name as tiebreaker) - **`toString`:** formatted output with `String.format` - **`final` parameters:** Dr. Steiner's convention
Check Your Understanding
If Alice has GPA 3.8 and Zoe has GPA 3.8, what does alice.compareTo(zoe) return?</p>
AA positive number (Alice comes after Zoe)
BA negative number (Alice comes before Zoe)
CZero (they are equal)
DIt throws an exception
GPAs are equal, so Double.compare(other.gpa, this.gpa) returns 0. The tiebreaker kicks in: "Alice".compareTo("Zoe") returns a negative number because "A" comes before "Z" alphabetically. So Alice sorts before Zoe.
### The Complete Main Program This program ties together file I/O, object creation, sorting, and report generation: ```java import java.io.File; import java.io.FileNotFoundException; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; public class HonorRollReport { public static void main(final String[] args) { try { // Step 1: Read students from CSV file ArrayList students = readStudents("students.csv"); System.out.println("Read " + students.size() + " students."); // Step 2: Sort by GPA (descending), then name Collections.sort(students); // Step 3: Print sorted list to console System.out.println("\nSorted Student List:"); for (Student s : students) { System.out.println(s); } // Step 4: Write formatted report to file writeReport(students, "honor_roll.txt"); System.out.println("\nReport written to honor_roll.txt"); } catch (FileNotFoundException e) { System.err.println("Error: " + e.getMessage()); } } /** * Read student records from a CSV file. * Format: name,id,gpa * * @param filename path to the CSV file * @return list of Student objects * @throws FileNotFoundException if the file does not exist */ public static ArrayList readStudents(final String filename) throws FileNotFoundException { ArrayList students = new ArrayList<>(); Scanner input = new Scanner(new File(filename)); while (input.hasNextLine()) { String line = input.nextLine(); if (line.trim().isEmpty()) { continue; } try { String[] parts = line.split(","); String name = parts[0].trim(); int id = Integer.parseInt(parts[1].trim()); double gpa = Double.parseDouble(parts[2].trim()); students.add(new Student(name, id, gpa)); } catch (NumberFormatException e) { System.err.println("Warning: Bad data in line: " + line); } } input.close(); return students; } /** * Write a sorted honor roll report to a file. * * @param students sorted list of students * @param filename output file path * @throws FileNotFoundException if the file cannot be created */ public static void writeReport(final ArrayList students, final String filename) throws FileNotFoundException { PrintStream output = new PrintStream(new File(filename)); output.println("=== HONOR ROLL REPORT ==="); output.println(); for (int i = 0; i < students.size(); i++) { Student s = students.get(i); output.printf("%d. %s - GPA: %.2f%n", i + 1, s.getName(), s.getGpa()); } output.println(); output.println("Total Students: " + students.size()); double totalGpa = 0; for (Student s : students) { totalGpa += s.getGpa(); } output.printf("Average GPA: %.2f%n", totalGpa / students.size()); output.close(); } } ``` **Output (console):** ``` Read 5 students. Sorted Student List: Diana (ID: 1004, GPA: 3.90) Alice (ID: 1001, GPA: 3.80) Zoe (ID: 1005, GPA: 3.80) Charlie (ID: 1003, GPA: 3.50) Bob (ID: 1002, GPA: 3.20) Report written to honor_roll.txt ``` **Output (honor_roll.txt):** ``` === HONOR ROLL REPORT === 1. Diana - GPA: 3.90 2. Alice - GPA: 3.80 3. Zoe - GPA: 3.80 4. Charlie - GPA: 3.50 5. Bob - GPA: 3.20 Total Students: 5 Average GPA: 3.64 ``` > **Key Insight:** This read-sort-process pipeline is the canonical pattern for real-world programs. Banking systems read transactions and generate statements. E-commerce platforms read orders and generate shipping lists. The data changes; the structure stays the same. --- ## Concept Map: How Everything Connects ``` Types & Expressions │ ▼ Control Flow (if/else, loops) │ ▼ Methods (parameters, returns, scope) │ ├──────────────────┐ ▼ ▼ Arrays / ArrayList File I/O (Scanner, PrintStream) │ │ └────────┬─────────┘ ▼ Classes & Objects (fields, constructors, encapsulation) │ ▼ Interfaces & Comparable (contracts, sorting) │ ▼ ★ Integration: Read → Create → Sort → Report ★ ``` Every level builds on the one above it. You cannot write the integration program without understanding all the layers. --- ## APE Preparation Tips The **Advanced Proficiency Exam** tests whether you can move directly into upper-division CS courses. Here is what to focus on: **What the APE tests:** - Code tracing (types, casting, expressions, method calls) - Writing methods from descriptions (IPO: Input, Process, Output) - Array and ArrayList manipulation (traversal, search, modification) - Object-oriented design (classes, encapsulation, `toString`, `equals`) - Interfaces and `Comparable` (writing `compareTo`, using `Collections.sort`) - File processing (reading, parsing, exception handling) **Study strategy:** 1. **Trace before you write.** For every code example in this course, predict the output by hand before running it. 2. **Practice the patterns.** Counter, sum, max, min, flag --- you should be able to write these in your sleep. 3. **Write complete programs.** The APE does not ask you to fill in blanks. It asks you to produce working code from scratch. 4. **Know the comparison rules.** Primitives use `==`. Strings use `.equals()`. Objects use `.equals()` or `.compareTo()`. Doubles use epsilon comparison. 5. **Understand references.** Know the difference between stack and heap. Know what aliasing means. Know when `==` compares values and when it compares addresses.
Check Your Understanding
You have a class Book that implements Comparable<Book> and an ArrayList<Book> books loaded from a file. Which single line sorts the list?</p>
Abooks.sort();
BCollections.sort(books);
CArrays.sort(books);
Dbooks.compareTo();
Collections.sort() works on ArrayList (and any List). Arrays.sort() works on raw arrays, not ArrayLists. books.sort() without a Comparator argument is valid in modern Java but was not covered in this course --- stick with Collections.sort(). compareTo() is an instance method called on one object, not on the list itself.
--- ## What Comes Next: CSCD 211 CSCD 211 (Programming Principles II) picks up exactly where this course ends. Here is what you will encounter: - **Inheritance and polymorphism:** Extending classes, method overriding, the `super` keyword, abstract classes - **Recursion:** Methods that call themselves --- the tree traversal pattern, divide-and-conquer algorithms - **Linked lists:** Building your own data structure with nodes and references (no arrays) - **Stacks and queues:** Abstract data types built on linked lists - **Generics:** Writing classes that work with any type (``) - **Algorithm analysis:** Big-O notation --- measuring how fast code runs as input grows Everything you learned here --- types, control flow, arrays, file I/O, classes, interfaces --- is prerequisite knowledge for CSCD 211. The better you understand this material, the smoother that transition will be. --- ## Summary This course took you from `System.out.println("Hello, World!")` to a multi-class application that reads files, creates objects, sorts them, and generates reports. The progression was deliberate: 1. **Weeks 1--2:** Types, expressions, and the discipline of static typing 2. **Weeks 3--4:** Control flow --- making decisions and repeating work 3. **Week 5:** Methods --- decomposing problems into reusable pieces 4. **Week 6:** Arrays --- your first real data structure 5. **Week 7:** File I/O --- connecting programs to the outside world 6. **Weeks 8--9:** Objects, classes, and interfaces --- modeling the real world in code 7. **Week 10:** Integration --- combining all of the above into complete programs The final exam and the APE test your ability to combine these tools. Study the patterns, trace code by hand, and practice writing complete programs. You have the toolkit. Now use it.