One of the most useful features of Java 8 are the new default
methods on interfaces. There are essentially two reasons (there may be others) why they have been introduced:
- Providing actual default implementations. Example:
Iterator.remove()
- Allowing for JDK API evolution. Example:
Iterable.forEach()
From an API designer's perspective, I would have liked to be able to use other modifiers on interface methods, e.g. final
. This would be useful when adding convenience methods, preventing "accidental" overrides in implementing classes:
interface Sender {
// Convenience method to send an empty message
default final void send() {
send(null);
}
// Implementations should only implement this method
void send(String message);
}
The above is already common practice if Sender
were a class:
abstract class Sender {
// Convenience method to send an empty message
final void send() {
send(null);
}
// Implementations should only implement this method
abstract void send(String message);
}
Now, default
and final
are obviously contradicting keywords, but the default keyword itself would not have been strictly required, so I'm assuming that this contradiction is deliberate, to reflect the subtle differences between "class methods with body" (just methods) and "interface methods with body" (default methods), i.e. differences which I have not yet understood.
At some point of time, support for modifiers like static
and final
on interface methods was not yet fully explored, citing Brian Goetz:
The other part is how far we're going to go to support class-building tools in interfaces, such as final methods, private methods, protected methods, static methods, etc. The answer is: we don't know yet
Since that time in late 2011, obviously, support for static
methods in interfaces was added. Clearly, this added a lot of value to the JDK libraries themselves, such as with Comparator.comparing()
.
Question:
What is the reason final
(and also static final
) never made it to Java 8 interfaces?
final
prevents a method from being overridden, and seeing how you MUST override methods inherited from interfaces, I dont see why it would make sense to make it final. Unless it was to signify that the method is final AFTER overriding it once.. In that case, maybe there qas difficulties? If im not understanding this right, please let me kmow. Seems interesting – Aeschinesfinal
would have a use in preventing implementing classes from overriding the default implementation of an interface method. – Gmtdefault final
methods, and found out that they are not allowed:( I don't see strong arguments against the combination. – Greedefault
method asfinal
would imply that classes implementing two interfaces with the same method have no chance to disambiguate… On the other hand I don’t see any practical reason to forbid overriding a convenience method like the one in the example. It might not be intended to be overridden but being overridden does not hurt. Hey, I’m waiting for the next “I want treat interfaces like classes” discussion: “what about other visibility thanpublic
forinterface
methods?”. – Parlinfinal
. Unfortunately, my reference is not very up-to-date. There must've been more recent discussions with respect tofinal
. As far as multiple-inheritance conflicts are concerned, we already have those. Consider:interface A1 { void x(); }
andinterface A2 { int x(); }
. Orinterface B1 extends List<Object> {}
andinterface B2 extends List<String> {}
– Sexagesimalpublic interface A<T> { void add(T e); @safeVarArgs default final void addAll(T... elems) { for (T e : elems) add(e); }}
Because final and, consequently, @safeVarArgs is not allowed here, we get: "Type safety: Potential heap pollution via varargs parameter elems" – Reena