Unit 13 · lesson

An Exception Marks a Failed Runtime Assumption

You have already seen runtime failures such as invalid integer parsing and invalid array indexes.

Integer.parseInt("twelve")

The source can compile because parsing a String into an int is a valid operation to request. At runtime, the specific text cannot satisfy the parser's contract.

The exception carries evidence about that failure.

Concept flow

An exception exposes a failed runtime assumption

The exception type and context help locate the first operation that could not honor its contract.

  1. INPUT / STATEa concrete value reaches an operation
    requires
  2. ASSUMPTIONthe operation has a contract the value must satisfy
    fails at
  3. EXCEPTIONtype and message carry failure evidence
    locate
  4. RESPONSIBLE BOUNDARYidentify the first failed contract
    respond
  5. POLICYvalidate, handle, propagate, or fail fast deliberately

Read the exception in layers

For a small classroom program, identify at least:

exception type
message / failed value when available
first relevant line in your own code
operation being attempted
assumption that operation required

Do not begin by copying the whole stack trace into a search engine.

For:

int score = Integer.parseInt(text);

the useful model is raw text crossing a parse boundary into typed state. If parsing fails, the defect or invalid data exists at that boundary. Rewriting a downstream average method cannot fix it.

Exceptions are objects too

An exception has a type and carries information.

You can catch a specific type:

try {
    int value = Integer.parseInt(text);
    IO.println(value);
} catch (NumberFormatException ex) {
    IO.println("Invalid integer: " + text);
}

The catch block runs only when the matching failure occurs within the try block.

Validate before an operation when the rule is yours

If your domain says score must be 0 through 100, parsing and validation are separate:

int score = Integer.parseInt(text);

if (score < 0 || score > 100) {
    throw new IllegalArgumentException("score out of range");
}

"120" parses correctly as an integer. Your application rejects the typed value because it violates the domain contract.

Fail fast near the violated contract

Suppose a method requires positive sample count:

double average(int total, int count) {
    if (count <= 0) {
        throw new IllegalArgumentException("count must be positive");
    }
    return (double) total / count;
}

The failure occurs at the method boundary where the violated assumption is understood.

Allowing bad state to flow deeper can make the eventual exception farther from the root cause.

Classify five failures

For each, identify whether you would expect:

  • compile-time rejection;
  • runtime exception from a Java/library operation;
  • explicit application exception;
  • logic failure with no exception.

Cases:

  1. "abc" passed to Integer.parseInt.
  2. score 120 parsed successfully but forbidden by domain.
  3. accessing values[values.length].
  4. percentage calculated with integer division.
  5. assigning a String to an int variable.

Evidence

Build one program that demonstrates two different runtime failures at two different boundaries. Preserve the original failing input and identify the assumption behind each failure.

Then add the minimum validation or exception handling required by the application's actual policy. Do not catch everything just to make red text disappear.