Method Declarations and Signatures
A Java interface is a reserved word that introduces a set of instance method declarations with no implementations.
The Drawing Program Problem
Imagine a drawing program where many different shapes need to be painted onto a screen. The drawing code wants to say, simply, stroke this shape with a pen. It does not care whether the shape is a circle, a polygon, or a piece of text. What it needs is a guarantee that every shape it receives knows how to be stroked.
Java gives you a construct for writing down that guarantee without writing any of the drawing logic itself. That construct is called an interface. This article answers two questions: what does an interface actually contain, and what rules govern the things placed inside it? Keep one idea in mind as you read: the interface describes a promise, and a class is the thing that keeps it.
What an Interface Contains
A Java interface is a reserved word that introduces a set of instance method declarations with no implementations. In Java, interface is reserved, so you cannot use it as an ordinary name. A declaration gives a method's name, its parameters, and its return type. An implementation supplies the body that actually does the work. An interface gives only the declarations.
Read the example from the outside in. The keyword interface opens the definition, and Strokeable is the name chosen for it. Inside the braces sits a single declaration, stroke, which accepts one Graphics parameter. The declaration ends with a semicolon. There is no body in curly braces, because the interface does not provide one. The body belongs to whichever class eventually implements Strokeable.
- interface opens the definition and Strokeable is its name
- void
stroke(Graphics g); is a method declaration with no body - the semicolon marks the end of the declaration
The example above is an illustrative reconstruction of the Strokeable example described in the source. The source specifies the interface name, the single stroke declaration, its Graphics parameter, and the semicolon. The return type is shown here as void for completeness, because Java method declarations always include one.
An interface is best seen as a container. The interface sits at the top. Inside it you may find method declarations, which describe behavior that implementing classes must supply, and variable declarations, which describe fixed values that implementing classes receive. The method branch carries an obligation: every class that implements the interface must provide a body for stroke. The variable branch carries a gift: every implementing class can use a declared constant without declaring it again. Keeping these two effects separate is the key to reading interfaces correctly.
Declaration Versus Implementation
A method declaration and a method implementation share the same first line, the part naming the method, its parameters, and its return type. They differ in what follows. The interface stops at the semicolon. A class that implements the interface writes the body in curly braces and does the actual work there. The diagram below places the two side by side so you can see what each one contains.
Because the two forms share a header, a class can be checked against the interface by comparing headers. The interface supplies the header, and the class must supply a body that goes with a matching header.
Anatomy of a Method Signature
The method declaration inside an interface has several parts. Its return type, its name, and its parameter list together form the declaration that an implementing class must match. Modifiers come before the return type. For interface methods, the modifiers public and abstract are in effect even when they are not written, as the next section explains. The strip below annotates each token of the stroke declaration.
Required, Optional, and Implied Modifiers
A modifier is a keyword such as public, abstract, static, or final. For interfaces, the source states fixed rules for which modifiers apply. Some are fixed by the language's rules, and writing them is optional because they are already implied. The distinction matters, because readers often assume that a missing keyword means something different. In an interface, the presence or absence of these keywords changes how the text reads, not what the interface requires.
The table below summarizes which modifiers are implied for each kind of member. The rule applies to what the compiler will treat the member as, so each row shows the status of a modifier in an interface.
| Member | Modifier or feature | Status in an interface |
|---|---|---|
| Method | public | Implied; may be omitted |
| Method | abstract | Implied; may be omitted |
| Method | method body in curly braces | Not provided; the interface supplies only the declaration |
| Variable | public | Implied; may be omitted |
| Variable | static | Implied; may be omitted |
| Variable | final | Implied; may be omitted |
Modifiers for members declared inside a Java interface
Tracing Where a Class Breaks the Promise
What do you think happens?
Suppose a class declares that it implements Strokeable, but the class leaves out any code for the stroke method. What does the class break?
Reveal answer
The class breaks the interface's promise. Every class that implements the interface must provide a body for stroke, so the missing body means the class has not kept its agreement.
The interface specifies the method, and the class has agreed to supply it. Leaving it out means the class does not satisfy the contract it claimed.
When a program that uses interfaces fails, the most useful question is where the result first departed from what the interface promised. Start from the interface declaration and walk forward. Ask whether each declared method has a matching implementation in the class, and whether each constant is being used rather than redefined. The place where that comparison first fails is usually the place to look. The flowchart below traces that walk for a class that claims to implement Strokeable.
A Class That Omits stroke
A class named Circle declares that it implements Strokeable, but it contains no stroke method at all. Find where the program first departs from the interface's promise.
- 1Read the interface
Strokeable declares one method, stroke, which takes a Graphics parameter. This is the promise.
- 2Read the class claim
Circle declares that it implements Strokeable, so it has agreed to provide a body for each method the interface specifies.
- 3Compare method by method
The interface's stroke method has no matching implementation in Circle. The first comparison fails here.
- 4Locate the divergence
The divergence is at the missing stroke implementation. Any later error that involves drawing a Circle as a Strokeable is a consequence of this early mismatch, not its cause.
The program first departs from the interface promise at the missing stroke implementation in Circle. Fixing that method is the correction that restores the contract.
Mistakes Learners Make With Interfaces
Common mistake Writing a body for an interface method
What it looks likevoid stroke(Graphics g) { } inside an interfaceWhy it failsThe interface declares only method declarations with no implementations. The body belongs to the implementing class.
Do this insteadWrite the declaration with a semicolon, such as void stroke(Graphics g);, and put the body in the class that implements the interface.
Common mistake Assuming a missing public or abstract means the method is something else
What it looks likeSeeing void stroke(Graphics g); and concluding it is a concrete method
Why it failsMethods in an interface must be public and abstract, so those modifiers are implied even when omitted.
Do this insteadRead the omitted modifiers as present when you interpret the interface.
Common mistake Claiming to implement an interface without providing every method
What it looks likeclass Circle implements Strokeable with no stroke method
Why it failsEvery class that implements the interface must provide an implementation for each method the interface specifies.
Do this insteadAdd a stroke method whose header matches the interface declaration and whose body does the work.
Common mistake Redefining a constant that the interface already provides
Why it failsVariables in an interface are public static final fixed values shared by every implementing class.
Do this insteadUse the constant, such as INCHES_PER_FOOT, rather than declaring a new one for the same purpose.
Practice Tracing a Broken Implementation
An interface named Labelable declares one method, String label(), that returns a String and has no parameters. A class Box declares that it implements Labelable and provides a method void label(String text) with a body. Work through the walk from the interface to the class. At which step does the comparison first fail, and why?
Hints
- Compare the header of the interface method with the header of the class method, including the return type and parameter list.
- A method with the same name but a different return type or parameter list does not satisfy the declaration.
- The first failing comparison is the divergence point.
Rewrite the declaration String label(); inside an interface so that it shows the implied modifiers explicitly, and state which keywords you added and why they do not change the meaning.
Hints
- Methods in an interface must be public and abstract.
- The explicit form and the implicit form mean the same thing to the compiler.
Key Takeaways
- A Java interface is a reserved word that introduces a set of instance method declarations with no implementations, and a class that implements it must supply a body for each declared method.
- Methods in an interface are public and abstract, and variables in an interface are public static final, so those modifiers may be omitted without changing their meaning.
- A method declaration gives the name, parameters, and return type, while an implementation adds a body; the interface supplies only the declarations.
- When a class claims to implement an interface, trace the comparison method by method and locate the first failing check, since later symptoms often follow from that early mismatch.