Difference Between Interface and Abstract Class in Java

Learn the difference between an interface and abstract class in Java 25 with code, a comparison table, default methods, AbstractList and when to use each.

Side-by-side comparison of what a Java interface and an abstract class can contain

The difference between an interface and abstract class in Java is that an abstract class is a partly built class with fields, constructors and shared code that a subclass extends, whereas an interface is a contract of methods without instance state that any class can implement, and a class can implement many interfaces but extend only one class.

We use an abstract class to share code and state among closely related classes, and an interface to describe a capability that unrelated classes can offer, such as Comparable or Runnable. In practice, the two work best together.

The following example defines a storage contract as an interface and puts the shared code in an abstract class.

interface Storage {                                     // the contract
    void put(String key, String value);
    String get(String key);
}

abstract class BaseStorage implements Storage {         // a partial implementation
    protected final Map<String, String> data = new HashMap<>();  // instance state
    private final String name;
    protected BaseStorage(String name) { this.name = name; }     // constructor
    public String get(String key) { return data.get(key); }       // shared code
    public String name() { return name; }
}

class MemoryStorage extends BaseStorage {
    MemoryStorage() { super("memory"); }
    public void put(String key, String value) { data.put(key, value); }
}

The interface names the operations and nothing more, while the abstract class already holds a map, a constructor and a working get() method. Each type gets its own section first, followed by a side-by-side comparison, the way the JDK combines the two, and a checklist for choosing one.

1. Abstract Classes Hold State and Shared Code

A class declared with the abstract keyword cannot be instantiated, and it may contain abstract methods without a body. Every other feature of a normal class stays available, such as instance fields, constructors, protected and private members, and final methods. If a class has at least one abstract method, the compiler requires the class to be abstract.

A concrete subclass extends the abstract class and implements the missing methods. The constructor of the abstract class runs as part of every subclass constructor, so the shared fields are set up in one place.

BaseStorage prefs = new MemoryStorage();
prefs.put("theme", "dark");
String theme = prefs.get("theme");          // "dark"
String storageName = prefs.name();          // "memory"

Creating a BaseStorage with new is a compile error, because the class is abstract and still has no body for put(). An anonymous subclass that fills in the gap is allowed, which is handy for a one-off variant such as a read-only store in a test.

// does not compile: BaseStorage is abstract; cannot be instantiated
BaseStorage broken = new BaseStorage("broken");
BaseStorage readOnly = new BaseStorage("read-only") {
    public void put(String key, String value) {
        throw new UnsupportedOperationException("read-only storage");
    }
};
String readOnlyName = readOnly.name();      // "read-only"

2. Interfaces Define a Contract

An interface declares what a type can do without saying how. Its abstract methods are implicitly public and abstract, and its fields are implicitly public static final constants, so an interface cannot hold per-object state and has no constructor.

Interfaces gained method bodies in two steps. Java 8 added default and static methods, and Java 9 added private methods (JEP 213) so that default methods can share helper code. The following example uses every kind of interface member.

interface Expiring {
    long MAX_TTL = 86_400;                      // constant, public static final

    long ttlSeconds();                          // abstract method

    default boolean isShortLived() {            // Java 8, default method
        return ttlSeconds() < minutes(5);
    }

    static Expiring of(long seconds) {          // Java 8, static method
        return () -> Math.min(seconds, MAX_TTL);
    }

    private long minutes(long count) {          // Java 9, private method
        return count * 60;
    }
}
Expiring session = Expiring.of(120);
boolean shortLived = session.isShortLived();        // true
long capped = Expiring.of(999_999).ttlSeconds();    // 86400

Because Expiring has a single abstract method, a lambda can implement it, which is what of() returns. A class can implement Storage, Expiring and any other interface at the same time, which gives Java multiple inheritance of type without the problems of multiple inheritance of state.

3. Interface vs Abstract Class Comparison

Default methods let interfaces carry behavior, but they still cannot carry instance state, constructors or non-public abstract methods, and that gap decides most design choices. The diagram groups what each type can contain.

Side-by-side comparison of what a Java interface and an abstract class can contain
An abstract class can hold state and constructors; an interface holds only constants and methods, and a class can implement many interfaces

The table lists the rules for Java 25, with the version that introduced each interface feature.

FeatureInterfaceAbstract class
Keyword for the subtypeimplements (a class), extends (an interface)extends
How many per classAny numberOne
Instance fieldsNo, only public static final constantsYes, any modifier
ConstructorsNoYes, called through super(…)
Abstract methodsImplicitly public abstractAny access except private
Methods with a bodydefault and static (Java 8), private (Java 9)Any kind
final methodsNoYes
protected membersNoYes
Lambda implementationYes, if it has one abstract methodNo
Typical JDK exampleComparable, Runnable, ListAbstractList, InputStream, Number

Since Java 17, both can be sealed, so the author controls which subtypes may exist. Neither type can be instantiated with new, and both can declare a static main() method, so that is not a difference between them.

4. An Abstract Class That Implements an Interface

An abstract class can implement an interface without providing all of its methods, because the class itself stays incomplete. The first concrete subclass must supply whatever is still missing. In the intro, BaseStorage implements get() and leaves put() to MemoryStorage.

The JDK uses this combination on purpose. The List interface declares 25 abstract methods, and AbstractList implements almost all of them on top of get() and size(). The Javadoc calls such a class a skeletal implementation, and it turns a full List into a two-method job.

class Weekdays extends AbstractList<String> {
    private final String[] days = {"Mon", "Tue", "Wed", "Thu", "Fri"};

    @Override
    public String get(int index) { return days[index]; }

    @Override
    public int size() { return days.length; }
}
List<String> weekdays = new Weekdays();
boolean hasWed = weekdays.contains("Wed");  // true
int thu = weekdays.indexOf("Thu");          // 3
List<String> middle = weekdays.subList(1, 3);   // [Tue, Wed]
boolean added = weekdays.add("Sat");        // UnsupportedOperationException

Callers see only the List interface, and Weekdays reuses the iteration, search and sublist code of AbstractList. The inherited add() throws UnsupportedOperationException until a subclass overrides it, which is the documented way to build an unmodifiable list.

5. When to Use an Interface or an Abstract Class

The question to ask is whether the types share an implementation or only a role. Classes that share fields and code belong under one abstract class, whereas classes that only promise the same operations should implement a common interface. The Oracle Java tutorial gives similar guidance, and three situations cover most cases.

  • Pick an abstract class when several closely related classes share fields or code, when we need constructors to set up shared state, or when some members must stay protected or final.
  • Pick an interface when unrelated classes should offer the same operation, when a class needs more than one supertype, or when callers should depend on a contract that tests can replace with a fake or a lambda.
  • Pick both when a public contract has many implementations with common code. Declare the interface for callers and an abstract base class for implementers, as List and AbstractList do.

Say a web app keeps user settings in memory during tests and in Redis in production. The settings service depends on the Storage interface, and both implementations extend BaseStorage to reuse the key handling. Swapping the store becomes a one-line change where the service is created.

class SettingsService {
    private final Storage storage;

    SettingsService(Storage storage) { this.storage = storage; }

    String theme() {
        String value = storage.get("theme");
        return value != null ? value : "light";
    }
}
SettingsService settings = new SettingsService(new MemoryStorage());
String defaultTheme = settings.theme();     // "light"

Frameworks follow the same split. The Jakarta Servlet API ships HttpServlet as an abstract class, so each servlet inherits the request dispatching code and overrides only doGet() or doPost(), while Spring defines most extension points, such as Converter, as interfaces. The comparison also maps to two OOP concepts, namely abstraction and inheritance, and extends vs implements covers the keywords in detail.

6. Interface and Abstract Class FAQs

Constructors cause the most confusion, because one of the two types can declare them and the other cannot, and default methods come right after.

6.1. Can abstract classes have constructors in Java?

Yes. The constructor runs when a subclass is created, through the implicit or explicit super(…) call, and it typically initializes shared fields. Declaring it protected makes the intent clear.

6.2. Can an interface have a constructor?

No. An interface has no instance fields to initialize, so the compiler rejects a constructor declaration in an interface.

6.3. Can an abstract class have no abstract methods?

Yes. A class can be abstract only to prevent direct instantiation, for example a base class whose subclasses add the meaningful behavior. HttpServlet is abstract even though none of its methods is abstract.

6.4. Can an interface extend an abstract class?

No. An interface can extend only other interfaces. An abstract class, on the other hand, can implement any number of interfaces.

6.5. Did default methods make abstract classes unnecessary?

No. Default methods let an interface grow without breaking existing implementations, but an interface still cannot hold instance fields, constructors or protected methods. When implementations share state, an abstract class is still the right tool.

7. Conclusion

An abstract class is a partial implementation with state, constructors and any kind of method, and a class extends only one of them. An interface is a contract without instance state, it may contain default, static and private methods, and a class can implement many interfaces.

Choose an abstract class for shared code among close relatives and an interface for roles that unrelated classes play. For a public API with several implementations, we declare the interface for callers and add an abstract base class for implementers.

8. References

Happy Learning !!

Source Code on Github

Leave a Comment

  1. Abstract classes can have a constructor because the constructor does not define a method signature that must be matched inherited by child classes. It’s the only method that doesn’t require that same signature on child implementations

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.