Java Interfaces
Table of Contents + −
In the last lesson you learned about Java abstraction. An abstract class can carry shared code, but sometimes you want something purer: just a list of abilities a class promises to have, with no shared code at all. That pure contract is an interface.
🤔 Why do we need interfaces?
A car, a drone, and a boat can all “move”, but share almost nothing else. They are not one family. So a common parent class feels wrong. An interface fixes this:
- It defines the ability once, like Movable.
- Any class from any family can promise to provide it.
- One method can then work on all of them, instead of one per type.
- You can add new movable types later without touching old code.
Think of a power socket. A lamp, a laptop charger, a phone charger all just plug in, as long as the plug fits the shape. The socket is the contract. An interface is about what a class can do, not what it is.
🧩 What is an interface?
An interface is a contract. It lists methods a class must provide. Here is a small interface for being an animal.
interface Animal { void makeSound(); // no body: just the promise void eat();}Any class that is an Animal must have makeSound() and eat(). It does not say how. The quiet rules Java applies:
- Each line ends in a semicolon, not
{ }. That marks a method with no body. - Interface methods are
publicandabstractby default. Sovoid makeSound();really meanspublic abstract void makeSound();. abstractmeans “no body, must be filled in later”.- So any class that implements them must mark them
publictoo.
An interface is like a checklist on a wall. It does not do the work. It says what work anyone who signs up must do.
🤝 Implementing an interface
A class uses the implements keyword to sign the contract, then provides a body for every method. Here is a Dog that signs the Animal contract.
class Dog implements Animal { @Override public void makeSound() { System.out.println("Woof"); }
@Override public void eat() { System.out.println("Dog is eating"); }}Dog implements Animal, so it must define both methods. Leave one out and it will not compile. The @Override line is optional, but worth keeping:
- It makes Java check the method really exists in the interface.
- So a misspelled name like
makeSoundsis caught right away. - It tells the next reader where the method came from.
Now we can use a Dog through the Animal type. Here we make a Dog but hold it in an Animal reference, then call its methods.
public class Main { public static void main(String[] args) { Animal a = new Dog(); // interface type, Dog object a.makeSound(); a.eat(); }}Output
WoofDog is eatingThe variable a has the type Animal, but the object inside is a Dog. We talk to the contract, and the real Dog does the work:
- The interface is the steering wheel. The Dog is the engine.
- Through
ayou can only call methods theAnimalinterface knows about. - If
Doghad afetch()not in the contract,a.fetch()would not compile.
Interface methods are public
Methods you implement from an interface must be public. The interface is a public promise, so the class must keep it publicly. That is why the methods above are marked public. If you forget public, the compiler rejects the class with an error about trying to make a method less visible.
🧰 Implementing multiple interfaces
A class can extend only one parent class, but it can implement many interfaces. Why this is safe:
- Java bans two parent classes to avoid confusion over which parent’s code wins.
- A traditional interface carries no instance code, so two of them cannot clash.
- So interfaces give you multiple inheritance of type without the danger.
Here are two small ability interfaces.
interface Swimmer { void swim();}
interface Flyer { void fly();}Now here is a Duck that has both abilities at once.
class Duck implements Swimmer, Flyer { // both abilities @Override public void swim() { System.out.println("Duck is swimming"); }
@Override public void fly() { System.out.println("Duck is flying"); }}A Duck implements both interfaces, separated by a comma:
- You list as many interfaces as you like after
implements, comma separated. - The class must satisfy every method from every interface in that list.
- Now the Duck can be used as a
Swimmerin one place and aFlyerin another.
You can mix a parent class in too: class Duck extends Bird implements Swimmer, Flyer. The parent gives the “is a” family. The interfaces add abilities.
🔢 Interface fields are constants
Every field in an interface is automatically public static final, even if you do not type those words:
public: anyone can read it.static: it belongs to the interface itself, not to any one object.final: it is set once and can never change.- So an interface field is a constant, shared by everyone.
Here is one.
interface Payment { double TAX_RATE = 0.18; // really public static final
double amount();}TAX_RATE is a fixed value any class reads as Payment.TAX_RATE. Try to change it and the compiler stops you. Use this for things that never change, never for data that varies per object.
🧩 Default methods
Modern Java lets an interface provide a body for a method using the default keyword. Why this was added:
- Imagine thousands of programs already implement your
Animalinterface. - Add a new method
sleep(), and in the old days every one of those classes would stop compiling. - A default method gives the new method a body, so existing classes keep working untouched.
Here is an interface that ships a default body for sleep().
interface Animal { void makeSound();
default void sleep() { // a provided default body System.out.println("Sleeping..."); }}A class implementing Animal must still define makeSound, but gets sleep for free. Your choices with a default method:
- Use
sleepas-is, writing nothing. - Override
sleepto give it different behaviour. - Either way, old code that never knew about
sleepstill compiles.
Default methods are the main exception to “interfaces have no bodies”. Do not overuse them. An interface is still meant to be mostly a contract.
⚙️ Static methods in interfaces
A static method belongs to the interface itself, not to any object. You call it on the interface name. It is handy for small helpers that do not need an object.
interface MathTool { int apply(int x);
static int square(int n) { // belongs to the interface return n * n; }}You call it directly on the interface, like this.
public class Main { public static void main(String[] args) { int result = MathTool.square(5); // no object needed System.out.println(result); }}Output
25The difference from a default method:
- A default method runs on an implementing object.
- A static method runs on the interface name.
- So you call
MathTool.square(...), neveraMathTool.square(...).
🎯 A worked example: programming to an interface
Now a real pattern you will use a lot. First, the contract. Anything Payable can tell us how much it costs.
interface Payable { double getAmount();}Now two unrelated classes sign that contract. An Invoice and an Employee have nothing in common, but both can produce an amount to pay.
class Invoice implements Payable { private double total;
public Invoice(double total) { this.total = total; }
@Override public double getAmount() { return total; }}
class Employee implements Payable { private double salary;
public Employee(double salary) { this.salary = salary; }
@Override public double getAmount() { return salary; }}Here is the payoff. One method pays anything Payable. It does not care whether it got an Invoice or an Employee.
public class Main { static void pay(Payable item) { // accepts any Payable System.out.println("Paying: " + item.getAmount()); }
public static void main(String[] args) { Payable a = new Invoice(500.0); // interface ref, Invoice object Payable b = new Employee(3000.0); // interface ref, Employee object
pay(a); pay(b); }}Output
Paying: 500.0Paying: 3000.0The variables a and b are typed as Payable, not Invoice or Employee. We are programming to an interface: we depend on the contract, not the exact class. Why that wins:
- Add a
Subscriptionclass that implementsPayable, andpayworks with zero changes. - You can hold a
List<Payable>mixing invoices, employees, and subscriptions, then pay them in one loop. - The
paymethod is tiny and stable. New types arrive, and it never changes.
You see this all over Java. In List<String> names = new ArrayList<>(); the left side is the List interface, the right side is the ArrayList class. Switch to LinkedList and only that one line changes. Depend on what something can do, not on what it is.
⚖️ Interface vs abstract class
Both define methods children must implement, so when do you use which? We compare them fully in the abstract classes lesson. The short version:
- Use an interface for a pure ability or contract, especially when unrelated classes need it, or a class needs several abilities. A class can implement many interfaces.
- Use an abstract class when you have a shared base with common code and fields, and the children form one family. A class can extend only one.
A rough rule for the ability versus identity question:
- An interface says what a class can do. An abstract class says what a class is.
Birdfits an abstract class. Sparrows and eagles share real code.Flyerfits an interface. A bird, a plane, and a drone can all fly without being one family.- When in doubt and you only need a contract, prefer an interface.
⚠️ Common Mistakes
A few interface slip-ups to watch for:
Forgetting to implement a method. A class must define every method, unless it is default. Miss one and the class will not compile.
// ❌ Wrong: Dog promised Animal but skipped eat()class Dog implements Animal { public void makeSound() { System.out.println("Woof"); } // eat() is missing, so this does not compile}
// ✅ Right: every contract method is providedclass Dog implements Animal { public void makeSound() { System.out.println("Woof"); } public void eat() { System.out.println("Dog is eating"); }}Expecting instance fields in an interface. Interface fields are public static final constants, not per-object data. You cannot store changing state in an interface.
// ❌ Wrong: this is NOT a normal field; it is a constant you cannot reassigninterface Counter { int count = 0; // really public static final, cannot change later}
// ✅ Right: keep changing state in the implementing classclass Tally implements Counter { private int count = 0; // real instance field lives here}Confusing implements and extends. A class implements an interface but extends a class. Mixing them up is a common typo, and the error message can be confusing.
// ❌ Wrong: you cannot extend an interface from a classclass Dog extends Animal { } // Animal is an interface
// ✅ Right: implement the interfaceclass Dog implements Animal { public void makeSound() { System.out.println("Woof"); } public void eat() { System.out.println("Dog is eating"); }}Forgetting public on the methods. The interface methods are public, so your class must keep them public. A common slip is to leave the keyword off, which makes the method package-private by default and breaks the promise.
// ❌ Wrong: no public, so it is less visible than the contract requiresclass Dog implements Animal { void makeSound() { System.out.println("Woof"); } // missing public public void eat() { System.out.println("Dog is eating"); }}
// ✅ Right: every implemented method is publicclass Dog implements Animal { public void makeSound() { System.out.println("Woof"); } public void eat() { System.out.println("Dog is eating"); }}Trying to create an object of an interface. You cannot do new Animal(). An interface has no bodies to run. Create objects of the classes that implement it, then hold them in an interface variable, like Animal a = new Dog();.
✅ Best Practices
Habits for using interfaces well:
- Use interfaces for abilities. Names like
Movable,Comparable,Printabledescribe what a class can do. - Program to the interface. Type your variables as the interface (
List,Payable) and let the exact class sit on the right ofnew. - Prefer interfaces when classes are unrelated. A Car and a Boat can share
Movablewithout a forced family. - Implement several when needed. Mix abilities like
Swimmer, Flyer. That is the safe kind of multiple inheritance. - Keep interfaces small and focused. A short interface is easy to implement. A huge one burdens every class that signs it.
- Use default methods with care. Great for growing an interface safely, but not a place for piles of logic.
- Add
@Overrideon implemented methods. It catches misspelled methods and tells the reader where the method came from.
🧩 What You’ve Learned
Nicely done. Let’s recap interfaces.
- ✅ An interface is a pure contract: a list of method signatures a class promises to provide.
- ✅ Interface methods are
publicandabstractby default, and fields arepublic static finalconstants. - ✅ A class uses
implementsand must define every method, unless it isdefault. - ✅ A class can implement many interfaces, even though it can extend only one parent class. That is Java’s multiple inheritance of type.
- ✅ Default methods add a body so interfaces can grow without breaking old classes; static methods live on the interface itself.
- ✅ Program to an interface (
List ref = new ArrayList) so your code depends on the contract, not the exact class. - ✅ Use an interface for an ability or contract; use an abstract class for a shared family base.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What is an interface in Java?
Why: An interface is a contract of methods that implementing classes must provide.
- 2
What keyword does a class use to adopt an interface?
Why: A class uses implements to sign an interface's contract.
- 3
How many interfaces can one class implement?
Why: A class can implement many interfaces, unlike extending classes where only one parent is allowed.
- 4
When should you prefer an interface over an abstract class?
Why: Interfaces suit pure contracts and let unrelated classes share abilities, with multiple interfaces allowed.
🚀 What’s Next?
We have met abstract classes and interfaces separately. To finish the OOP concepts module, let’s compare abstract classes head to head, looking closely at when each one is the right tool. Let’s wrap up with abstract classes.