Interfaces earn their keep when you want to name a capability that unrelated types share. Comparable, AutoCloseable, Serializable, Runnable, and Iterator are all standard-library examples, and each one lets code accept anything that satisfies the contract without knowing the concrete type.
That is the practical test: if your method parameter only ever calls methods declared on the interface, type the parameter as the interface. It keeps callers decoupled and makes the method testable with a small hand-written implementation.
Prefer an abstract class when you have noticed the same fields or the same sequence of calls appearing in three or more subclasses. At that point the duplication is real, and an abstract class moves it somewhere the compiler enforces.
Do not add a default method merely because you can. Every default method is permanent API on the interface, and it must keep working for every present and future implementor, including ones written by other teams.
Frequently Asked Questions
What is the difference between an interface and an abstract class in Java?
An interface carries no per-object state and declares no constructor, so it can describe a capability but not an implementation. An abstract class holds fields, runs constructors, and can mix abstract and concrete methods. A class may implement any number of interfaces but extend only one class, which is why interfaces provide multiple inheritance of type without the diamond problem.
Can an interface have instance fields?
No. Every field in an interface is implicitly public static final, so it belongs to the interface rather than to any object and cannot vary per instance. Reflection confirms the modifiers are stored exactly that way. To hold per-object state you need a class, which is the main reason interfaces cannot replace abstract classes.
Why do interface methods not need the abstract keyword?
Because it is implied. An interface method declared with a body is a default method, and one with a static body is a static method, so anything left over is implicitly public abstract. Writing the keywords out is legal and does nothing.
How does Java resolve two default methods with the same name?
Three rules, in order: a method on the implementing class wins; failing that, the most specific interface wins, so a subinterface beats its parent; failing that, if two unrelated interfaces both declare it, the compiler reports an error saying the class inherits unrelated defaults. You then break the tie with an override or a qualified super call such as A.super.go().
Why do default methods exist?
To let an interface gain a method without breaking existing implementors. Adding an abstract method forces every implementation in the world to add the method or fail to compile. Adding a default method brings an implementation with it, so existing code keeps working and only the implementors that want different behaviour override it. This is how Iterable.forEach and Collection.removeIf were added to the JDK.
Can a default method be overridden?
Yes, and it is optional. A class may override a default method exactly as it would override any inherited method, using the same signature rules. When it does not, it simply inherits the interface implementation. Marking the method @Override documents the intent and catches a signature typo.
What is a functional interface?
An interface with exactly one abstract method. Default and static methods do not count towards that total, so a functional interface may contain several of them and still accept a lambda. Adding the @FunctionalInterface annotation is optional but makes the compiler enforce the rule, which is useful because a stray second abstract method is easy to add by accident.
Are interface static methods inherited by implementing classes?
No. They belong to the interface itself and must be called through the interface name, such as Payables.of(AMOUNT). Calling one through an instance or a reference typed as the interface is a compile error, which is what stops static interface methods from colliding with instance methods on the implementing type.
Can an interface extend multiple other interfaces?
Yes, using extends, and the child then inherits every contract from its parents. This is how you build a larger promise out of smaller ones without involving classes. Unlike classes, the reverse is not allowed: an interface cannot extend a class, and asking for it produces "interface expected here".
One detail catches people when chaining interfaces. If the two parents both supply the same default, the conflict appears on the child interface, before any class is involved:
interface P1 {
default void go() {
}
}interface P2 {
default void go() {
}
}interface P3 extends P1, P2 {
}// error: types P1 and P2 are incompatible;
// interface P3 inherits unrelated defaults for go() from types P1 and P2
P3 must therefore override go() itself, or declare a fresh default that settles the question for its own implementors.