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?


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:

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:

ArrayList<String> 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:

// 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<T> 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

public class Student implements Comparable<Student> {
    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<Student>: 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?

The Complete Main Program

This program ties together file I/O, object creation, sorting, and report generation:

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<Student> 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<Student> readStudents(final String filename)
            throws FileNotFoundException {
        ArrayList<Student> 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<Student> 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?


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 (<T>)
  • 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.