Topic 5.7
Interfaces
In one line
An interface is a named list of abilities, a contract, that any class can promise to provide with implements. A class can implement many interfaces, and code written against an interface works with every class that implements it.
Think of it like this
A wall socket. The socket doesn't care whether you plug in a phone charger, a lamp or a kettle. It only cares that the plug has the right shape. Anything with that plug works. An interface is the plug shape: a promise about what something can do, with no say in how it's built inside.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Interface
- A type that lists methods (a contract) without saying how they work. Declared with the keyword
interface. - implements
- The keyword a class uses to promise it provides all the methods of an interface.
- Contract
- The promise an interface makes: any object of this type has these methods with this meaning.
- Implicitly public abstract
- Interface methods without a body are automatically public and abstract, even if you don't write those words.
- Constant
- A
public static finalfield. All fields in an interface are constants. - Marker interface
- An interface with no methods, used only as a label, like
Serializable. - Program to an interface
- Declare variables and parameters with interface types (
List) rather than concrete classes (ArrayList) so implementations can change.
Step by step
01Writing the contract
An online shop accepts cards and UPI. The checkout doesn't care how money moves, only that it can ask 'pay this amount' and get yes or no. That's the contract.
boolean pay(double amount); has no body and no modifiers, yet it is public abstract. Writing public abstract explicitly is legal but redundant.
interface PaymentMethod {
boolean pay(double amount); // public abstract, implicitly
String name();
}02Fulfilling it with implements
Each class says implements PaymentMethod and provides a body for both methods. These bodies must be public, because the interface's methods are public. Forgetting public is the most common interface compile error.
Card and Upi share no code and no parent class (apart from Object), yet both can be passed anywhere a PaymentMethod is expected.
class Card implements PaymentMethod {
private double limit;
Card(double limit) { this.limit = limit; }
public boolean pay(double amount) {
if (amount > limit) return false;
limit -= amount;
return true;
}
public String name() { return "Card"; }
}03Depend on the interface, not the class
Checkout receives a PaymentMethod in its constructor and never mentions Card or Upi. Add a Wallet class next year and Checkout doesn't change. This is the dependency inversion principle and the core of the Strategy pattern (System Design course, /topic/phase-2/strategy).
It also makes testing easy: pass a fake PaymentMethod that always returns true.
04Many interfaces, one class
A Duck can swim and fly; a Fish can only swim; a Plane can only fly. These capabilities don't fit a single family tree: is Duck under Swimmer or under Flyer? With interfaces it doesn't matter. Duck implements both.
Because interface methods (originally) had no bodies, implementing two interfaces that both declare void move() causes no conflict: the class writes one move() that satisfies both. Default methods add a wrinkle, which Topic 5.8 resolves.
05Interface constants
int MAX_ALTITUDE = 1000; inside an interface is public static final. Every implementing class can use the bare name, and others can write Flyer.MAX_ALTITUDE. You cannot assign to it.
Effective Java warns against the constant interface anti-pattern: implementing an interface just to get short names for constants leaks those constants into your class's public API. Put constants in a final class or an enum, and use import static.
06Interfaces you already use
Comparable<T> (one method, compareTo) lets Collections.sort order your objects. Runnable (one method, run) is what threads execute (Topic 13.1). List, Set, Map are interfaces; ArrayList, HashSet, HashMap are classes implementing them (Phase 9). AutoCloseable makes try-with-resources work (Topic 7.6).
An interface with exactly one abstract method is a functional interface, and you can implement it with a lambda instead of a class. That's Phase 10's whole story.
Try it yourself
- 1
Add a third payment method
Add
class Wallet implements PaymentMethodwith a fixed cashback message inpay(). Use it withCheckoutwithout changing Checkout at all. - 2
Drop the public
In the Duck example, remove
publicfromDuck.swim()and compile. Read the 'weaker access privileges' error and put it back. - 3
Sort the other way
Change Student's
compareToso it sorts by name alphabetically (return name.compareTo(other.name);). Predict[Asha(82), Ravi(95), Zoya(88)]and run.
Code & diagrams
Expected output
Shoes via Card: paid
Watch via Card: declined
Book via UPI: paidExpected output
Duck paddles
Fish swims
Duck flies up to 1000 m
Plane flies
Duck is a Swimmer: true
Duck is a Flyer: true
Flyer.MAX_ALTITUDE = 1000Collections.sort was written years before Student existed. The Comparable contract is what connects them. More in Topic 9.10.
Expected output
[Ravi(95), Zoya(88), Asha(82)]Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Implement an interface method without public
Implement greet() with package-private access.
interface Greeter { void greet(); }
class En implements Greeter { void greet() { } }Break #2
Instantiate an interface
Write new Greeter().
interface Greeter { void greet(); }
public class Main { public static void main(String[] a) { Greeter g = new Greeter(); } }Myth vs fact
Myth
Interfaces can't contain any code.
Fact
That was true before Java 8. Interfaces can now have default, static and (since Java 9) private methods with bodies. They still can't have instance fields or constructors.
Myth
Implementing an interface is a kind of inheritance of code.
Fact
Classically it's inheritance of *type*: you promise behaviour. Default methods do add inherited code, but never inherited state.
Myth
Fields declared in an interface are per-object.
Fact
They are public static final constants shared by everyone. Interfaces have no per-object state.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
invokeinterfacedispatch: since the same interface method can sit at a different vtable index in every implementing class, HotSpot searches the class's itable (a list of interface → method-table offsets). Inline caches make monomorphic interface calls as cheap as class calls; at megamorphic sites, itable stubs are a little more expensive than vtable stubs. - ▸
Adding a new abstract method to a published interface breaks every implementer: source fails to compile, and old binaries throw
AbstractMethodErrorwhen the new method is called. That's why Java 8 added default methods: soCollection.stream()andIterable.forEach()could be added without breaking every collection class in the world. - ▸
The Java Language Specification says an interface implicitly declares public abstract versions of
Object's public methods if it doesn't declare them. That's why you can calltoString()on an interface-typed variable, and whyComparatorcan declareboolean equals(Object)without breaking its functional-interface status (it doesn't count as an abstract method). - ▸
Interfaces are the backbone of dependency injection: Spring and similar frameworks wire
PaymentMethodimplementations intoCheckoutat start-up. See the System Design course's Dependency Injection topic (/topic/phase-2/dependency-injection).
Remember this
- 1
An interface declares methods that implementing classes must provide:
interface PaymentMethod { boolean pay(double amount); }. Methods without a body in an interface are implicitlypublic abstract, so you don't write those words. - 2
A class promises to fulfil the contract with
implements:class Card implements PaymentMethod. It must provide apublicbody for every abstract method, or be declared abstract. The compiler checks this. - 3
A class can implement many interfaces (
class Duck implements Swimmer, Flyer), even though it can extend only one class. Interfaces model *capabilities* that cut across unrelated classes: a Duck, a Submarine and a Fish can all beSwimmers. - 4
An interface is a type. You can declare variables, parameters and lists of it:
PaymentMethod m = new Card();,List<Swimmer>. Calls through it are dispatched to the real object (invokeinterface, Topic 5.4). Program to the interface:List<String> names = new ArrayList<>();lets you swap implementations later. - 5
Fields in an interface are implicitly
public static final: constants, not per-object state. Interfaces have no constructors and no instance fields. Since Java 8 they may also containdefaultandstaticmethods, and since Java 9privatemethods (Topic 5.8). - 6
Interfaces can extend other interfaces, even several:
interface ReadWrite extends Readable, Writable. Some interfaces declare no methods at all (marker interfaces such asSerializableandCloneable); they just tag a class for code that checks withinstanceof.
Explain it without notes
What is an interface, and what does a class promise when it implements one?
Why can a class implement many interfaces but extend only one class?
What does 'program to an interface' mean, and why is it useful?
What are the implicit modifiers of methods and fields in an interface?
Practice
Create an interface Shape with double area() and implement it in Circle and Square. Compute the largest area in a List<Shape>.
Create interfaces Readable (String read()) and Writable (void write(String s)) and a ReadWrite interface extending both. Implement it with a class that stores the last written string.
Make Product(String name, double price) implement Comparable<Product> by price ascending and sort a list.
Trade-offs
- ↔
Interfaces decouple callers from implementations, but every interface is another file and another indirection. An interface with exactly one implementation and no plans for more (and no test doubles) can be premature abstraction.
- ↔
Interfaces can't hold state, so shared fields and helper logic must live elsewhere: in default methods (no state), in an abstract helper class, or in a composed object.
Done when you can
Done when you can declare an interface and implement it in two unrelated classes.
Done when you can implement several interfaces in one class and use each as a type.
Done when you know interface methods are public abstract and fields are constants.
Done when you can implement
Comparableand sort your own objects.Done when you can explain 'program to an interface' with an example.