Why do we need default methods in Java?

I am looking at news in Java 8 compared to 7 and in addition to very interesting things like lambdas or a new temporary structure, I found that a new function (?) Was introduced: default methods .

I found the following example in this article :

public interface Math { int add(int a, int b); default int multiply(int a, int b) { return a * b; } } 

It seems very strange to me. Above, the code looks like an abstract class with an implemented method. So why introduce default methods in an interface? What is the actual advantage of this approach?

In the same article, I read this explanation:

Why do I need to add methods to interfaces? Well, this is because interfaces are too closely related to their implementation classes. those. it is impossible to add a method to an interface without violating the implementation class. After adding a method in the interface, all its implemented classes must declare the method body of this new method.

Well, that doesn't convince me at all. IMHO I believe that when a class implements an interface, obviosly should declare a body of methods for each method in it. This is certainly a limitation, but it also confirms its "nature" (if you understand what I mean ...)

If you have common logic for each inheriting class, you will put it in the implementing class abstract .

So what is the real advantage of the default method? (this looks more like a workaround than a new feature ...)


UPDATE I understand that this approach is intended for backward compatibility, but it still does not convince me that way. The interface represents the behavior that the class MUST have . Thus, a class that implements a certain interface certainly has this behavior. But if someone can arbitrarily change the interface, this restriction will be violated. Behavior can change at any time ... Am I wrong?

+7
java programming-languages java-8
source share
3 answers

This is for backward compatibility.

If you have an interface that other people have implemented, then if you add a new method to the interface, all existing implementations will be violated.

By adding a new method with a default implementation, you remain source compatible with existing implementations.

For a slightly simple / far-fetched example that hopefully demonstrates this, let's say you created a library:

 void drawSomething(Skin skin) { } interface Skin { Color getColor(); Image getBackgroundImage(); } 

Now you are starting to create a new version of your library and want to add the concept of border colors, which is easy to add to the interface:

 interface Skin { Color getColor(); Color getBorderColor(); Image getBackgroundImage(); } 

But the problem is that every person using your library should go back to every Skin implementation they have ever done and add this new method.

If instead you provided the standard implementation of getBorderColor , which was just called getColor , then everything "just works."

+7
source share

In the past, there were many methods acting on an abstract interface. Prior to Java 8, they had to be added to an additional class connecting the interface, for example. Collections with Collection .

This old approach was no more convincing than default methods and no more practical. Instead of list.sort() you should have said Collections.sort(list) . This also implies that when creating the interface you had to make a fundamental decision, either you would need each List implementation to implement the sort method, or you would provide a sort method in a utility class that could not be overridden.

Using the default methods, you can have a standard implementation, the implementation of which should not be implemented by List implementations by itself, but it can be overridden if a particular implementation has a more efficient way to do this, knowing its internals, for example ArrayList.sort passes its internal array directly on Arrays.sort , skipping some intermediate operations.

+3
source share

Suppose that at some point you want to add new functionality to the declared interface, right up to Java 7. If you add a new method to the declared interface, you also need to define the method implementation in the classes that implement this interface.

In java 8, you can add a default method containing an implementation, and the entire child class will inherit this method.

Edit: (After updating the question)

The interface represents the behavior that the class MUST have

It still represents the behavior this class should have, your confusion is how you define the behavior. All implementing classes inherit the default method, and are free to write their own implementation. consider the following two cases:

  • If the class implementation does not provide its own implementation and simply inherits the default method. If you change the default behavior of the method in the interface, the implementation classes will have updated behavior, since they inherit the default method, which is why it contains. An interface represents the behavior that a class MUST have.
  • If the implementing class provides its own version of the default method, and if you change the behavior (only arguments) of the default method. In this case, the implementation class will have two overloaded methods, one of which was previously defined, and the second by default. and if you change the overall behavior (arguments with return type as well), this will create ambiguity in the implementation of the class, since you cannot overload the method by changing the return type, and the implementation will be violated. again he holds. An interface represents the behavior that a class MUST have.

Example:

The media operation in the collection is added in Java 8 (link: http://openjdk.java.net/jeps/107 ) to implement this forEach() method added to Iterable . Adding an abstract method to the Iterable interface will break all existing code, because each class must implement this method.

Solution to the problem, by default forEach() added to the Iterable interface,

 interface Iterable { default void forEach(Consumer<? super T> action) { for (T t : this) action.accept(t); } } 

Ref: Java 8: default method in interface

0
source share