Interface Implementation
A default method is a method with an implementation in an interface, marked with the default keyword, and classes that implement the interface can use it.
A Method the Class Never Wrote
This article starts with a program rather than a definition. It is built around an interface called Readable and a class called Stars that implements it. The main method calls a method named readLine on a Stars object. Yet the Stars class, as written, does not define readLine anywhere. Your task in this article is to explain where readLine comes from and why the program still works.
What do you think happens?
The Stars class contains only readChar and main. When main calls stars.readLine(), which code body does Java use? Choose before reading on.
Reveal answer
Java falls back to the body that the interface itself provides for readLine.
Because readLine is a default method in Readable, it has a body in the interface. Stars inherits that body, so the call to stars.readLine() is handled by the interface code. The class does not need its own copy, and the program compiles and runs. The sections below trace exactly how this happens.
Keep your answer in mind. The next sections confirm or correct it, and they show where each line of the call actually executes.
Tracing the Call from main to the Interface
Follow the path of one call. When main runs stars.readLine(), Java looks for a readLine method in the Stars class. It does not find one. It then uses the default body that Readable provides. That body creates an empty StringBuilder and calls readChar for the first character. Each call to readChar goes to the Stars version, because Stars is the object on which the call was made. The loop keeps appending characters until readChar returns a line feed character. At that point the method returns the accumulated text to main.
Notice the two-way movement in the diagram. The default body lives in Readable, but it keeps asking the Stars object for characters. The line that main prints is assembled in readLine, while each individual character is produced in readChar. Keep that split in mind, because it is the key to debugging later in this article.
Abstract and Default Methods Side by Side
A default method is a method with an implementation in an interface, marked with the default keyword, and classes that implement the interface can use it. An abstract method in an interface is a method with no body. It declares a required behavior but gives no code for it, so the implementing class must supply that code.
readCharhas no body, so it is abstract and every implementing class must write itreadLineis marked default and has a body, so the interface supplies it- The loop body inside
readLinecallsreadChar, which is whyreadLinedepends on the implementing class
The code above is a reconstruction that follows the behavior described in the source. The source confirms the syntax default public String readLine() followed by a body in braces, and it confirms that readChar is declared with no body. The loop details are an illustrative version of the behavior the source describes: it appends characters until a line feed is returned.
| Feature | Abstract method | Default method |
|---|---|---|
| Has a body in the interface | No | Yes, marked with default |
| Must the implementing class write it | Yes | No, it may inherit the body |
| Example in the Readable interface | readChar | readLine |
| Role in this design | Supplies the raw values | Builds a result from those values |
Abstract and default methods inside the same interface
What Stars Must Write and What It Inherits
The compile-time rule is simple. A class implementing an interface must provide an implementation for every abstract method in that interface. It does not have to write the default methods, because the interface already supplies their bodies. In the Readable example, readChar is abstract, so Stars must write it. Stars does that with a body that returns the star character most of the time and a line feed character otherwise. readLine is default, so Stars may leave it alone.
****- Stars implements Readable, so it inherits
readLinefrom the interface readCharis the only method Stars writes, because it is the only abstract method- The output shown belongs to this illustrative version, which returns a line feed on every fifth call
Common mistake Assuming a class must write every method named in the interface
What it looks likeStars does not write readLine, yet the program compiles and runs.
Why it failsDefault methods already carry a body in the interface, so the implementing class does not need to supply one.
Do this insteadWrite the abstract methods, such as readChar, and treat default methods as inherited behavior that you may override.
Common mistake Expecting a compile error when a default method is left out
Why it failsOnly abstract methods must be implemented. A missing default method is filled in by the interface.
Do this insteadWhen you see a compile error, look for a missing abstract method in the implementing class.
Common mistake Believing that readLine runs once per character instead of once per call to readLine
Finding Which Body Runs at Call Time
When a call is made, Java decides which body to run by checking the implementing class first. If the class defines the method, its body is used. If the class does not define it, the default body from the interface is used. In the Stars program, Stars does not define readLine, so the default body runs. The decision diagram below shows that choice as a series of checks.
The decision is made by what the implementing class defines, not by what the interface declares. Because Stars does not define readLine, the call falls through to the interface body. If you later add a readLine method to Stars, that method would be the one selected instead.
Debugging by Locating the Producing Method
Suppose a printed line looks wrong. The source gives a clear debugging rule: separate the default method that assembles a result from the abstract method that produces the raw values, and check which method produced the first wrong value. The line that main prints is built inside readLine, but each character is produced by readChar.
A line prints with a missing character in the middle. Start with the characters. If readChar returns the wrong character on one call, the fault is in the character-producing code in Stars. If readChar returns the right characters but the printed line is still wrong, the fault is in the assembly loop inside the default readLine body. Find the first wrong value, then check which method produced it.
A class Dots implements Readable and writes only readChar. It returns a period for every call and a line feed on the third call. What does Dots.main print when it calls readLine, and which method produced the first character of that output?
Hints
- Dots does not define
readLine, so which body does Java use? - Trace the loop in readLine: how many characters are appended before the line feed is returned?
- The first character comes from
readChar, which Dots writes itself.
Key Takeaways
- A default method has a body in an interface, is marked with the default keyword, and can be used by any class that implements the interface.
- An abstract method has no body, and every class implementing the interface must write it, or the program will not compile.
- A call to a method the class does not define is handled by the default body in the interface, which is why Stars can call
readLinewithout writing it. - When debugging, find the method that produced the first wrong value: the default method assembles the result, while the abstract method produces the raw values.