629

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?

cellepo
  • 4,001
  • 2
  • 38
  • 57
Narendra Pathai
  • 41,187
  • 18
  • 82
  • 120
  • 47
    Maybe you still cannot have fields, private methods, etc. in interfaces, while you can in abstract class? – sp00m Nov 15 '13 at 10:12
  • 2
    I was wondering about this topic before, now i`m clear.Thanks to @Narendra Pathai . I would like to add link of another thread asked by you regarding same topic, as both of these were my doubts. http://stackoverflow.com/questions/19998309/purpose-of-default-or-defender-methods-in-java-8 – Ashutosh Ranjan Jun 18 '15 at 05:56
  • You can find a nice post on this one here: http://blog.codefx.org/java/everything-about-default-methods/ – Fabri Pautasso Nov 21 '16 at 12:35
  • You can still sometimes code a base class as an interface even if the base class has state. It's just that the interface has to define setters and getters for the state and the concrete classes have to implement them and define the field. One restriction on this is that in an abstract class, the bean property can be private or protected. In interfaces only have public methods. So one reason you would use an abstract base class is if your classes have a property that needs to be private or protected. – DaBlick Aug 13 '18 at 21:26
  • @DaBlick Could you not solve the state problem in an interface via a HashMap. Ex: if you want a class Foo which holds int a, b, String c. and you want them to have state, create a HashMap< /*name of Foo object*/ String, /*map of fields*/ Hashmap< /*name specific Field*/ String, /*field value*/ Object>> map. When you want to "instantiate" the theoretical class Foo, you have method, instantiate(String nameOfFoo) which does map.put(nameOfFoo, fields) where fields is a HashMap fields.put("a", new int("5")); fields.put("b", new int("6")); fields.put("c", "blah")); – George Xavier Jul 24 '19 at 16:05
  • in other words <"nameOfFoo", <"specificfieldofFoo", fieldValue> > – George Xavier Jul 24 '19 at 16:06
  • @GeorgeXavier To me it sounds like the HashMap you are talking about IS "state". I don't think in an interface you have way to hold the "state" of the HashMap. – DaBlick Jul 24 '19 at 20:21
  • @DaBlick a static final map or collection can hold nonstatic values... I think. In which case, the map links the name of the object to another map which links the specific field in the specific object, to the value. Like an index. Enter in the name of the "instance" retrieving the map of fields. Enter in the name of the specific field in that already retrieved "instance" retrieving the field value. – George Xavier Jul 25 '19 at 14:38
  • @GeorgeXavier That is not semantically equivalent to fields in general. Only static fields. I would consider that a bad practice and discourage that. All implementations of the interface would share the same property values (like static fields, but unlike non-static fields). You also expose yourself to bugs, re-entrancy issues, etc. JMHO – DaBlick Jul 25 '19 at 19:55
  • @DaBlick It's not a field, but it works as an equivalent. All you are doing is linking the object to a name via a string and hashmap, and the "field" equivalents would be inside the second hashmap. I never meant that systematically, it is a field. Rather, I meant that it works as an equivalent in that it will technically allow for a simulated "instantiation". I don't know what you mean by property values; the values inside the hashmap are able to be changed even if the hashmap in itself is static. I don't know what re-entry is though. – George Xavier Jul 25 '19 at 20:35
  • Default methods has put a stop on classic pattern: https://stackoverflow.com/a/32774868/1216775 – akhil_mittal Sep 09 '21 at 03:47

16 Answers16

368

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.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 40
    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. – panther Feb 16 '15 at 18:47
  • 3
    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. – Anuroop Sep 17 '17 at 09:41
  • 1
    @Anuroop Interfaces cannot declare instance fields at all. – Marko Topolnik Sep 17 '17 at 09:42
  • @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. – Anuroop Sep 17 '17 at 09:46
  • 8
    @Anuroop Not just by default---that's the only option. Interfaces cannot declare instance state, which is why abstract classes are here to stay. – Marko Topolnik Sep 17 '17 at 09:47
  • "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. – Philip Rego Feb 27 '18 at 19:59
  • 2
    @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. – Marko Topolnik Feb 27 '18 at 20:13
  • 4
    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. – hfontanez Sep 09 '18 at 22:13
  • 1
    @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. – Marko Topolnik Sep 10 '18 at 06:32
  • I think an example in general about when to use the default method over an abc method would be good here as well. – Anna Klein May 05 '19 at 12:47
  • 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 Jul 25 '19 at 20:48
  • Appreciate "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." – Troskyvs Jul 19 '22 at 00:58
152

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.

Vadym Vasyliev
  • 1,539
  • 1
  • 8
  • 5
  • 27
    This answer is actually correct and makes sense especially "Conceptually, main purpose of defender methods is a backward compatibility " – Trying Sep 13 '15 at 20:09
  • 1
    @UnKnown this page gives more insight: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html – bernie Jun 14 '16 at 14:22
  • @UnKnown, basically it allows you to add methods to an interface and classes that implement that interface automatically get that functionality. – LegendLength Jul 15 '17 at 07:15
  • 3
    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 Sep 17 '17 at 09:43
  • 5
    @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_. – geronimo Dec 22 '17 at 11:20
  • 2
    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? – Faheem Shah Mar 25 '20 at 09:02
  • 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 – Glenn Mohammad Jan 11 '21 at 12:06
71

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.

Masudul
  • 21,823
  • 5
  • 43
  • 58
  • 1
    'it is impossible to add methods to an interface without breaking the existing implementation' - is it? – Andrey Chaschev Nov 15 '13 at 10:27
  • 31
    @AndreyChaschev If you add a new method to the interface then all implementors must implement that new method. Therefore it breaks existing implementations. – Marko Topolnik Nov 15 '13 at 10:31
  • 4
    @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`. – Andrey Chaschev Nov 15 '13 at 10:39
  • 4
    @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. – Marko Topolnik Nov 15 '13 at 10:43
  • I won't break if it so happens that ahead of time, all implementations included that method. Which is unlikely but possible. – George Xavier Jul 25 '19 at 20:58
31

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.

Sufiyan Ghori
  • 18,164
  • 14
  • 82
  • 110
  • 1
    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. – Hemanth Peela Feb 10 '19 at 17:22
  • 1
    why does an abstract class have a constructor if it cannot be instantiated? – George Xavier Jul 24 '19 at 15:01
  • 1
    We can call super() from child class which will call constructor of abstract class.This impacts the state of abstract class. – Sujay Mohan Sep 24 '19 at 05:30
  • @GeorgeXavier for your question as to 'Why do abstract classes have constructors?" Hopefully this may shed some light on your question. Thanks. ..... Link 1: (https://stackoverflow.com/questions/260666/can-an-abstract-class-have-a-constructor) ...... Link 2: (https://stackoverflow.com/questions/2170500/why-do-abstract-classes-in-java-have-constructors) – Aniket Jun 16 '21 at 16:26
22

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.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
20

These two are quite different:

Default methods are to add external functionality to existing classes without changing their state.

And abstract classes are a normal type of inheritance, they are normal classes which are intended to be extended.

Andrey Chaschev
  • 16,160
  • 5
  • 51
  • 68
17

Although its an old question let me give my input on it as well.

  1. abstract class: Inside abstract class we can declare instance variables, which are required to the child class

    Interface: Inside interface every variables is always public static and final we cannot declare instance variables

  2. abstract class: Abstract class can talk about state of object

    Interface: Interface can never talk about state of object

  3. abstract class: Inside Abstract class we can declare constructors

    Interface: Inside interface we cannot declare constructors as purpose of
    constructors is to initialize instance variables. So what is the need of constructor there if we cannot have instance variables in interfaces.

  4. abstract class: Inside abstract class we can declare instance and static blocks

    Interface: Interfaces cannot have instance and static blocks.

  5. abstract class: Abstract class cannot refer lambda expression

    Interfaces: Interfaces with single abstract method can refer lambda expression

  6. abstract class: Inside abstract class we can override OBJECT CLASS methods

    Interfaces: We cannot override OBJECT CLASS methods inside interfaces.

I will end on the note that:

Default method concepts/static method concepts in interface came just to save implementation classes but not to provide meaningful useful implementation. Default methods/static methods are kind of dummy implementation, "if you want you can use them or you can override them (in case of default methods) in implementation class" Thus saving us from implementing new methods in implementation classes whenever new methods in interfaces are added. Therefore interfaces can never be equal to abstract classes.

Umar Tahir
  • 585
  • 6
  • 21
15

Regarding your queries:

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

As per oracle documentation on default methods

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

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

oracle documentation provides perfect answer.

Abstract Classes Compared to Interfaces:

Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation.

However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.

With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public.

You can extend only one class, whether or not it is abstract. But you can implement any number of interfaces.

abstract class use cases:

  1. You don't have implementation in base class (with shared data) and only sub-classes have to define their own implementation. You need abstract class instead of interface since you want to share state with sub-classes.

  2. Abstract classes are used in Abstract Factory design pattern implementation ( creational pattern )

    example: Factory Pattern. When to use factory methods?

  3. You can find many use cases of abstract classes in design patterns.

    example: Bridge pattern ( Structural pattern )

    Does the Bridge Pattern decouples an abstraction from implementation?

  4. Abstract classes are used in Decorator design pattern

    example : When to Use the Decorator Pattern?

  5. Abstract class is best fit for template method pattern where you have to create skeleton.

    example: Template design pattern in JDK, could not find a method defining set of methods to be executed in order

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
  • 1
    Now interfaces have private methods too https://howtodoinjava.com/java9/java9-private-interface-methods/ – valijon Oct 09 '19 at 02:29
9

Default methods in Java interface enables interface evolution.

Given an existing interface, if you wish to add a method to it without breaking the binary compatibility with older versions of the interface, you have two options at hands: add a default or a static method. Indeed, any abstract method added to the interface would have to be impleted by the classes or interfaces implementing this interface.

A static method is unique to a class. A default method is unique to an instance of the class.

If you add a default method to an existing interface, classes and interfaces which implement this interface do not need to implement it. They can

  • implement the default method, and it overrides the implementation in implemented interface.
  • re-declare the method (without implementation) which makes it abstract.
  • do nothing (then the default method from implemented interface is simply inherited).

More on the topic here.

The Guy with The Hat
  • 10,836
  • 8
  • 57
  • 75
kiriloff
  • 25,609
  • 37
  • 148
  • 229
6

Remi Forax rule is You don't design with Abstract classes. You design your app with interfaces. Watever is the version of Java, whatever is the language. It is backed by the Interface segregation principle in SOLID principles.

You can later use Abstract classes to factorize code. Now with Java 8 you can do it directly in the interface. This is a facility, not more.

Nicolas Zozol
  • 6,910
  • 3
  • 50
  • 74
2

when should interface with default methods be used and when should an abstract class be used?

Backward compatibility: Imagine that your interface is implemented by hundreds of classes, modifying that interface will force all the users to implement the newly added method, even though it could be not essential for many other classes that implements your interface, Plus it allows your interface to be a functional interface

Facts & Restrictions:

1-May only be declared within an interface and not within a class or abstract class.

2-Must provide a body

3-It is not assumed to be abstract as other normal methods used in an interface.

Ahmad Sanie
  • 3,678
  • 2
  • 21
  • 56
1

In Java 8, an interface looks like an abstract class although their might be some differences such as :

1) Abstract classes are classes, so they are not restricted to other restrictions of the interface in Java e.g. abstract class can have the state, but you cannot have the state on the interface in Java.

2) Another semantic difference between interface with default methods and abstract class is that you can define constructors inside an abstract class, but you cannot define constructor inside interface in Java

Manish Sahni
  • 488
  • 2
  • 7
  • 21
0

Default methods in Java Interface are to be used more for providing dummy implementation of a function thus saving any implementing class of that interface from the pain of declaring all the abstract methods even if they want to deal with only one. Default methods in interface are thus in a way more a replacement for the concept of adapter classes.

The methods in abstract class are however supposed to give a meaningful implementation which any child class should override only if needed to override a common functionality.

anik
  • 155
  • 1
  • 17
0

As mentioned in other answers, the ability to add implementation to an interface was added in order to provide backward compatibility in the Collections framework. I would argue that providing backward compatibility is potentially the only good reason for adding implementation to an interface.

Otherwise, if you add implementation to an interface, you are breaking the fundamental law for why interfaces were added in the first place. Java is a single inheritance language, unlike C++ which allows for multiple inheritance. Interfaces provide the typing benefits that come with a language that supports multiple inheritance without introducing the problems that come with multiple inheritance.

More specifically, Java only allows single inheritance of an implementation, but it does allow multiple inheritance of interfaces. For example, the following is valid Java code:

class MyObject extends String implements Runnable, Comparable { ... }

MyObject inherits only one implementation, but it inherits three contracts.

Java passed on multiple inheritance of implementation because multiple inheritance of implementation comes with a host of thorny problems, which are outside the scope of this answer. Interfaces were added to allow multiple inheritance of contracts (aka interfaces) without the problems of multiple inheritance of implementation.

To support my point, here is a quote from Ken Arnold and James Gosling from the book The Java Programming Language, 4th edition:

Single inheritance precludes some useful and correct designs. The problems of multiple inheritance arise from multiple inheritance of implementation, but in many cases multiple inheritance is used to inherit a number of abstract contracts and perhaps one concrete implementation. Providing a means to inherit an abstract contract without inheriting an implementation allows the typing benefits of multiple inheritance without the problems of multiple implementation inheritance. The inheritance of an abstract contract is termed interface inheritance. The Java programming language supports interface inheritance by allowing you to declare an interface type

johnnyodonnell
  • 1,838
  • 3
  • 16
  • 34
0

From a business use case context , Interfaces can be used to define specific business rules , where as abstract class would define the common structure to kickoff the business.

Say some business owner wants to partner with Amazon and Walmart , then the interfaces defined here would be WalmartPartner and AmazonPartner would define the specific business rules and the abstract class BusinessSetup will get the business setup in a specific region.

// Interfaces
 
public interface WalmartPartner {
    public static boolean signUpForWalmartBusinessAccount(String BusinessId){
        System.out.println("Setting up Walmart Business Partner");
        return true;
    }
    public default  void  getWalmartDeals(){
        System.out.println("Default walmart deal executed !");
    }
    public abstract void setupShopifyForWalmart();
    public abstract  void setupWalmartProducts();

public interface AmazonPartner {
    public static boolean signUpAsAmazonServicePartner(String BusinessId){
        System.out.println("Setting up Amazon Business Partner");
        return true;
    }
    public default  void  paymentPlatformSetup(){
        System.out.println(" Amazon default payment platform is setup");
    }
    public abstract void setupPrimeMemberDealsByRegion();
    public abstract  void setupPrimeDeals();
}

 // Abstract class 

public abstract class BusinessSetup {
    String businessId ;
    public BusinessSetup(String businessId){
        this.businessId = businessId;
        System.out.println("1. Initial Business setup for BusienssID: "+this.businessId+" is Complete");
    }
    public final boolean getBusinessRegisteredInRegion(String region){
        System.out.println("2. Business got registered in "+region+ "!");
        return true;
    }
    public abstract void setupCustomerPlatform(String customerId);
    public abstract void setupVendorPlatform(String vendorId);

}

// Concrete Class 
public class WalMartPartnerImpl extends BusinessSetup implements WalmartPartner {
    public WalMartPartnerImpl(String businessId) {
        super(businessId);
    }
    @Override
    public void setupCustomerPlatform(String customerId) {
    }

    @Override
    public void setupVendorPlatform(String vendorId) {
    }

    @Override
    public void setupShopifyForWalmart() {
    }

    @Override
    public void setupWalmartProducts() {
    }
    public static void main(String args[]){
        WalMartPartnerImpl walMartPartner = new WalMartPartnerImpl("wal8989");
        walMartPartner.getBusinessRegisteredInRegion("california");
        walMartPartner.getWalmartDeals();
        walMartPartner.setupCustomerPlatform("wal8989");

    }
}
Alferd Nobel
  • 3,185
  • 2
  • 30
  • 35
-2

Please think first of open/closed principle. The default methods in interfaces DO VIOLATE it. This is a bad feature in Java. It encourages bad design, bad architecture, low software quality. I would suggest to avoid using default methods completely.

Ask yourself a few questions: Why can't you put your methods to the abstract class? Would you need then more than one abstract class? Then think about what is your class responsible for. Are you sure all methods you are going to put to the single class really fulfill the same purpose? May be you will distinguish several purposes and will then split your class into several classes, for each purpose its own class.

Pang
  • 9,564
  • 146
  • 81
  • 122
mentallurg
  • 4,967
  • 5
  • 28
  • 36