0

As the official statement about virtual extension methods (default methods) states:

The purpose of virtual extension methods (default methods) is to enable interfaces to be evolved in a compatible manner after their initial publication.”

Can I see some good examples in the JDK for this in action? So far I've found in the java.util.Collection interface and several others but it would be nice to have a more thorough list.

edit: I was not looking for whether using default methods are safe or not (since I've already read the question which is linked). I was looking for practical examples in the JDK.

Adam Arold
  • 29,285
  • 22
  • 112
  • 207
  • the best thing to do with them is to never use them... IOW there are no good examples of their use as their use is an antipattern. They were included solely to allow hacking in the lambda functionality without causing code incompatibility with existing Java code. – jwenting Aug 03 '15 at 12:05
  • 1
    Who said that their usage is an antipattern? You? Why using them is an antipattern? Since the language designer himself said that there are valid use cases for their usage they **are not** an antipattern and your words are hollow to me. – Adam Arold Aug 03 '15 at 12:07
  • The main purpose of default methods is to allow interface evolution, as you've already seen in `java.util.Collection`. There really isn't much more to it. – biziclop Aug 03 '15 at 12:17
  • 2
    http://stackoverflow.com/questions/28681737/java-8-default-methods-as-traits-safe – Adam Arold Aug 03 '15 at 12:23
  • @AdamArold you're mixing implementation details inside an interface definition. If that's not an antipattern I don't know what is... – jwenting Aug 03 '15 at 13:18
  • 1
    I still trust Brian Goetz instead. – Adam Arold Aug 03 '15 at 14:00
  • 1
    See: http://stackoverflow.com/questions/28681737/java-8-default-methods-as-traits-safe/28684917#28684917 – Brian Goetz Aug 03 '15 at 14:25
  • 1
    Yea, that is the answer I linked as well. And it states 4 valid use cases for default methods. – Adam Arold Aug 03 '15 at 14:46

1 Answers1

3

There are several places in standard classes which I know beyond collections:

  • Java SQL API has interface enhancements. ResultSet.updateObject, PreparedStatement.setObject, PreparedStatement.executeLargeUpdate (differs from executeUpdate returning long instead of int) and so on were added. By default they throw UnsupportedOperationException or some other exception. This is "interface evolution": a way to enhance older interface with new features.

  • Functions in java.util.function have default methods which allow to combine them. These methods are not expected to be redefined as functional interfaces are mostly intended to work with lambdas. These methods are just for convenience. This is not the "interface evolution" as these interfaces appeared first in Java 8. However were these methods non-default, you would not be able to express these interfaces with lambdas as single-abstract-method rule would be violated.

  • Several default methods added to java.util.Comparator: reversed(), thenComparing() and so on. Also default implementations are fine and usually not intended to be replaced. This is similar to functions, but Comparator interface existed before, so it's also kind of interface evolution.

  • The java.util.Spliterator interface has default methods. This is actually good example as default methods of different purpose are shown here. The getComparator() method by default throws, but it must be overridden if spliterator uses SORTED characteristic. The hasCharacteristic() method is just a convenience way to use non-default characteristics() method and probably should never be redefined. The forEachRemaining() default implementation will always work correctly, but overriding it may produce much more effective result for some spliterators. The getExactSizeIfKnown() default implementation is also always correct and usually no need to redefine it. However if your spliterator is never sized, you can optimize it a little, just returning -1.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • 2
    And an even more obvious example: Iterator.remove(). Iterator acqulred a default in Java 8 that throws UOE, effectively making the method optional (99% of non-JDK implementations just throw UOE anyway.) – Brian Goetz Aug 03 '15 at 14:26
  • 1
    @BrianGoetz, I wanted to mention this, but for some reason I thought that "several others" mentioned by OP include `Iterator`. Probably it's just my imagination though. – Tagir Valeev Aug 03 '15 at 16:41
  • 1
    I would point out that, in hindsight, the examples you cite in the second bullet (composing functions with other functions) turn out to be flawed if these functional interfaces might be extended (and they are, `BinaryOperator` extends `Function`). We might even deprecate these specific default methods. (Like any tool, users can make mistakes, and sometimes even experts do.) – Brian Goetz Sep 12 '20 at 14:56