Java's default interface methods collide with private instance methods? [duplicate] - java

This question already has answers here:
Do Java 8 default methods break source compatibility?
(5 answers)
Closed 6 years ago.
So as far as I know, the main idea behind the new interface default methods of Java 8 is to support Interface Evolution, i.e. extend an interface without braking existing implementations.
But what just occurred to me is that actually all these new default interface methods in the API hava a potential to break existing code. Namely, my implementation breaks if in a class I am implementing an interface X, and that interface X now has a new default method, which has the same signature than some private instance method of my class that already existed! Because in this case the compiler thinks I'm overriding the interface method while reducing its visibility, which is not allowed. So what if I have some implementation of Iterable and came up with some private forEach utility method? No when I update to Java 8 I can no longer compile.
Is it just me that is a bit shocked that Oracle actually released a not fully downwards-compatible API update? Has something like this ever happened in the past, that upgrading to a new compilation version can make some of your code no longer compile? Because if so I'm not aware of it. And what are your opinions of this?
edit: Oh, wait, what I said might have a flaw.. I mentioned the example with the Iterable#forEach method, but actually, this method takes some parameter that is also only introduced with Java 8. So there is no way that I could have defined such a method previously. Now, my next question: Could it be that ALL new default methods take some new type to guarantee they cannot collide with any pre-Java-8 existing instance method?
Cheers

Oracle had to choose between letting the language and APIs stagnate, or risk some backward incompatibilities. Yes, default methods can cause problems with existing extending interfaces and implementations. That's well known.
Has that already happened in the past? Yes: the JDBC interfaces have several times had new methods. assert was not a keyword but is one since Java 1.4, etc. enum was not a keyword before 1.5, etc.
EDIT
Examples of backward incompatibilities:
If you have an interface MyCollection extending Collection and having a method stream(), it will conflict with the new default stream() method, because it has the same signature but a different return type.
If you have an interface or class extending/implementing List<E> and having a method void sort(Comparator<E> c), it will conflict with the new default method void sort(Comparator<? super E>).

So what if I have some implementation of Iterable and came up with some private forEach utility method?
This isn't a problem because this would only overload the method. You can't have a forEach(Consumer) as this interface didn't exist before.
Is it just me that is a bit shocked that Oracle actually released a not fully downwards-compatible API update?
In each major version there is changes which could break backward compatibility, In Java 1.4, the keyword enum was added which meant if you have a variable called enum it would break.
Has something like this ever happened in the past, that upgrading to a new compilation version can make some of your code no longer compile?
Some APIs have changed, one of the oldest changes was a fix to String.hashCode() in Java 1.2.

In my opinion this Default method stuff should not be used by us Java developers. This was probably the only way to extend Existing Code without breaking the backward compatibilty.
But this is just my opinion.

Related

In Predicate interface why these methods negate() and() & or() are default. They can be easily overrided [duplicate]

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

default method in interface with difination [duplicate]

This question already has answers here:
What is the "default" implementation of method defined in an Interface?
(3 answers)
Closed 6 years ago.
I was studying lambada and there was a point which states that in java 8 we can declare a method with definition in interfaces like
interface Test {
default String method(){
return "string";
}
}
and as per specification we can use two methods with same signature but depends on programmer how he wants to use it?
Now the question is same task can be if achieved by using definition not declaration then what's the point of using default method?
like they behave same as regular method definition and programmer need to declare body and rest part?
what is the actual point as it seems a bit hard to grasp
thanks #ElliottFrisch and #kagemusha for hint after searching i got the answer
Why default methods?
List<?> list = …
list.forEach(…); // lambda code goes here
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.
So it’d be really frustrating if we have lambdas in Java 8 but couldn’t use those with the standard collections library since backwards compatibility can’t be sacrificed.
Due to the problem described above a new concept was introduced. Virtual extension methods, or, as they are often called, defender methods, can now be added to interfaces providing a default implementation of the declared behavior.
Simply speaking, interfaces in Java can now implement methods. 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 doesn’t seem to be the language feature that would be appropriate to use every day, but it seems to be essential for Java Collections API update to be able to use lambdas naturally.

Do Java 8 default methods break source compatibility?

It has generally been the case the Java source code has been forward compatible. Until Java 8, as far as I know, both compiled classes and source have been forward compatible with later JDK/JVM releases. [Update: this is not correct, see comments re 'enum', etc, below.] However, with the addition of default methods in Java 8 this appears to no longer be the case.
For example, a library I have been using has an implementation of java.util.List which includes a List<V> sort(). This method returns a copy of the contents of the list sorted. This library, deployed as a jar file dependency, worked fine in a project being built using JDK 1.8.
However, later I had occasion to recompile the library itself using JDK 1.8 and
I found the library no longer compiles: the List-implementing class with its own sort() method now conflicts with the Java 8 java.util.List.sort() default method. The Java 8 sort() default method sorts the list in place (returns void); my library's sort() method - since it returns a new sorted list - has an incompatible signature.
So my basic question is:
Doesn't JDK 1.8 introduce a forward incompatibility for Java source code due to default methods?
Also:
Is this the first such forward incompatible change?
Was this considered or discussed when default methods where designed and implemented? Is it documented anywhere?
Was the (admittedly small) inconvenience discounted versus the benefits?
The following is an example of some code that compiles and runs under 1.7 and
runs under 1.8 - but does not compile under 1.8:
import java.util.*;
public final class Sort8 {
public static void main(String[] args) {
SortableList<String> l = new SortableList<String>(Arrays.asList(args));
System.out.println("unsorted: "+l);
SortableList<String> s = l.sort(Collections.reverseOrder());
System.out.println("sorted : "+s);
}
public static class SortableList<V> extends ArrayList<V> {
public SortableList() { super(); }
public SortableList(Collection<? extends V> col) { super(col); }
public SortableList<V> sort(Comparator<? super V> cmp) {
SortableList<V> l = new SortableList<V>();
l.addAll(this);
Collections.sort(l, cmp);
return l;
}
}
}
The following shows this code being compiled (or failing to) and being run.
> c:\tools\jdk1.7.0_10\bin\javac Sort8.java
> c:\tools\jdk1.7.0_10\bin\java Sort8 this is a test
unsorted: [this, is, a, test]
sorted : [this, test, is, a]
> c:\tools\jdk1.8.0_05\bin\java Sort8 this is a test
unsorted: [this, is, a, test]
sorted : [this, test, is, a]
> del Sort8*.class
> c:\tools\jdk1.8.0_05\bin\javac Sort8.java
Sort8.java:46: error: sort(Comparator<? super V>) in SortableList cannot implement sort(Comparator<? super E>) in List
public SortableList<V> sort(Comparator<? super V> cmp) {
^
return type SortableList<V> is not compatible with void
where V,E are type-variables:
V extends Object declared in class SortableList
E extends Object declared in interface List
1 error
Doesn't JDK 1.8 introduce a forward incompatibility for Java source code due to default methods?
Any new method in a superclass or interface can break compatibility. Default methods make it less likely that a change in an interface will break compatibility. In the sense that default methods open the door to adding methods to interfaces, you could say that default methods may contribute to some broken compatibility.
Is this the first such forward incompatible change?
Almost certainly not, since we've been subclassing classes from the standard library since Java 1.0.
Was this considered or discussed when default methods were designed and implemented? Is it documented anywhere?
Yes, it was considered. See Brian Goetz's August 2010 paper "Interface evolution via “public defender” methods":
Source compatibility
It is possible that this scheme could introduce source incompatibilities to the extent that library interfaces are modified to insert new methods that are incompatible with methods in existing classes. (For example, if a class has a float-valued xyz() method and implements Collection, and we add an int-valued xyz() method to Collection, the existing class will no longer compile.)
Was the (admittedly small) inconvenience discounted versus the benefits?
Before, changing an interface would definitely break compatibility. Now, it might. Going from 'definitely' to 'might' can be seen either positively or negatively. On the one hand, it makes it feasible to add methods to interfaces. On the other hand, it opens the door to the kind of incompatibility you saw, not just with classes, but with interfaces too.
The benefits are larger than the inconveniences, though, as cited at the top of Goetz's paper:
Problem statement
Once published, it is impossible to add methods to an interface without breaking existing implementations. The longer the time since a library has been published, the more likely it is that this restriction will cause grief for its maintainers.
The addition of closures to the Java language in JDK 7 place additional stress on the aging Collection interfaces; one of the most significant benefits of closures is that it enables the development of more powerful libraries. It would be disappointing to add a language feature that enables better libraries while at the same time not extending the core libraries to take advantage of that feature.
Doesn't JDK 1.8 introduce a forward incompatibility for Java source code due to default methods?
Yes as you've seen your self.
Is this the first such forward incompatible change?
No. Java 5 enumkeyword was also breaking because before that you could have variables named that which would no longer compile in Java 5 +
Was this considered or discussed when default methods where designed and implemented? Is it documented anywhere?
Yes Orcale Java 8 source incompatibility description
Was the (admittedly small) inconvenience discounted versus the benefits?
Yes
We can draw a parallel with abstract class. An abstract class is intended to be subclassed so that the abstract methods can be implemented. The abstract class itself contains concrete methods that invoke the abstract methods. The abstract class is free to evolve by adding more concrete methods; and this practice may break subclasses.
Therefore the exact problem you described existed even before Java8. The problem is much more manifested on Collection APIs because there are a lot of subclasses out in the wild.
While the leading motivation of default method was to add some useful methods to existing Collection APIs without breaking subclasses, they had to exercise great self-control of doing it too much, for fear of breaking subclasses. A default method is added only if it's absolutely necessary. The real question here is, why List.sort is considered absolutely necessary. I think that is debatable.
Regardless of why default method was introduced in the 1st place, it is now a great tool for API designers, and we ought to treat it the same as concrete methods in abstract classes - they need to be designed carefully up front; and new ones must be introduced with great caution.
Ironically default methods in interfaces were introduced to allow existing libraries using those interfaces not to break, while introducing massive new functionality in the interfaces. (backward compatibility.)
Conflicts like that sort method might arise. Something to pay for the extra functionality. In your case also something to investigate (should new functionality be used instead?).
Java forward compatibility breaks are little, more in its typing system, which was constantly enlarged. First with generic types and now with inferred types from functional interfaces. From version to version and from compiler to compiler there were slight differences.
Reading this issue, I was thinking of its solution.
Default methods have solved the backward compatibility problems but forward compatibility issues will exist.
I think instead of extending existing classes, in such cases, we can have our application specific interfaces to add some desired behaviour to our class. We can implement this application specific interface and use it.

What is the reason of Java 8 default method on interfaces? [duplicate]

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

Preferences of abstract classes over interfaces in Java 8

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

Categories

Resources