Learning java 8 default methods .
This link like any other resource on internet says
In ‘the strictest sense’, Default methods are a step backwards because
they allow you to ‘pollute’ your interfaces with code. But they
provide the most elegant and practical way to allow backwards
compatibility. It made it much easier for Oracle to update all the
Collections classes and for you to retrofit your existing code for
Lambda.
My understanding is that java 8 dev/designers provided the default method in interfaces so that all implementing class does not have to unnecessarily
override same behavior, hence provide backward compatibility. For example :- if ForEach method would not have been default method, every collection implementing class had to implement it. Agreed .
To overcome that we could have had one class providing implementation of these default methods and then implementing class like arraylist etc could
have extended that. This way we could have statisfy both java fundamentals i.e reusability and abstraction i.e keeping the interface pollution less
I am sure java 8 dev/designer have already thought about this as they are much more learned and i am missing something here. Can someone help here so that we developers can also be on top of it as this major change?
Before Java 8, interfaces could have only abstract methods. The implementation of these methods has to be provided in a separate class. So, if a new method is to be added in an interface then its implementation code has to be provided in the class implementing the same interface.
To overcome this issue, Java 8 has introduced the concept of default methods which allow the interfaces to have methods with implementation without affecting the classes that implement the interface.
The default methods were introduced to provide backward comparability so that existing interfaces can use the lambda expressions without implementing the methods in the implementation class. Default methods are also known as defender methods or virtual extension methods.
To overcome that we could have had one class providing implementation of these default methods and then implementing class like arraylist etc could have extended that.
Your suggestion would work only for standard JDK classes (since they usually extends some base classes such as AbstractCollection and AbstractList, were the implementation of the new methods can be added).
What about custom classes that implement JDK interfaces? If, for example, you have a class that implements List but doesn't extend some JDK List implementation, you should be able to switch to Java 8 without having to implement new methods in your class.
With default implementations of new methods in the List interface, you don't have to touch your custom class. You can later add a custom implementation to those methods if you are not satisfied by the default implementation.
If there is a requirement to add new method to an interface, clients which use existing interface will be broken as classes needs to implement all methods in the interface.
In this scenario, default and static methods can be used. These methods can have body and clients don't need to implement them, so existing implementations work without any changes.
For example, if you want to enhance interfaces to add methods which accept lambda expressions, you can use default methods.
Related
Java 8 has included a new feature called Defender methods which allows creation of default method implementation in interface.
Now first of all this is a huge paradigm shift for all condensed programmers in Java. I viewed a JavaOne 13 presentation given by Brian Goetz where he was discussing about the new stream() and parallelStream() implementations in Collections library.
For adding new methods in Collection interface, they could not have just added a new method without breaking the previous versions. So he told that for catering this a new feature of Default methods was added.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
Now my question is basically that are default methods just helpful when needed to add new methods to interface without breaking client code? Or are there some other uses to it too?
Besides having the possibility of adding methods to the interface in future versions, there is the important point of allowing an interface to stay a functional interface even if it has more than one method.
A functional interface has only one non-default abstract method which can be implemented via a lambda expression. One example is the Predicate interface which has only one abstract method (test) while providing default methods for negating a Predicate or combining it with another Predicate. Without default methods these methods had to be provided in another utility class like the pre-Java 8 Collections class (as you don’t want to give up the possibility of lambda implementations for such an interface).
As you said, the main motivation was allowing the evolution of existing interfaces.
However there are reasons why you'd want to use them in brand new interfaces as well:
One such reason is methods that can easily be implemented using the other (non-default) methods of the interface. Using default methods for this reduces the need for Foo-interface/AbstractFoo-base-implementation combinations (see AbstractList for example).
While this does not create an entirely new field, it means that you can have end-user-friendly interfaces (with lots of useful methods), still keeping it simple to implement.
There was a problem with interfaces that they were not open to extension, which means if there was a need to add new method to an interface it would have broken the existing implementation of these interfaces. Thus it was imperative that all the classes implementing that interface had to provide implementation for the newly added method, even if the method was not needed. Thus interfaces were not easy to evolve.
One example that comes to mind is Java MapReduce API for Hadoop, which was changed in 0.20.0 release to favour abstract classes over interfaces, since they are easier to evolve. Which means, a new method can be added to abstract class (with default implementation), with out breaking old implementations of the class.
With the release of Java 8, it is now possible to add default method in interfaces also, thus making them easier to evolve too. With the addition of default method to an interface, addition of new method, to even an interface will not break the pre-existing code.
For adding new methods in Collection interface, they could not have
just added a new method without breaking the previous versions.
Yes they could have done this but Let's think from API designer perspective for e.g. Collection Library is used by some libraries like apache-commons, guava etc and which instead are used by many java projects. Now imagine just by adding one new method in Collection interface will break entire chain of projects.
Now my question is basically that are default methods just helpful
when needed to add new methods to interface without breaking client
code? Or are there some other uses to it too?
Motivation/Need for Default Methods
API Evolution in compatible way
The initial purpose of introducing default methods was to make collections library backward compatible. This library was modelled as a deep hierarchy of interfaces, including prominent members such as Collection, List, Map, and Set. They needed to be enriched to make lambdas truly useful for everyday programming.
To make Collections library lambda rich, java architects could have
refactored them to support lambda but it was a far from a good
solution as it will break all the all existing Java deployments and
countless 3rd party libraries extending the Collections hierarchy
Instead java architects thought to introduce default methods capabilities for backward compatibility.
Use cases of Default Methods
One important use case is to aid functional thinking in java. A functional interface with default methods is a pure behaviour-only construct. It cannot hold state. This aligns your thinking with functional programming and allows you to take advantage of what the programming model has to offer
Optional Methods : There are classes in java that implement an interface but leave empty method implementations for e.g. Iterator interface. It defines hasNext and next but also the remove method. Prior to Java8 remove was ignored because the user didn't want to use that capablity. Therefore many classes implementing Iterator interface would have empty implementation of for remove which is unnecessary boiler plate code. With default methods we can provide a default implementation for such methods, so concrete classes don't need to explicitly provide an empty implementation.
Default methods helps in resolving Multiple inheritance of behaviour in java. Before Java8, there was support for Multiple inheritance of Type only and now with the help of default methods we can have multiple inheritance of behaviour.
For e.g.
Java 8 has three rules for resolving conflicts brought upon by
multiple inheritance when ambiguous:
First, an explicit method declaration in the class or a superclass takes priority over any default method declaration.
Otherwise, the method with the same signature in the most specific default providing interface is selected.
Finally, if there is still conflict, you have to explicitly override the default methods and choose which one your class should choose.
In Conclusion Default methods offer a brand new way to design objects.
References :
Java8 In Action
Functional Java: A Guide to Lambdas and Functional Programming in Java 8
default methods made possible the functional programming concept. For functional programming type code we need only one abstract method .
Also adding an method in interface will not made it compulsory for all the classes implementing an interface. Simplified the coding practise
This question already has answers here:
When to use: Java 8+ interface default method, vs. abstract method
(16 answers)
Closed 7 years ago.
Why We need Defender methods in interfaces in java 8 as we already have abstract classes.I found various answers on internet like:
To add external functionality
But Abstract class is for partial Abstraction where as our interface is actually a pure abstract class so why their is a default method inside an interface?
The problem with sharing functionality by placing it in an abstract base class is that a class can derive from exactly one base class. This is a limitation in cases when you would like to inherit functionality from more than one base.
Sharing functionality through an abstract base class may also become a problem when you need to implement an interface from a class that already has a base class. In this case you cannot derive your new class at all, because you must pick one of the two bases, when presumably you want both.
Default methods solve this problem with elegance: placing your common implementation into the default method allows you to share the code without limitations.
You can think of the main difference between default methods and inheriting an abstract class as the difference between sharing functionality horizontally across siblings that implement the same interface, or vertically among children that inherit from the same base class.
Here is an examoke: consider an interface that looks like ResultSet of JDBC, which has two ways of accessing the same column - by name and by index. The interface could be coded up like this:
interface ResultSet2 {
int findColumn(String columnLabel);
String getString(int index);
long getLong(int index);
default long getLong(String columnLabel) {
return getLong(findColumn(columnLabel));
}
default String getString(String columnLabel) {
return getString(findColumn(columnLabel));
}
}
Anyone implementing ResultSet2 would have to implement three methods, and get the remaining two for free. They would have an option to provide an alternative implementation, but that would be optional.
The main reason behind defender methods is to be able to extend long-existing interfaces with new functionality, without breaking the existing code. Particulary with Java 8 lamba expressions they introduced a lot of new methods on collection interfaces, like Iterable.forEach. With providing default methods, existing classes implementing the Iterable interface dont have to be altered to use in Java 8 environment.
The original intent was to compete with C#'s extension methods. Given core methods of an interface, e.g. get(), set() in List, extention methods (e.g. sort()) can be defined and implemented.
Java guys argued that it would be better to declare such methods on the interface itself, rather than in external places; so that the methods could be overridden by subtypes, providing optimal implementations per subtype. (They also argued that such methods should be controlled by the interface authors; this is rather a soft point)
While default methods can be added to existing interfaces, it is very risky of breaking existing 3rd party subtypes, particularly for very old types like List with lots of subtypes in the wild. Therefore very few default methods were added to existing core Java APIs. See this question.
For new interfaces, default method is a very valuable tool for API designers. You can add a lot of convenience methods to an interface, for example, Function.compose(). Subtypes only need to implement abstract/core methods, not default methods (but they can if they want to).
I disagree with the idea that default methods can "evolve" interfaces. They do not change the core semantics of an interface, they are just convenience methods (in the form of instance method).
And default methods should be carefully designed up-front when the interface is designed; as said, it is very risky to add default methods afterwards.
C#'s extension method allows 3rd party to add convenience methods; this is very nice, and there is no reason why Java couldn't introduce something similar in future.
Java 8 has included a new feature called Defender methods which allows creation of default method implementation in interface.
Now first of all this is a huge paradigm shift for all condensed programmers in Java. I viewed a JavaOne 13 presentation given by Brian Goetz where he was discussing about the new stream() and parallelStream() implementations in Collections library.
For adding new methods in Collection interface, they could not have just added a new method without breaking the previous versions. So he told that for catering this a new feature of Default methods was added.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
Now my question is basically that are default methods just helpful when needed to add new methods to interface without breaking client code? Or are there some other uses to it too?
Besides having the possibility of adding methods to the interface in future versions, there is the important point of allowing an interface to stay a functional interface even if it has more than one method.
A functional interface has only one non-default abstract method which can be implemented via a lambda expression. One example is the Predicate interface which has only one abstract method (test) while providing default methods for negating a Predicate or combining it with another Predicate. Without default methods these methods had to be provided in another utility class like the pre-Java 8 Collections class (as you don’t want to give up the possibility of lambda implementations for such an interface).
As you said, the main motivation was allowing the evolution of existing interfaces.
However there are reasons why you'd want to use them in brand new interfaces as well:
One such reason is methods that can easily be implemented using the other (non-default) methods of the interface. Using default methods for this reduces the need for Foo-interface/AbstractFoo-base-implementation combinations (see AbstractList for example).
While this does not create an entirely new field, it means that you can have end-user-friendly interfaces (with lots of useful methods), still keeping it simple to implement.
There was a problem with interfaces that they were not open to extension, which means if there was a need to add new method to an interface it would have broken the existing implementation of these interfaces. Thus it was imperative that all the classes implementing that interface had to provide implementation for the newly added method, even if the method was not needed. Thus interfaces were not easy to evolve.
One example that comes to mind is Java MapReduce API for Hadoop, which was changed in 0.20.0 release to favour abstract classes over interfaces, since they are easier to evolve. Which means, a new method can be added to abstract class (with default implementation), with out breaking old implementations of the class.
With the release of Java 8, it is now possible to add default method in interfaces also, thus making them easier to evolve too. With the addition of default method to an interface, addition of new method, to even an interface will not break the pre-existing code.
For adding new methods in Collection interface, they could not have
just added a new method without breaking the previous versions.
Yes they could have done this but Let's think from API designer perspective for e.g. Collection Library is used by some libraries like apache-commons, guava etc and which instead are used by many java projects. Now imagine just by adding one new method in Collection interface will break entire chain of projects.
Now my question is basically that are default methods just helpful
when needed to add new methods to interface without breaking client
code? Or are there some other uses to it too?
Motivation/Need for Default Methods
API Evolution in compatible way
The initial purpose of introducing default methods was to make collections library backward compatible. This library was modelled as a deep hierarchy of interfaces, including prominent members such as Collection, List, Map, and Set. They needed to be enriched to make lambdas truly useful for everyday programming.
To make Collections library lambda rich, java architects could have
refactored them to support lambda but it was a far from a good
solution as it will break all the all existing Java deployments and
countless 3rd party libraries extending the Collections hierarchy
Instead java architects thought to introduce default methods capabilities for backward compatibility.
Use cases of Default Methods
One important use case is to aid functional thinking in java. A functional interface with default methods is a pure behaviour-only construct. It cannot hold state. This aligns your thinking with functional programming and allows you to take advantage of what the programming model has to offer
Optional Methods : There are classes in java that implement an interface but leave empty method implementations for e.g. Iterator interface. It defines hasNext and next but also the remove method. Prior to Java8 remove was ignored because the user didn't want to use that capablity. Therefore many classes implementing Iterator interface would have empty implementation of for remove which is unnecessary boiler plate code. With default methods we can provide a default implementation for such methods, so concrete classes don't need to explicitly provide an empty implementation.
Default methods helps in resolving Multiple inheritance of behaviour in java. Before Java8, there was support for Multiple inheritance of Type only and now with the help of default methods we can have multiple inheritance of behaviour.
For e.g.
Java 8 has three rules for resolving conflicts brought upon by
multiple inheritance when ambiguous:
First, an explicit method declaration in the class or a superclass takes priority over any default method declaration.
Otherwise, the method with the same signature in the most specific default providing interface is selected.
Finally, if there is still conflict, you have to explicitly override the default methods and choose which one your class should choose.
In Conclusion Default methods offer a brand new way to design objects.
References :
Java8 In Action
Functional Java: A Guide to Lambdas and Functional Programming in Java 8
default methods made possible the functional programming concept. For functional programming type code we need only one abstract method .
Also adding an method in interface will not made it compulsory for all the classes implementing an interface. Simplified the coding practise
Now, we know that Java 8 has introduced default and static methods in interfaces.
Interfaces were originally introduced in Java to avoid the diamond problem that occurred in C++, in multiple inheritance.
But along with the introduction of default methods in interfaces in Java 8, now, Java has also introduced the diamond problem, which it avoided in previous versions.
Default methods are not compulsorily needed to be overridden.
But when a diamond problemoccurs using interfaces, the class implementing those interfaces must override the default methods.
So now, I have three questions in my mind:
Why is the need to have default methods?
Couldn't we have multiple inheritance through classes itself, in place of having default methods in interfaces?
And what was the need to avoid diamond problem in the previous versions, if they had to introduce it in Java 8 anyway?
Any good explanation or any link for explanation?
PS I did not find any link on the internet containing any good article on this.
All they said is that an abstract class gives you more concreteness.
As in, abstract classes can have constructors but interfaces cannot.
So again, I want to know, If abstract classes are more concrete, and can have constructors,
and anyways Java has introduced the diamond problem, why should we have interfaces now? Wouldn't abstract classes be good enough as a stand alone for multiple inheritance?
No, it didn't reintroduce the diamond problem, because interfaces still can't have any state, and default methods may not be final.
So, when you choose to implement two interfaces, you still have all the freedom you want to implement the default methods, either by choosing one of the provided default implementations, or by providing your own implementation. But you'll never have a problem of inheriting conflicting state from both interfaces, or inheriting two different final methods and not being able to resolve the conflict.
So, here are the answers to your questions:
To be able to introduce new methods in existing interfaces without breaking backward compatibility: existing implementations will automatically implement these methods since their implementation is in the base interface.
No, because that would introduce a diamond problem.
Irrelevant
Regarding Point 1:
In order to support lambda expression for all collection classes, like forEach method, it was necessary to add something which will have backward compatibility.
see this video for detail Lambda Peak Under the hood
Default methods make it possible to enhance an existing interface while providing binary compatibility with former versions of the interface to existing users.
See more here https://docs.oracle.com/javase/tutorial/java/IandI/nogrow.html
I am looking for a java equivalent to the C# extension methods feature. Now I have been reading about Java 8's default methods, but as far as I can see, I can only add these to interfaces...
...is there any language feature that will allow me to write an extension method for a final class that doesn't implement an interface? (I'd rather not have to wrap it...)
Java doesn't have extension methods. Default methods are not extension methods. Let's look at each feature.
Default methods
Both Java and C# support this feature
Problems solved:
Many objects may implement the same interface and all of them may use the same implementation for a method. A base class could solve this issue but only if the interface implementors don't already have a base class as neither java nor C# support multiple inheritance.
An API would like to add a method to an interface without breaking the API consumers. Adding a method with a default implementation solves this.
Java's or C#'s default methods are a feature to add a default implementation to an interface. So objects that extend an interface don't have to implement the method, they could just use the default method.
interface IA { default public int AddOne(int i) { return i + 1; } }
Any object that implements IA doesn't have to implement AddOne because there is a default method that would be used.
public class MyClass implements IA { /* No AddOne implementation needed */ }
C# now has this feature in C# 8 (or .Net 5)
C#'s Extension Method
Problems solved:
Ability to add methods to sealed classes.
Ability to add methods to classes from third-party libraries without forcing inheritance.
Ability to add methods to model classes in environments where methods in model classes are not allowed for convention reasons.
The ability for IntelliSense to present these methods to you.
Example: The type string is a sealed class in C#. You cannot inherit from string as it is sealed. But you can add methods you can call from a string.
var a = "mystring";
a.MyExtensionMethed()
Java lacks this feature and would be greatly improved by adding this feature.
Conclusion
There is nothing even similar about Java's default methods and C#'s extension method features. They are completely different and solve completely different problems.
C# extension methods are static and use-site, whereas Java's default methods are virtual and declaration-site.
What I believe you are hoping for is the ability to "monkey-patch" a method into a class you do not control, but Java does not give you that (by design; it was considered and rejected.)
Another benefit of default methods over the C# approach is that they are reflectively discoverable, and in fact from the outside, don't look any different from "regular" interface methods.
One advantage of C#'s extension methods over Java's default methods is that with C#'s reified generics, extension methods are injected into types, not classes, so you can inject a sum() method into List<int>.
Above all, the main philosophical difference between Java's default methods and C#'s extension methods is that C# lets you inject methods into types you do not control (which is surely convenient for developers), whereas Java's extension methods are a first-class part of the API in which they appear (they are declared in the interface, they are reflectively discoverable, etc.) This reflects several design principles; library developers should be able to maintain control of their APIs, and library use should be transparent -- calling method x() on type Y should mean the same thing everywhere.
C# extension methods are just syntactic sugar for static methods that take the extended type as first argument. Java default methods are something completely different. To mimic C# extension methods, just write usual static methods. You will not have the syntatic sugar, however; Java does not have this feature.
Java default methods are real virtual methods. For example, they can be overridden. Consider a class X inheriting from an interface I that declares a default foo() method. If X or any of its super classes declares no own foo() method, then X will get the foo() implementation of I. Now, a subclass Y of X can override X.foo() like a usual method. Thus, default methods are not only syntactic sugar. They are real extensions of the method overriding and inheritance mechanism that cannot be mimicked by other language features.
Default methods even require special VM support, so they are not even a compiler only feature: During class loading, the hierarchy of a class has to be checked to determine which default methods it will inherit. Thus, this decision is made at runtime, not at compile time. The cool thing about it is that you do not have to recompile a class when an interface it inherits gets a new default method: The VM will, at class load time, assign that new method to it.
It is possible to have extension methods with some tricks.
You may give a try to Lombok or XTend. Although extension methods don't come with the out of the box Java implementation, both Lombok and XTend offers a fully working solution.
Lombok is a simple standalone code processing framework, which makes most of the criticized Java specific hassle less painful, including extension methods:
https://projectlombok.org/features/experimental/ExtensionMethod.html
Xtend http://www.eclipse.org/xtend/ goes a few lightyears forward, and implements a language which is a combination of the best parts of modern languages such as Scala on top of Java and Java type system. This allows implementing some classes in Xtend and others in Java within the same project. The Xtend code complies to valid Java code, so no JVM magic happens under the hood. On the other hand, it is a little too much if you have only extension methods missing.
JPropel https://github.com/nicholas22/jpropel-light implements LINQ style extension methods in Java using Lombok. It may worth of a peek :)