default methods
In the previous lesson, a class that implements an interface wrote each of its methods itself. Because of this rule, an interface is hard to change.
Back to the job ad. Say the employer adds a new duty to it: report after each delivery. All the couriers who already took the job break the deal at once, because they cannot do this. Java works the same way: add a new method without a body to Courier, and every class that implements Courier stops compiling.
The employer acts smarter and attaches a ready instruction to the new duty: if you have no way of your own, write "Delivered" in the chat. Those who can report in their own way do so, and the rest follow the instruction. In Java, such an instruction is a default method. To watch only the report, let's leave one method in Courier, report:
public class Main {
public static void main(String[] args) {
Courier c = new Cyclist();
c.report(); // Delivered
}
}
interface Courier {
default void report() {
System.out.println("Delivered");
}
}
class Cyclist implements Courier {}Let's go through the program step by step:
- In the
Courierinterface, thereportmethod is written with a body, and the worddefaultstands before it. - The
Cyclistclass implementsCourierbut has noreportof its own, and the compiler does not object. c.report()runs the body from the interface and printsDelivered.
A method with a body in an interface
A default method is an interface method with a body and the word default before it. Such methods appeared in Java 8.
What matters about default methods:
- a class gets a
defaultmethod ready-made and does not have to write it; - a
defaultmethod, like a method without a body, ispublic; - a class can write its own version: then it overrides the
defaultmethod, like a parent's method in the previous theme.
Interviewers often ask why default methods appeared. The answer: to add new methods to an interface without breaking the classes that already implement it.
Which method runs
There is one rule. On a call, Java first looks for the method in the object's class, then in its parents. Only if none of them has written its own method does the interface's default method run. A courier who has a way of their own to report does not read the instruction.
The widget has two couriers: Cyclist has no report of its own, and Drone has one. Press "Next step" and watch whose frame lands on top at each call.
1public class Main {2 public static void main(String[] args) {3 Courier a = new Cyclist();4 Courier b = new Drone();5 a.report();6 b.report();7 }8}9 10interface Courier {11 default void report() {12 System.out.println("Delivered");13 }14}15 16class Cyclist implements Courier {}17 18class Drone implements Courier {19 @Override20 public void report() {21 System.out.println("Drone landed");22 }23}
a refers to a Cyclist object, and the Cyclist class has no report of its own.
Both calls are written the same way, through a variable of type Courier. The object decided which report to run: for Cyclist only the instruction from the interface was found, and Drone reported in its own way. This is the same polymorphism as with the universal remote.
Here the instruction picture is not exact. On a paper instruction, a courier can tick off how many reports they have already sent. A default method has no such paper: an interface keeps no data of an object. The next section is about that.
Abstract class or interface
Now both an interface and an abstract class can have methods with a body. So how do they differ? It is one of the most common questions at a Java interview.
| Abstract class | Interface | |
|---|---|---|
| Object fields | yes, each object has its own values | no, an interface's fields are shared constants |
| Constructor | yes | no |
| How many a class can take | one parent through extends | any number through implements |
Behind the table there is a different meaning:
- an abstract class answers the question "what is it?": a cyclist and a van driver are employees, and each has a name and a number of deliveries;
- an interface answers the question "what can it do?": both an employee and a drone can deliver.
Hence the rule of choice. If related classes need common fields and a constructor, take an abstract class. If quite different classes will get the ability, take an interface. A class can combine both: class Van extends Vehicle implements Courier.
Common mistake
Someone tried to keep the number of reports in an interface field:
interface Courier {
int reports = 0;
default void report() {
reports++; // ✗
System.out.println("Delivered");
}
}error: cannot assign a value to static final variable reportsThe program does not compile. A field in an interface is a constant: the compiler added the words static and final itself, and the message names both. An interface cannot keep an object's data, such as the number of its reports. Such a field is declared in a class, and if several related classes need it, in their common abstract parent.
Key points
- A
defaultmethod is an interface method with a body: a class gets it ready-made and can override it. - On a call, Java first looks for the method in the object's class and its parents, and the
defaultmethod runs only if none of them has its own. - An abstract class has object fields and a constructor, while an interface's fields are shared constants; but a class can implement any number of interfaces.
- An abstract class describes what an object is, and an interface describes what it can do.