0

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

user3237736
  • 845
  • 1
  • 9
  • 24
  • The compiler disallows interfaces to declare `default` methods with the same signature as a non-private method in `Object`: [JLS 9.4.1.2](https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.4.1.2). `Object` is special. – rgettman Feb 25 '16 at 19:02

3 Answers3

4

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

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
2

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.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
-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.

Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82