Interfaces and Abstraction
Define contracts with interfaces, prefer composition over inheritance, and hide detail with access modifiers.
Why it matters
Start from the concept, not the syntax
Meet a concrete situation where this idea earns its place, then state the boundary it guards.
An interface is a promise: any class that implements it can do these things. Programming against promises rather than concrete types keeps code flexible, and default methods let those promises grow without breaking existing implementers.
By the end of this chapter
Leaking implementation through public fields and concrete types makes code rigid and impossible to change safely.
- Interface contracts
- Default methods
- Access modifiers
Mechanism
How Java expresses the concept
Walk the actual types, rules, and runtime behavior involved—the same behavior described in the Java Language Specification.
The mental model
An interface defines a contract and may also provide default, static, or private methods. A class can implement many interfaces but extend only one class; use interfaces for abstraction and substitutability, while composition means assembling objects that collaborate.
Java 8 added default methods (`default`) so interfaces can gain behavior without forcing every implementer to change, and static interface methods for shared helpers. Java 9 added private interface methods for code shared between defaults.
Access modifiers control visibility: `private` (class only), package-private (no modifier, same package), `protected` (package plus subclasses), and `public` (everywhere). Favor the narrowest modifier that works; encapsulation is a promise about what you will not change.
Abstraction is choosing what to expose. An interface exposes capability and hides how; a well-designed API lets the internals change without disturbing callers. Combine interfaces with package-private implementation classes to hide detail.
Concept map
Inspect the building blocks as a whole
Use the map as a structural reference; it shows the pieces and their relationships, not an execution sequence.
Core Java
Interfaces and abstraction
An interface declares a contract of capabilities; a class implements it. Default methods let interfaces evolve without breaking implementers.
- 01Contract by interface
- 02Multiple interfaces, one superclass
- 03Default methods
- 04Access modifiers
- 05Abstraction as a promise
- 06Hide implementation detail
Implementation
Encode the smallest runnable example
Write and run the code, then observe the behavior you just predicted with a real Java program.
Runnable snippet path
Predict, run, and change each example
Implement an interface
The class promises to supply every interface method; default methods are optional to override.
interface PricingPolicy {
int price(int base);
default String label() { return "standard"; }
}
class Discounted implements PricingPolicy {
@Override public int price(int base) { return base / 2; }
}Remember
Program against the interface type so the concrete class can be swapped.
Change one input, predict the result, then compile or test it before continuing.
Narrow access
Keep state private; expose only what callers need.
public class Wallet {
private int cents;
public int cents() { return cents; }
void add(int c) { if (c > 0) cents += c; }
}Remember
Package-private (no modifier) is tighter than public and often the right default for internals.
Change one input, predict the result, then compile or test it before continuing.
Watch out
Break it on purpose, then repair the right layer
Predict the symptom before running the failure case, and close with the completion checklist.
Deliberate failure
Break
Return a mutable ArrayList from an API method and let callers modify it
Observe
Internal state changes from outside and invariants break silently
Repair
Program to interfaces and return immutable or copied collections so internals stay private
Why it matters
Program to interfaces and return immutable or copied collections so internals stay private
Completion checklist
- Define behavior with an interface
- Evolve contracts with default methods
- Apply the narrowest access modifier that works
Go deeper
Official references
The primary sources behind this chapter. Every claim above stays consistent with them.