Java 8 introduced default methods on interfaces to provide backwards compatibility for implementations of the collections interfaces, to avoid MethodNotFound errors on legacy libraries.
i.e A library with a java 7 implementation of List will not implement the stream() method. If java 8 code uses this library the default implementation provides a fall-back.
What I see in practice is many developers are using this feature over-zealously to emulate mix-ins and multiple inheritance in a style that resembles scala traits.
One of my concerns is that this style of programming blurs the line between interfaces (i.e. contracts) and their implementations and therefore introduces hidden tight coupling and violates inversion of control, forcing me to use back doors to test the code by overriding the default implementations in my unit tests, to suppress behavior that should not be present at the unit test level.
Is this use of default methods an anti-pattern, or am I alone in suspecting this?
From Oracle's documentation: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
I would assume that the emphasis is on compatibility in the above (though, let's face it, the above is pretty vague). There's no apparent compilation "restriction" to using defaults like a trait, and I note that a number of tutorials are out there espousing the use of
default
in that context (for better or worse). There are certainly gotchas however (they aren't equivalent to Scala's traits for example). See @brian-goetz's answer in the below for a more comprehensive dscussion:Java 8 default methods as traits : safe?
In short: how you use
default
is going to shape whether it's ultimately an anti-pattern or not. Ergo, to answer your question, it probably is used over-zealously by some.