Java Interface vs Abstract Class - know when to use what

Posted on Mar 25, 2022

Learn the differences between Java Interfaces and Abstract Classes in this tutorial


The interface and abstract class reference types in Java are used to create abstractions.

Both interface and abstract class can’t be instantiated directly. They need to be implemented or extended by other classes.

But these two reference types have many differences that change the way your abstractions work.

One obvious difference is that an abstract class is a class. A Java class can only extend one class, but it can implement many interfaces.

Below are some notable differences between Java interface and abstract class reference types:

Access modifier for members

An abstract class can have members with access modifiers (such as private, protected, and public) while interface members are all public:

abstract class Individual {
    protected String tribe = "Hominini";
    private String species = "Homo Sapiens";
    public String name = "Nathan";
}

interface Human {
    protected String tribe = "Hominini";
    // ERROR: protected modifier not allowed
    private String species = "Homo Sapiens";
    // ERROR: private modifier not allowed
    public String name = "Nathan";
    // WARNING: public modifier is redundant
}

The protected and private access modifiers are not allowed in an interface.

The public modifier is redundant because all variable members of an interface are public by default.

Non-access modifier for members

By default, an interface members are both static and final.

On the other hand, an abstract class members can be final, static, or neither.

Consider the interface code example below:

interface Human {
    String name = "Nathan";
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Human.name); // Nathan
        Human.name = "Jack" // ERROR
    }
}

An interface members can be called directly because they are static by default.

In an abstract class, you need to declare the members as static to access them directly:

abstract class Individual {
    String first_name = "Nathan";
    static String last_name = "Sebhastian";
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Individual.first_name); // ERROR
        System.out.println(Individual.last_name); // OK

        Individual.first_name = "Smith"; // ERROR
        Individual.last_name = "Smith"; // OK
    }
}

You can also add the final modifier to make the members value immutable:

abstract class Individual {
    // this is the default in interface:
    final static String last_name = "Sebhastian";
}

Because abstract class variables are not final by default, you can declare variables without initializing them as follows:

abstract class Individual {
    String first_name;
    String last_name;
}

And that’s how the interface and abstract class differ in terms of non-access modifiers.

Methods modifier in the reference types

By default, an interface can only have abstract methods. Declaring a method with implementation will result in a compile-time error:

interface Human {
    void greetings() {
        System.out.println("Hello!");
    }
    // ERROR: abstract methods cannot have a body

    void call(); // Correct abstract method
}

Since Java 8, the interface type has been improved so it can also have default and static methods.

When you want to provide a default implementation of interface methods, add the default modifier as follows:

interface Human {
    default void greetings() {
        System.out.println("Hello!");
    }

    // You can also declare a static method:
    static void call() {
        System.out.println("Hi!");
    }
}

In an abstract class, you can declare both regular and abstract methods as shown below:

abstract class Individual {
    void greetings() {
        System.out.println("Hello!");
    }

    abstract void call();
}

Note that you need to add the abstract modifier when declaring an abstract method in an abstract class.

Inheritance rule

The interface and abstract class have no special inheritance rule.

You can extend a single class and implement multiple interfaces to an abstract class when you need to:

class A {}
class B {}

interface ZX {}
interface ZY {}

abstract class C extends A, B {}
// ERROR: only one class allowed

abstract class C extends A implements ZX, ZY {}
// OK

On the other hand, an interface can only extend another interface:

class A {}

interface ZX {}
interface ZY {}

interface Test implements ZX {}
// ERROR: implements not allowed

interface Test extends A {}
// ERROR: interface expected, class A received

interface Test extends ZX, ZY {}
// OK

And those are the notable differences between an interface and an abstract class in Java.

When to use interface or abstract class?

The key point to remember is that an interface is used to achieve complete abstraction, while an abstract class is used to achieve partial abstraction.

An interface is used to provide capabilities that an implementing class will provide.

For example, the Animal interface promises that the implementing object can walk:

interface Animal {
    void walk();
}

But the implementation of the walk method is left to the object that implements it.

A Dog class will walk with four legs, while a Kangaroo class walk with two legs:

class Dog implements Animal {
    @Override
    public void walk() {
        System.out.println("4 legs");
    }
}

class Kangaroo implements Animal {
    @Override
    public void walk() {
        System.out.println("2 legs");
    }
}

Although now you can have default and static methods, the rule remains the same: An interface defines what an object can do.

On the other hand, an abstract class is more interested in what an object is.

When using an abstract class you are giving common characteristics between the implementing objects:

abstract class Person {
    String first_name;
    String last_name;
    int lungs = 2;

    void breathe() {
        System.out.println("Breathe in.. breathe out");
    }
}

A person’s first_name and last_name are commonly given when the person is born, so they are declared, but not initialized.

You can’t do the same with an interface because any variable declared in an interface is final.

To sum it up, an interface is used to provide promises of what an object can do and have.

Meanwhile, an abstract class provides the shared things that an object can do and have.

I hope this tutorial has helped you to understand the differences between an interface and an abstract class. 👍

Level up your programming skills

I'm sending out an occasional email with the latest programming tutorials. Drop your email in the box below and I'll send new stuff straight into your inbox!

No spam. Unsubscribe anytime.