Do the default methods use Java 8 by default?

As a rule, Java source code was advanced. Prior to Java 8, as far as I know, both compiled classes and source files were compatible with later versions of JDK / JVM. [Update: this is incorrect, see comments re 'enum', etc. Below.] However, with the addition of default methods in Java 8, this no longer holds.

For example, the library I used has an implementation of java.util.List that includes List<V> sort() . This method returns a copy of the contents of the sorted list. This library, deployed as a jar file dependency, worked fine in a project built using JDK 1.8.

However, later I had to recompile the library using JDK 1.8 and I found that the library no longer compiles: the List -implementing class with its own sort() method now conflicts with the default Java 8 method java.util.List.sort() . The Java 8 method sort() by default 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 main question is:

  • Doesn't JDK 1.8 introduce 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 the default methods are designed and implemented? Is it documented somewhere?
  • Was the (admittedly slight) inconvenience of discount and benefits?

Below is an example of some code that compiles and runs under versions 1.7 and works 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 how this code is compiled (or not executed) and executed.

 > 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 
+54
java java-8 default-method forward-compatibility
Jul 02 '15 at 15:05
source share
5 answers

Doesn't JDK 1.8 introduce forward incompatibility for Java source code due to default methods?

Any new method in a superclass or interface may break compatibility. The default methods make it less likely that changing the interface will break compatibility. In the sense that default methods open the door for adding methods to interfaces, you can say that default methods may contribute to some broken compatibility.

Is this the first such advanced incompatible change?

Almost certainly not, since we were subclass classes from the standard library since Java 1.0.

Was this considered or discussed when the default methods were developed and implemented? Is it documented anywhere?

Yes, it has been reviewed. See Brian Goetz August 2010, “Developing an Interface Through Public Defender Techniques :

  1. Source compatibility

It is possible that this scheme may lead to incompatibility of the source to the extent that the library interfaces are modified to insert new methods that are incompatible with methods in existing classes. (For example, if a class has a float-value xyz () method and implements Collection, and we add the inty-value xyz () method to Collection, the existing class will no longer compile.)

Was the (admittedly slight) inconvenience of discount and benefits?

Prior to this, changing the interface will certainly violate compatibility. Now maybe. The transition from “definitely” to “can” can be seen positively or negatively. On the one hand, it becomes possible to add methods to interfaces. On the other hand, it opens the door to the incompatibility that you saw, not only with classes, but also with interfaces.

The advantages are higher than the inconvenience, however, as indicated at the top of Goetz’s paper:

  • Description of the problem

Once published, it is not possible to add methods to the interface without breaking existing implementations. The longer the time elapsed since the publication of the library, the greater the likelihood that this restriction will cause grief for those who accompany it.

Adding Java language closures to JDK 7 puts a strain on obsolete collection interfaces; One of the most significant benefits of closing is that it allows you to create more powerful libraries. It would be disappointing to add language features that will improve libraries and at the same time not expand the main libraries to take advantage of this opportunity.

+57
Jul 02 '15 at 15:25
source share
— -

Doesn't JDK 1.8 introduce forward incompatibility for Java source code due to default methods?

Yes, as you saw yourself.

Is this the first such forward incompatible change?

No. The Java 5 enum keyword also broke, because before that you could have variables with a name that would no longer compile in Java 5 +

Was this considered or discussed when the default methods are developed and implemented? Is it documented somewhere?

Yes Description of Orcale Java 8 source code incompatibility

Was (admittedly minor) inconvenience discounted compared to benefits?

Yes

+9
Jul 02 '15 at 15:12
source share

We can draw a parallel with the abstract class. An abstract class is intended to be a subclass so that abstract methods can be implemented. The abstract class itself contains specific methods that reference abstract methods. An abstract class can be developed freely by adding more specific methods; and this practice may violate subclasses.

Therefore, the exact problem you were talking about existed before Java8. The problem is much more apparent in the Collection APIs, because in the wild there are many subclasses.

While the leading motivation for the default method was to add some useful methods to existing Collection APIs without breaking subclasses, they had to show a lot of self-control, doing so too much for fear of subclassing. The default method is only added if absolutely necessary. The real question here is why List.sort is considered absolutely necessary. I think this is debatable.

Regardless of why the default method was introduced in 1st place, now it is a great tool for API designers, and we should treat it the same way as specific methods in abstract classes - they need to be carefully developed in advance; and new ones should be introduced with great care.

+3
Jul 02 '15 at 17:10
source share

Ironically, the default methods in the interfaces were applied, allowing existing libraries using these interfaces to not be interrupted, as well as introducing new functionality in the interfaces. (backward compatibility.)

Conflicts like sort are possible. Something needs to be paid for additional functionality. There is also something to research in your case (should you use the new functionality instead?).

The prospects for collaboration in Java are small, more in the typing system, which is constantly expanding. First with generic types and now with type inferences from functional interfaces. There were slight differences from version to version and from compiler to compiler.

+2
Jul 02 '15 at 15:32
source share

Reading this problem, I thought about solving it. The default methods have resolved backward compatibility issues, but compatibility issues will exist.
I think that instead of extending the existing classes in such cases, we can have interfaces specific to our application to add any desired behavior to our class. We can implement this interface and use it.

0
Feb 19 '17 at 7:39 on
source share



All Articles