Skip to main content

Abstract Class vs Interface in Java: Every Difference, Updated for Java 8 to 25

Abstract class vs interface in Java in a 12-row comparison table, with default, static and private interface methods, sealed interfaces, the diamond problem with the real compiler error, when to choose which, and the standard interview answer. Verified on JDK 25.

An abstract class is a partly built class: it can hold fields, constructors and finished methods, plus abstract methods that subclasses must fill in, and a class can extend only one. An interface is a contract of what a type can do: it has no instance state, can carry default, static and private methods since Java 8 and 9, and a class can implement as many as it likes. Choose an abstract class to share state and constructor logic inside one family; choose an interface to describe a capability that unrelated classes can have.
ABSTRACT CLASSstate + constructors + some codeextends exactly ONE“is a kind of” a familyINTERFACEcontract (+ default/static/private code)implements MANY, no instance state“can do” a capabilityRule of thumb: interface by default; abstract class when subclasses must share fields or constructor logic.
The two boxes are the decision in one picture. The 12-row table, the Java 8 to 25 changes, a real diamond-problem compiler error, sealed interfaces and the standard interview answer follow, with every program run on JDK 25.
Versions. Every program on this page was compiled and run on JDK 25.0.4.1 (Temurin, LTS, build 25.0.4.1+1-LTS). Where Java 8 behaved differently the text says so. The compiler errors and console output are quoted verbatim from those runs; the “Download” links at the end of each section point to the exact .java files.

Abstract class vs interface: every difference in 12 rows

#FeatureAbstract classInterface
1Keywordabstract classinterface
2Can you create an object with new?No (only via a concrete subclass or anonymous subclass)No (only via an implementing class, anonymous class or lambda)
3Instance fields (state)Yes, any access levelNo. Fields are implicitly public static final constants
4ConstructorsYes; run when a subclass is createdNo
5Methods with a bodyYes, any kinddefault, static (Java 8) and private (Java 9)
6Abstract methodsYes, must be marked abstractYes, implicitly public abstract
7Member access levelspublic, protected, package, privateAbstract/default/static are public; private helpers allowed
8How many can a class use?extends exactly oneimplements any number
9Lambda targetNoYes, if it has exactly one abstract method (a functional interface)
10Adding a method laterSafe if it has a bodySafe only as a default method; an abstract one breaks implementers
11Sealing (sealed, Java 17)YesYes
12Typical meaningIS-A: a family sharing state and logicCAN-DO: a capability or role
Rows 3, 4 and 8 decide most real choices: if subclasses need a shared field or constructor, it must be an abstract class; if a type must plug into several hierarchies, it must be an interface. The next sections prove the rows that people most often get wrong, with real programs.

Abstract class: shared state and a template method

An abstract class is the right tool when every subclass shares fields and a fixed algorithm with one or two variable steps. This is the template method pattern:
abstract class Report {
    protected final String title;
    Report(String title) { this.title = title; System.out.println("Report constructor ran for " + title); }
    abstract String body();
    final String render() { return "== " + title + " ==\n" + body(); }
}
class CsvReport extends Report {
    CsvReport(String t) { super(t); }
    String body() { return "a,b,c"; }
}
Source: AbstractVsInterface.java. Report owns the title field and a constructor, declares body() abstract, and makes render() final so no subclass can change the overall shape. CsvReport supplies only the variable part.
$ java AbstractVsInterface.java
-- abstract class: state, constructor, template method --
Report constructor ran for sales
== sales ==
a,b,c
The first line proves row 4: the abstract class constructor ran when the subclass was created, so the abstract class really is part of the object. Compare that with an interface, which has no constructor to run. For how super(...) chaining works, see Constructors in Java.

Interface: default, static and private methods (Java 8 and 9)

Before Java 8 an interface could hold only abstract methods, so adding one broke every implementer. Java 8 added default methods (a body that implementers inherit) and static methods, and Java 9 added private methods so defaults can share code without exposing it:
interface Greeter {
    String name();
    default String greet() { return decorate("Hi " + name()); }
    static String shout(String s) { return s.toUpperCase() + "!"; }
    private String decorate(String s) { return "[" + s + "]"; }
}
Source: AbstractVsInterface.java. Only name() is abstract, so Greeter is a functional interface; the anonymous class below needs to supply just that.
$ java AbstractVsInterface.java
-- interface: default, static, private methods --
[Hi Ankur]
HELLO!
[Hi Ankur] came from the default method calling the private helper. HELLO! came from the static method called on the interface name, not on an object. The reason Java added defaults at all was to evolve the standard library (collections gained forEach and stream) without breaking every class that already implemented them. Interfaces still cannot hold instance state. A field in an interface is a constant, and trying to treat it as a variable is a compile error:
$ javac BrokenInterfaceState.java
BrokenInterfaceState.java:3: error: cannot assign a value to static final variable count
    default void inc() { count++; }
                         ^
1 error
Source: BrokenInterfaceState.java. This is row 3 in action: int count = 0; in an interface means public static final int count = 0;.

The diamond problem and how Java resolves it

Multiple inheritance of state is what Java forbids for classes. Multiple inheritance of behaviour is allowed through interface defaults, which reintroduces the “diamond”: two interfaces provide the same default method, and a class implements both.
interface Adefault hello()interface Bdefault hello()class Bothmust override hello()Two unrelated defaults: javac refuses until the class chooses (or combines) them.
The class at the bottom has two equally valid inherited versions, so the compiler will not guess. First the failure, then the fix:
$ javac BrokenDiamond.java
BrokenDiamond.java:3: error: types A and B are incompatible;
class Both implements A, B { }
^
  class Both inherits unrelated defaults for hello() from types A and B
1 error
Source: BrokenDiamond.java. The fix is to override and say which one you mean, with Interface.super.method():
interface A { default String hello() { return "A"; } }
interface B { default String hello() { return "B"; } }
class Both implements A, B {
    @Override public String hello() { return A.super.hello() + "+" + B.super.hello(); }
}
$ java AbstractVsInterface.java
-- diamond: class must pick one --
A+B
A+B shows the class called both inherited versions explicitly. If one of the two interfaces were a class method instead, the class version would win without error; the explicit message is only for two defaults that tie.

Sealed interfaces (Java 17 and later)

A sealed interface lists exactly which types may implement it. That makes it a closed set, which lets the compiler check a switch for completeness without a default branch:
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}
Source: AbstractVsInterface.java, where area is a switch over Shape with a case for each permitted record and no default.
$ java AbstractVsInterface.java
-- sealed interface + switch --
Circle area = 3.14
Square area = 4.00
If you later add a third permitted type, every such switch stops compiling until it handles it, which is the point: the compiler finds the places you forgot. sealed works on abstract classes too (row 11); the interface form is the common choice for closed families of records.

One class, many interfaces, one parent class

interface Flyer {}
interface Swimmer {}
class Animal {}
class Duck extends Animal implements Flyer, Swimmer {}
$ java AbstractVsInterface.java
-- one class, many interfaces; one parent class only --
[interface Flyer, interface Swimmer]
Duck superclass = Animal
Duck extends one class and implements two interfaces, which is the entire inheritance model in one line. It is also why interfaces describe abilities (Flyer, Swimmer) while the single superclass describes what the thing is.

When to choose which

SituationPick
Subclasses need to share fields or constructor logicAbstract class
You want a fixed algorithm with variable steps (template method)Abstract class
Unrelated classes must share a capability (Comparable, Runnable, Closeable)Interface
A class already extends another class and needs one more roleInterface (only option)
You want lambdas to implement itInterface with one abstract method
You want a closed family the compiler can checksealed interface (or abstract class) + records
Public library API you will evolveInterface with default methods
The standard interview answer to “why do both exist?” A class can extend only one class, so Java needed a way to say “this type can do X” without using up that single slot: that is the interface. But a contract alone cannot carry shared fields or constructor logic, so Java also keeps abstract classes for the case where related classes genuinely share state. Since Java 8 the gap has narrowed because interfaces can hold behaviour, but they still cannot hold instance state, and that is the line that never moved. The same “prefer composition and small contracts” reasoning is on the OOPs Concepts in Java page; the Collections framework is the best real example, with List as an interface and AbstractList as the skeleton class (see Top 40 Java Collections Interview Questions).
Download the code. AbstractVsInterface.java · BrokenDiamond.java · BrokenInterfaceState.java.

Run a runnable one with java File.java (JDK 11 or later; JDK 25 recommended). Files starting with Broken are meant to fail to compile.

Common interview questions

1. What is the difference between an abstract class and an interface?

An abstract class can have instance fields, constructors and any method bodies, and a class extends only one. An interface has no instance state, may have default, static and private methods, and a class can implement many. See the 12-row table above.

2. Can an abstract class have a constructor?

Yes. It cannot be called with new directly, but it runs when a concrete subclass is instantiated through super(...); the output above shows it running.

3. Can an interface have a constructor?

No. Interfaces have no instance state to initialise.

4. Can an interface have variables?

Only constants. Every field is implicitly public static final; assigning to it is a compile error.

5. What are default methods and why were they added?

Interface methods with a body, added in Java 8 so interfaces like Collection could gain new methods without breaking existing implementers.

6. Can an interface have static and private methods?

Yes: static since Java 8 (called on the interface name), private since Java 9 (shared helper code for default methods).

7. What is the diamond problem and how does Java handle it?

Two interfaces provide the same default method and a class implements both. The compiler rejects the class until it overrides the method, optionally calling A.super.m() and B.super.m().

8. Does Java support multiple inheritance?

Not of classes. A class extends one class but implements many interfaces, which gives multiple inheritance of type and of default behaviour, never of instance state.

9. Can an abstract class implement an interface without implementing its methods?

Yes. Because the abstract class cannot be instantiated, it can leave interface methods unimplemented for its concrete subclasses.

10. Can an abstract class be final?

No. final forbids extension and abstract requires it, so the combination is a compile error.

11. What is a functional interface?

An interface with exactly one abstract method, which a lambda or method reference can implement. @FunctionalInterface asks the compiler to check it.

12. What is a sealed interface?

An interface that names, with permits, the only types allowed to implement it. Combined with pattern-matching switch it gives compiler-checked completeness.

13. When would you choose an abstract class over an interface?

When subclasses share instance fields or constructor logic, or when you want a template method with a final skeleton; otherwise prefer an interface.

Common mistakes

  • Using an abstract class just to share constants or helpers. A static utility or an interface constant block is lighter, and it does not use up your single extends slot.
  • Expecting state in an interface. int count = 0; is a constant; incrementing it does not compile.
  • Forgetting to resolve conflicting defaults. Two interfaces with the same default method make the implementing class fail to compile until it overrides.
  • Adding an abstract method to a published interface. Every implementer breaks. Add a default method instead.
  • Calling an overridable method from an abstract class constructor. It can run before the subclass fields are set; see Flexible Constructor Bodies in Java 25 (JEP 513).
  • Reaching for extends because it reuses code. If the relationship is not IS-A, use composition and an interface.

FAQ

What is the difference between abstract class and interface in Java?

An abstract class can hold instance state, constructors and implemented methods, and a class can extend only one. An interface defines a contract with no instance state, can have default, static and private methods, and a class can implement many.

When should I use an abstract class instead of an interface?

Use an abstract class when subclasses must share fields or constructor logic or follow a fixed template algorithm. Use an interface when you want to describe a capability that unrelated classes can have or when a class needs multiple roles.

Can an interface have a method body in Java 8 or later?

Yes. Java 8 added default and static methods with bodies, and Java 9 added private methods. Instance state is still not allowed.

Why does Java not support multiple inheritance of classes?

To avoid ambiguity about which parent field or method a subclass inherits. Interfaces give multiple inheritance of type and behaviour while avoiding multiple inheritance of state, and conflicting defaults must be resolved explicitly.

Has the difference between abstract class and interface changed in Java 25?

The core difference has not: interfaces still cannot hold instance state and abstract classes still can. Since Java 17 both can be sealed to restrict which classes may extend or implement them.

Where to go next

Other articles in this Java fundamentals series:

No Comments yet!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.