Interfaces
Contracts, multiple implementation, default, static and private methods, and interface vs abstract class.
An interface is a contract: a named set of methods that a class promises to provide. It says what an object can do, not how, and it is not tied to any class hierarchy. A Phone, a Drone and a Car have nothing in common as classes, but all of them can be Chargeable.
Interfaces are probably the most important tool for flexible Java design. Almost every major API (List, Comparable, Runnable, JDBC's Connection, Spring's repositories) is built on them.
Declaring and implementing an interface#
Points to notice:
- Interface methods without a body are implicitly
public abstract, so the implementing methods must bepublic. Writing justvoid charge(int minutes)inPhonegives "attempting to assign weaker access privileges". - Interface fields are implicitly
public static final: they are constants, never per-object state. - You can't write
new Chargeable(), but you can useChargeableas a variable, parameter, array or return type. That is where the power is.
Implementing several interfaces#
A class can extend only one class, but it can implement any number of interfaces. That lets one object play several roles:
Interfaces can also extend other interfaces, even several at once: interface Amphibious extends Flyer, Swimmer { }.
Program to the interface#
The biggest benefit of interfaces is that calling code depends only on the contract, so implementations become swappable:
OrderService doesn't know or care how messages travel. In tests you can pass a fake sender that just records messages. This idea, handing an object the dependencies it needs from outside, is called dependency injection, and it is the heart of Spring.
You already use this habit with collections: List<String> names = new ArrayList<>(); declares the variable as the interface List, so you could switch to another implementation later without changing the rest of the code.
Default, static and private methods#
Since Java 8, interfaces can contain method bodies in three forms:
defaultmethods: inherited by implementing classes, which may override them. They let library authors add methods to an interface without breaking every existing implementation.staticmethods: helpers called on the interface name, likeList.of(...)orComparator.naturalOrder(). They are not inherited by implementing classes.privatemethods (Java 9+): helpers shared by the default methods, hidden from everyone else.
The diamond: two defaults with the same name
If a class inherits the same default method from two interfaces, Java refuses to guess. The class must override it, and can pick one parent's version with Interface.super.method():
A related rule: classes win. If a superclass already has a method with the same signature as an interface default, the class's version is used.
Functional interfaces (a preview)#
An interface with exactly one abstract method is a functional interface. Instead of writing a whole class, you can implement it with a lambda:
Runnable, Comparator and everything in java.util.function are functional interfaces. The Lambdas lesson goes deep on this.
Marker interfaces and well-known JDK interfaces#
Some interfaces have no methods at all and just "tag" a class, like java.io.Serializable. More often you will implement interfaces the JDK already understands:
Interface vs abstract class#
Rule of thumb: start with an interface. Reach for an abstract class when implementations genuinely share state or a lot of code. Many designs use both: an interface for the contract and an abstract class that partially implements it (List and AbstractList).
Common mistakes#
- Forgetting
publicon the implementing method (weaker access is not allowed). - Trying to store per-object state in an interface field; it's a shared constant.
- Writing
implementsbeforeextends: the order isclass A extends B implements C, D. - Using
interface X implements Y; interfacesextendsother interfaces. - Calling a static interface method through an implementing class or instance (
PercentOff.none()doesn't compile); call it on the interface:PriceRule.none().
What's next#
So far, every data-holding class needed a constructor, getters, toString, equals and hashCode written by hand. Records generate all of that from a single line.
Check your understanding
Quick quiz
1.Which declaration is legal in Java?
2.A field declared in an interface as
int MAX = 10;is implicitly...3.A class implements two interfaces that both provide a
default String hello()method. What must it do?
Finished reading?
Mark this lesson complete to track your progress.