ChatGPT解决这个技术问题 Extra ChatGPT

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

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?

Maybe you still cannot have fields, private methods, etc. in interfaces, while you can in abstract class?
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. stackoverflow.com/questions/19998309/…
You can find a nice post on this one here: blog.codefx.org/java/everything-about-default-methods
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 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"));

M
Marko Topolnik

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.


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.
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 Not just by default---that's the only option. Interfaces cannot declare instance state, which is why abstract classes are here to stay.
@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, 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.
V
Vadym Vasyliev

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

Abstract class can have a constructor. 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.


This answer is actually correct and makes sense especially "Conceptually, main purpose of defender methods is a backward compatibility "
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 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.
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?
M
Masudul

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.


'it is impossible to add methods to an interface without breaking the existing implementation' - is it?
@AndreyChaschev If you add a new method to the interface then all implementors must implement that new method. Therefore it breaks existing implementations.
@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.
@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.
I won't break if it so happens that ahead of time, all implementations included that method. Which is unlikely but possible.
S
Sufiyan Ghori

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.


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.
why does an abstract class have a constructor if it cannot be instantiated?
We can call super() from child class which will call constructor of abstract class.This impacts the state of abstract class.
@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/…)
a
akhil_mittal

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

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. 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.


A
Andrey Chaschev

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.


U
Umar Tahir

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

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 abstract class: Abstract class can talk about state of object Interface: Interface can never talk about state of object 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. abstract class: Inside abstract class we can declare instance and static blocks Interface: Interfaces cannot have instance and static blocks. abstract class: Abstract class cannot refer lambda expression Interfaces: Interfaces with single abstract method can refer lambda expression 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.


C
Community

Regarding your query of

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?

java 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. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.

Use cases for each of them have been explained in below SE post:

What is the difference between an interface and abstract class?

Are the abstract classes still useful in that scenario?

Yes. They are still useful. They can contain non-static, non-final methods and attributes (protected, private in addition to public), which is not possible even with Java-8 interfaces.


Now interfaces have private methods too howtodoinjava.com/java9/java9-private-interface-methods
T
The Guy with The Hat

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.


N
Nicolas Zozol

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.


A
Ahmad Sanie

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.


M
Manish Sahni

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


I agree with #2 but for #1, can't you just implement the interface and thus have a state via the implementation class?
a
anik

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.


j
johnnyodonnell

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


A
Alferd Nobel

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");

    }
}

P
Pang

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.