When to use: Java 8+ interface default method, vs. abstract method

147,513

Solution 1

There's a lot more to abstract classes than default method implementations (such as private state), but as of Java 8, whenever you have the choice of either, you should go with the defender (aka. default) method in the interface.

The constraint on the default method is that it can be implemented only in the terms of calls to other interface methods, with no reference to a particular implementation's state. So the main use case is higher-level and convenience methods.

The good thing about this new feature is that, where before you were forced to use an abstract class for the convenience methods, thus constraining the implementor to single inheritance, now you can have a really clean design with just the interface and a minimum of implementation effort forced on the programmer.

The original motivation to introduce default methods to Java 8 was the desire to extend the Collections Framework interfaces with lambda-oriented methods without breaking any existing implementations. Although this is more relevant to the authors of public libraries, you may find the same feature useful in your project as well. You've got one centralized place where to add new convenience and you don't have to rely on how the rest of the type hierarchy looks.

Solution 2

There are a few technical differences. Abstract classes can still do more in comparison to Java 8 interfaces:

  1. Abstract class can have a constructor.
  2. Abstract classes are more structured and can hold a state.

Conceptually, main purpose of defender methods is a backward compatibility after introduction of new features (as lambda-functions) in Java 8.

Solution 3

This is being described in this article. Think about forEach of Collections.

List<?> list = …
list.forEach(…);

The forEach isn’t declared by java.util.List nor the java.util.Collection interface yet. One obvious solution would be to just add the new method to the existing interface and provide the implementation where required in the JDK. However, once published, it is impossible to add methods to an interface without breaking the existing implementation.

The benefit that default methods bring is that now it’s possible to add a new default method to the interface and it doesn’t break the implementations.

Solution 4

As described in this article,

Abstract classes versus interfaces in Java 8

After introducing Default Method, it seems that interfaces and abstract classes are same. However, they are still different concept in Java 8.

Abstract class can define constructor. They are more structured and can have a state associated with them. While in contrast, default method can be implemented only in the terms of invoking other interface methods, with no reference to a particular implementation's state. Hence, both use for different purposes and choosing between two really depends on the scenario context.

Solution 5

Whenever we have a choice between abstract class and interface we should always (almost) prefer default (also known as defender or virtual extensions) methods.

  1. Default methods have put an end to classic pattern of interface and a companion class that implements most or all of the methods in that interface. An example is Collection and AbstractCollection. Now we should implement the methods in the interface itself to provide default functionality. The classes which implement the interface has choice to override the methods or inherit the default implementation.

  2. Another important use of default methods is interface evolution. Suppose I had a class Ball as:

    public class Ball implements Collection { ... }

Now in Java 8 a new feature streams in introduced. We can get a stream by using stream method added to the interface. If stream were not a default method all the implementations for Collection interface would have broken as they would not be implementing this new method. Adding a non-default method to an interface is not source-compatible.

But suppose we do not recompile the class and use an old jar file which contains this class Ball. The class will load fine without this missing method, instances can be created and it seems everything is working fine. BUT if program invokes stream method on instance of Ball we will get AbstractMethodError. So making method default solved both the problems.

Java 9 has got even private methods in interface which can be used to encapsulate the common code logic that was used in the interface methods that provided a default implementation.

Share:
147,513
Narendra Pathai
Author by

Narendra Pathai

Under construction... Till then #SOreadytohelp

Updated on July 13, 2022

Comments

  • Narendra Pathai
    Narendra Pathai almost 2 years

    Java 8 allows for default implementation of methods in interfaces called Default Methods.

    I am confused between when would I use that sort of interface default method, instead of an abstract class (with abstract method(s)).

    So when should interface with default methods be used and when should an abstract class (with abstract method(s)) be used? Are the abstract classes still useful in that scenario?

  • Andrey Chaschev
    Andrey Chaschev over 10 years
    'it is impossible to add methods to an interface without breaking the existing implementation' - is it?
  • Marko Topolnik
    Marko Topolnik over 10 years
    @AndreyChaschev If you add a new method to the interface then all implementors must implement that new method. Therefore it breaks existing implementations.
  • Andrey Chaschev
    Andrey Chaschev over 10 years
    @MarkoTopolnik thanks, missed that. Just to mention there is a way to partially avoid this - by presenting this method in a default abstract implementation. For this example this would be AbstractList::forEach throwing an UnsupportedOperationException.
  • Marko Topolnik
    Marko Topolnik over 10 years
    @AndreyChaschev Yes, that was the old way (khm... is the current way :), with the deficiency that it restricts the implementor to single inheritance from the provided abstract implementation.
  • panther
    panther over 9 years
    By this reasoning, the next thing they would add is default method declarations. I am still unsure about this, the feature seems more like a hack to me that is being exposed to everyone for misuse.
  • Trying
    Trying over 8 years
    This answer is actually correct and makes sense especially "Conceptually, main purpose of defender methods is a backward compatibility "
  • bernie
    bernie almost 8 years
  • LegendLength
    LegendLength almost 7 years
    @UnKnown, basically it allows you to add methods to an interface and classes that implement that interface automatically get that functionality.
  • Anuroop
    Anuroop over 6 years
    The only use of Abstract Classes in Java 8 era that i can see is for defining non-final fields. In Interfaces the fields are by default final so you cannot change them once they are assigned.
  • Marko Topolnik
    Marko Topolnik over 6 years
    @Anuroop Interfaces cannot declare instance fields at all.
  • Anuroop
    Anuroop over 6 years
    A more subtle point about point no. 2 above about "can hold state is this". Abstract classes can hold state which can be changed later. Interfaces can also hold state but once a state is assigned after instance creation the state cannot be changed.
  • Anuroop
    Anuroop over 6 years
    @MarkoTopolnik I would like to add to your comment that interface fields are by default public static final and this is what i mean by my previous comment.
  • Marko Topolnik
    Marko Topolnik over 6 years
    @Anuroop Not just by default---that's the only option. Interfaces cannot declare instance state, which is why abstract classes are here to stay.
  • geronimo
    geronimo over 6 years
    @Anuroop I'd not describe the public static final fields of an interface as "state". The static part means that the're not related to a particular instance at all. They are assigned on class instantiation, which is not the same as after instance creation.
  • Philip Rego
    Philip Rego about 6 years
    "The constraint on the default method is that it can be implemented only in the terms of calls to other interface methods" How is that different then methods in an abstract class. Abstract methods can only call methods in it's class or a superclass.
  • Marko Topolnik
    Marko Topolnik about 6 years
    @PhilipRego Abstract methods don't call anything because they have no implementation. The implemented methods in a class can access the class's state (instance variables). Interfaces cannot declare them so the default methods cannot access them. They have to rely on the class providing an implemented method that accesses the state.
  • hfontanez
    hfontanez over 5 years
    Marko Topolnik, your answer is dead on. But I would like to recommend an update to your answer. You may want to add that the beauty of default methods is that, if the interface adds new default methods, your previous implementation of that interface will not break. This wasn't true prior to Java 8.
  • Marko Topolnik
    Marko Topolnik over 5 years
    @hfontanez Yes, that was the motivation to introduce the feature in Java 8, so they can add lambda-oriented methods to Collection. I can add a sentence about it.
  • Hemanth Peela
    Hemanth Peela over 5 years
    I believe Abstract class has Constructor which can be defined unlike in Interface. In Java 8 also they both different to each other due to this.
  • Anna Klein
    Anna Klein about 5 years
    I think an example in general about when to use the default method over an abc method would be good here as well.
  • George Xavier
    George Xavier almost 5 years
    I agree with #2 but for #1, can't you just implement the interface and thus have a state via the implementation class?
  • George Xavier
    George Xavier almost 5 years
    why does an abstract class have a constructor if it cannot be instantiated?
  • George Xavier
    George Xavier almost 5 years
    Although this is correct, it is a little misleading for you could have a method that indirectly calls to it. For example, if you had an interface Foo and Bar is a class that implements it. Foo has default method method1. You want to do the equivalant of Bar b = new Bar(). b.method1(). Instead have method1 be defined as public void method1(Foo f){} and simple do Foo.method1(b). Foo.method1(b) -> b.method1(); Hope this makes sense. Basically, just have a parameter that takes in an interface and call the method on the interface.
  • George Xavier
    George Xavier almost 5 years
    I won't break if it so happens that ahead of time, all implementations included that method. Which is unlikely but possible.
  • Sujay Mohan
    Sujay Mohan over 4 years
    We can call super() from child class which will call constructor of abstract class.This impacts the state of abstract class.
  • valijon
    valijon over 4 years
    Now interfaces have private methods too howtodoinjava.com/java9/java9-private-interface-methods
  • Faheem Shah
    Faheem Shah about 4 years
    I like the answer but what does "Conceptually, main purpose of defender methods is a backward compatibility after introduction of new features (as lambda-functions) in Java 8" mean?
  • Glenn Mohammad
    Glenn Mohammad over 3 years
    I just learned that the assumption taken was based on backward-compat. Thought it's got more something to do with resorting to multiple inheritance or "Traits" haha
  • Aniket
    Aniket almost 3 years
    @GeorgeXavier for your question as to 'Why do abstract classes have constructors?" Hopefully this may shed some light on your question. Thanks. ..... Link 1: (stackoverflow.com/questions/260666/…) ...... Link 2: (stackoverflow.com/questions/2170500/…)