Related
Java 8 gave us many fun ways to use functional interfaces and with them a new annotation: #FunctionalInterface. Its job is to tell the compiler to yell at us if we fail to stick to the rules of a functional interface (only one abstract method that needs overriding please).
There are 43 interfaces in the java.util.function package with this annotation. A search of jdk.1.8.0/src for #FunctionalInterface only turns up 57 hits. Why are the other interfaces (such as AutoCloseable) that could have added #FunctionalInterface still missing it?
There is a bit of a vague hint in the annotations documentation:
"An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface"
Is there any good reason NOT to intend that an interface I've designed (that may simply happen to be a functional interface) not be used as one? Is leaving it off an indication of anything besides not realizing it could have been added?
Isn't adding abstract methods to any published interface going to screw anyone implementing it, functional or not? I feel cynical assuming they just didn't bother to hunt them all down but what other explanation is there?
Update: After looking over "Should 'Comparable' be a 'Functional interface'?" I find I still have nagging questions. When a Single Method Interface and a Functional Interface are structurally identical what's left to be different? Is the difference simply the names? Comparable and Comparator are close enough to the same semantically. Turns out they are different structurally though so still not the best example...
Is there a case when an SMI is structurally fine to use as a Functional Interface but still discouraged over the semantic meaning of the name of the interface and the method? Or perhaps the contract implied by the Javadocs?
Well, an annotation documenting an intention would be useless if you assume that there is always that intention given.
You named the example AutoCloseable which is obviously not intended to be implemented as a function as there’s Runnable which is much more convenient for a function with a ()->void signature. It’s intended that a class implementing AutoCloseable manages an external resource which anonymous classes implemented via lambda expression don’t do.
A clearer example is Comparable, an interface not only not intended to be implemented as a lambda expression, it’s impossible to implement it correctly using a lambda expression.
Possible reasons for not marking an interface with #FunctionalInterface by example:
The interface has programming language semantics, e.g. AutoClosable or Iterable (that’s unlikely to happen for your own interfaces)
It’s not expected that the interface has arbitrary implementations and/or is more an identifier than the actual implementation, e.g. java.net.ProtocolFamily, or java.lang.reflect.GenericArrayType (Note that the latter would also inherit a default implementation for getTypeName() being useless for lambda implementations as relying on toString())
The instances of this interface should have an identity, e.g. java.net.ProtocolFamily, java.nio.file.WatchEvent.Modifier, etc. Note that these are typically implemented by an enum
Another example is java.time.chrono.Era which happens to have only a single abstract method but its specification says “Instances of Era may be compared using the == operator.”
The interface is intended to alter the behavior of an operation for which an implementation of the interface without inheriting/implementing anything else makes no sense, e.g. java.rmi.server.Unreferenced
It’s an abstraction of common operations of classes which should have more than just these operations, e.g. java.io.Closeable, java.io.Flushable, java.lang.Readable
The expected inheritance is part of the contract and forbids lambda expression implementations, e.g. in java.awt: ActiveEvent should be implemented by an AWTEvent, PrinterGraphics by a Graphics, the same applies to java.awt.print.PrinterGraphics (hey, two interfaces for exactly the same thing…), wheras javax.print.FlavorException should be implemented by a javax.print.PrintException subclass
I don’t know whether the various event listener interfaces aren’t marked with #FunctionalInterface for symmetry with other multi-method event listener that can’t be functional interfaces, but actually event listeners are good candidates for lambda expressions. If you want remove a listener at a later time, you have to store the instance but that’s not different to, e.g. inner class listener implementations.
The library maintainer has a large codebase with more than 200 candidate types and not the resources to discuss for every interface whether it should be annotated and hence focuses on the primary candidates for being used in a functional context. I’m sure, that, e.g. java.io.ObjectInputValidation, java.lang.reflect.InvocationHandler, juc RejectedExecutionHandler & ThreadFactory wouldn’t be bad as #FunctionalInterface but I have no idea whether, e.g. java.security.spec.ECField makes a good candidate. The more general the library is, the more likely users of the library will be able to answer that question for a particular interface they are interested in but it would be unfair to insist on the library maintainer to answer it for all interfaces.
In this context it makes more sense to see the presence of a #FunctionalInterface as a message that an interface is definitely intended to be usable together with lambda expressions than to treat the absence of the annotation as an indicator for it’s being not intended to be used this way. This is exactly like the compiler handles it, you can implement every single abstract method interface using a lambda expression, but when the annotation is present it will ensure that you can use this interface in this way.
Planned expansion. Just because an interface matches the requirements of an SMI now doesn't mean that expansion isn't needed later.
In java 8, functional interface is an interface having exactly one abstract method called functional method to which the lambda expression’s parameter and return types are matched.
The java.util.function contains general purpose functional interfaces used by JDK and also available for end users. While they are not the complete set of funtional interfaces to which lambda expressions might be applicable, but they provide enough to cover common requirements. You are free to create your own functional interfaces whenever existing set are not enough.
There are many such interfaces available which deserves to be designated as functional interface but java.util.function package already provides functional interfaces for our almost all purposes.
For example look into following code.
public interface Comparable<T> {
public int compareTo(T o);
}
#FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}
public static void main(String[] args){
ToIntFunction<String> f = str -> Integer.parseInt(str);
Comparable<String> c = str -> Integer.parseInt(str);
}
Comparable can also take an object and derive some int type value but there is a more general dedicated interface ToIntFunction is provided to perform this task. There is no such hard rule that all the deserving interfaces should be annotated with #FunctionalInterface but to gain the advantage of lambda feature, the interface should fulfill all criterias defined by FunctionalInterface.
Default methods are a nice new tool in our Java toolbox. However, I tried to write an interface that defines a default version of the toString method. Java tells me that this is forbidden, since methods declared in java.lang.Object may not be defaulted. Why is this the case?
I know that there is the "base class always wins" rule, so by default (pun ;), any default implementation of an Object method would be overwritten by the method from Object anyway. However, I see no reason why there shouldn't be an exception for methods from Object in the spec. Especially for toString it might be very useful to have a default implementation.
So, what is the reason why Java designers decided to not allow default methods overriding methods from Object?
This is yet another of those language design issues that seems "obviously a good idea" until you start digging and you realize that its actually a bad idea.
This mail has a lot on the subject (and on other subjects too.) There were several design forces that converged to bring us to the current design:
The desire to keep the inheritance model simple;
The fact that once you look past the obvious examples (e.g., turning AbstractList into an interface), you realize that inheriting equals/hashCode/toString is strongly tied to single inheritance and state, and interfaces are multiply inherited and stateless;
That it potentially opened the door to some surprising behaviors.
You've already touched on the "keep it simple" goal; the inheritance and conflict-resolution rules are designed to be very simple (classes win over interfaces, derived interfaces win over superinterfaces, and any other conflicts are resolved by the implementing class.) Of course these rules could be tweaked to make an exception, but I think you'll find when you start pulling on that string, that the incremental complexity is not as small as you might think.
Of course, there's some degree of benefit that would justify more complexity, but in this case it's not there. The methods we're talking about here are equals, hashCode, and toString. These methods are all intrinsically about object state, and it is the class that owns the state, not the interface, who is in the best position to determine what equality means for that class (especially as the contract for equality is quite strong; see Effective Java for some surprising consequences); interface writers are just too far removed.
It's easy to pull out the AbstractList example; it would be lovely if we could get rid of AbstractList and put the behavior into the List interface. But once you move beyond this obvious example, there are not many other good examples to be found. At root, AbstractList is designed for single inheritance. But interfaces must be designed for multiple inheritance.
Further, imagine you are writing this class:
class Foo implements com.libraryA.Bar, com.libraryB.Moo {
// Implementation of Foo, that does NOT override equals
}
The Foo writer looks at the supertypes, sees no implementation of equals, and concludes that to get reference equality, all he need do is inherit equals from Object. Then, next week, the library maintainer for Bar "helpfully" adds a default equals implementation. Ooops! Now the semantics of Foo have been broken by an interface in another maintenance domain "helpfully" adding a default for a common method.
Defaults are supposed to be defaults. Adding a default to an interface where there was none (anywhere in the hierarchy) should not affect the semantics of concrete implementing classes. But if defaults could "override" Object methods, that wouldn't be true.
So, while it seems like a harmless feature, it is in fact quite harmful: it adds a lot of complexity for little incremental expressivity, and it makes it far too easy for well-intentioned, harmless-looking changes to separately compiled interfaces to undermine the intended semantics of implementing classes.
It is forbidden to define default methods in interfaces for methods in java.lang.Object, since the default methods would never be "reachable".
Default interface methods can be overwritten in classes implementing the interface and the class implementation of the method has a higher precedence than the interface implementation, even if the method is implemented in a superclass. Since all classes inherit from java.lang.Object, the methods in java.lang.Object would have precedence over the default method in the interface and be invoked instead.
Brian Goetz from Oracle provides a few more details on the design decision in this mailing list post.
To give a very pedantic answer, it is only forbidden to define a default method for a public method from java.lang.Object. There are 11 methods to consider, which can be categorized in three ways to answer this question.
Six of the Object methods cannot have default methods because they are final and cannot be overridden at all: getClass(), notify(), notifyAll(), wait(), wait(long), and wait(long, int).
Three of the Object methods cannot have default methods for the reasons given above by Brian Goetz: equals(Object), hashCode(), and toString().
Two of the Object methods can have default methods, though the value of such defaults is questionable at best: clone() and finalize().
public class Main {
public static void main(String... args) {
new FOO().clone();
new FOO().finalize();
}
interface ClonerFinalizer {
default Object clone() {System.out.println("default clone"); return this;}
default void finalize() {System.out.println("default finalize");}
}
static class FOO implements ClonerFinalizer {
#Override
public Object clone() {
return ClonerFinalizer.super.clone();
}
#Override
public void finalize() {
ClonerFinalizer.super.finalize();
}
}
}
I do not see into the head of Java language authors, so we may only guess. But I see many reasons and agree with them absolutely in this issue.
The main reason for introducing default methods is to be able to add new methods to interfaces without breaking the backward compatibility of older implementations. The default methods may also be used to provide "convenience" methods without the necessity to define them in each of the implementing classes.
None of these applies to toString and other methods of Object. Simply put, default methods were designed to provide the default behavior where there is no other definition. Not to provide implementations that will "compete" with other existing implementations.
The "base class always wins" rule has its solid reasons, too. It is supposed that classes define real implementations, while interfaces define default implementations, which are somewhat weaker.
Also, introducing ANY exceptions to general rules cause unnecessary complexity and raise other questions. Object is (more or less) a class as any other, so why should it have different behaviour?
All and all, the solution you propose would probably bring more cons than pros.
The reasoning is very simple, it is because Object is the base class for all the Java classes. So even if we have Object's method defined as default method in some interface, it will be useless because Object's method will always be used. That is why to avoid confusion, we cannot have default methods that are overriding Object class methods.
Does Java have plan that default method substitute for Abstract Class?
I could not find a real case to use default method instead of Abstract?
There are no such plans, which you can derive from comparing the already documented intentions, which differ from the implications of such a plan:
Stuart Marks writes:
The main goal is to allow interface evolution, that is, the addition of new methods. If a new method is added to an interface, existing classes that implement the interface would be missing an implementation, which would be incompatible. To be compatible, an implementation has to come from somewhere, so it is provided by default methods.
…
The main intent of a Java interface is to specify a contract that any class can implement without having to alter its position in the class hierarchy. It's true that, prior to Java 8, interfaces were purely abstract. However, this is not an essential property of interfaces. Even when default methods are included, an interface at its heart still specifies a contract upon the implementing class. The implementing class can override default methods, so the class is still in complete control of its implementation. (Note also that default methods cannot be final.)
and Brian Goetz writes:
The proximate reason for adding default methods to interfaces was to support interface evolution, …
Here are some use cases that are well within the design goals:
Interface evolution. Here, we are adding a new method to an existing interface, which has a sensible default implementation in terms of existing methods on that interface. An example would be adding the forEach method to Collection, where the default implementation is written in terms of the iterator() method.
"Optional" methods. Here, the designer of an interface is saying "Implementors need not implement this method if they are willing to live with the limitations in functionality that entails". For example, Iterator.remove was given a default which throws UnsupportedOperationException; since the vast majority of implementations of Iterator have this behavior anyway, the default makes this method essentially optional. (If the behavior from AbstractCollection were expressed as defaults on Collection, we might do the same for the mutative methods.)
Convenience methods. These are methods that are strictly for convenience, again generally implemented in terms of non-default methods on the class. The logger() method in your first example is a reasonable illustration of this.
Combinators. These are compositional methods that instantiate new instances of the interface based on the current instance. For example, the methods Predicate.and() or Comparator.thenComparing() are examples of combinators.
Note that these do not target the primary domain of abstract classes, like providing a skeleton implementation. Besides the technical differences, abstract classes are semantically different as they bear design decisions about how to implement the functionality, which interfaces, even with default methods, should not. E.g. a well-known example is the List interface, for which two fundamentally different abstract classes exist, AbstractList and AbstractSequentialList and the choice of subclasses either or implementing List entirely different should not be foreclosed by the interface. So the List interface defines the contract and can never be a substitute for an abstract class, which provides a particular base implementation.
Other answers, and links to additional materials, have already adequately covered the technical differences between interfaces and abstract classes. What hasn't been covered well is why to use one over the other.
Consider two different ways to use a class or interface in Java: as a caller or as a subclasser. A caller has an object reference and can call public methods and access public fields via that reference. A subclasser can also access, call, and override protected members of the superclass. Classes can have protected members, but interfaces cannot.
A common question seems to be, now that we have default methods, why do we need abstract classes? A default method is part of what the interface presents to callers. A protected method on a class is not available to callers; it is only available to subclassers. Thus, if you want to share implementation with subclassers, then use a class (or abstract class) and define protected members and fields.
The protected mechanism allows a class to communicate with subclassers, distinct from the way it communicates with callers.
But the OP asks the opposite question: why would one use default methods in preference to abstract classes? In the situation where you actually have a choice (i.e., your abstraction doesn't require state, or protected methods, or any of the things that abstract classes have that interfaces do not), interfaces with default methods are far less constraining than abstract classes. You can only inherit from one class; you can inherit from many interfaces. So interfaces with default methods can behave like stateless traits or mixins, allowing you to inherit behavior from multiple interfaces.
Given that interfaces and abstract classes are used for different purposes, there is no plan to remove or replace anything.
Default methods can't substitute abstract classes, as abstract classes can (and often do) have fields. Interfaces can only contain behaviour and not state, which is unlikely to change in the future as multiple inheritance of state in Java is seen (rightly or wrongly) as evil.
They can also have final methods, which is another thing you can't mimic with default methods.
If anything, interfaces with default methods resemble traits rather than abstract classes, but the match isn't perfect. Using interfaces as traits is something that has to be done very carefully and knowing the limitations they come with. (Such as any implementing class can override a default method, potentially ruining the trait.)
More on this here.
One of the reasons why default methods in interfaces were introduced was to allow adding new methods to the JDK interfaces.
Without this feature once a class has been compiled with a specific version of an interface no new methods can be added to this interface. With the default methods in interfaces feature interfaces can be changed.
Default methods are a nice new tool in our Java toolbox. However, I tried to write an interface that defines a default version of the toString method. Java tells me that this is forbidden, since methods declared in java.lang.Object may not be defaulted. Why is this the case?
I know that there is the "base class always wins" rule, so by default (pun ;), any default implementation of an Object method would be overwritten by the method from Object anyway. However, I see no reason why there shouldn't be an exception for methods from Object in the spec. Especially for toString it might be very useful to have a default implementation.
So, what is the reason why Java designers decided to not allow default methods overriding methods from Object?
This is yet another of those language design issues that seems "obviously a good idea" until you start digging and you realize that its actually a bad idea.
This mail has a lot on the subject (and on other subjects too.) There were several design forces that converged to bring us to the current design:
The desire to keep the inheritance model simple;
The fact that once you look past the obvious examples (e.g., turning AbstractList into an interface), you realize that inheriting equals/hashCode/toString is strongly tied to single inheritance and state, and interfaces are multiply inherited and stateless;
That it potentially opened the door to some surprising behaviors.
You've already touched on the "keep it simple" goal; the inheritance and conflict-resolution rules are designed to be very simple (classes win over interfaces, derived interfaces win over superinterfaces, and any other conflicts are resolved by the implementing class.) Of course these rules could be tweaked to make an exception, but I think you'll find when you start pulling on that string, that the incremental complexity is not as small as you might think.
Of course, there's some degree of benefit that would justify more complexity, but in this case it's not there. The methods we're talking about here are equals, hashCode, and toString. These methods are all intrinsically about object state, and it is the class that owns the state, not the interface, who is in the best position to determine what equality means for that class (especially as the contract for equality is quite strong; see Effective Java for some surprising consequences); interface writers are just too far removed.
It's easy to pull out the AbstractList example; it would be lovely if we could get rid of AbstractList and put the behavior into the List interface. But once you move beyond this obvious example, there are not many other good examples to be found. At root, AbstractList is designed for single inheritance. But interfaces must be designed for multiple inheritance.
Further, imagine you are writing this class:
class Foo implements com.libraryA.Bar, com.libraryB.Moo {
// Implementation of Foo, that does NOT override equals
}
The Foo writer looks at the supertypes, sees no implementation of equals, and concludes that to get reference equality, all he need do is inherit equals from Object. Then, next week, the library maintainer for Bar "helpfully" adds a default equals implementation. Ooops! Now the semantics of Foo have been broken by an interface in another maintenance domain "helpfully" adding a default for a common method.
Defaults are supposed to be defaults. Adding a default to an interface where there was none (anywhere in the hierarchy) should not affect the semantics of concrete implementing classes. But if defaults could "override" Object methods, that wouldn't be true.
So, while it seems like a harmless feature, it is in fact quite harmful: it adds a lot of complexity for little incremental expressivity, and it makes it far too easy for well-intentioned, harmless-looking changes to separately compiled interfaces to undermine the intended semantics of implementing classes.
It is forbidden to define default methods in interfaces for methods in java.lang.Object, since the default methods would never be "reachable".
Default interface methods can be overwritten in classes implementing the interface and the class implementation of the method has a higher precedence than the interface implementation, even if the method is implemented in a superclass. Since all classes inherit from java.lang.Object, the methods in java.lang.Object would have precedence over the default method in the interface and be invoked instead.
Brian Goetz from Oracle provides a few more details on the design decision in this mailing list post.
To give a very pedantic answer, it is only forbidden to define a default method for a public method from java.lang.Object. There are 11 methods to consider, which can be categorized in three ways to answer this question.
Six of the Object methods cannot have default methods because they are final and cannot be overridden at all: getClass(), notify(), notifyAll(), wait(), wait(long), and wait(long, int).
Three of the Object methods cannot have default methods for the reasons given above by Brian Goetz: equals(Object), hashCode(), and toString().
Two of the Object methods can have default methods, though the value of such defaults is questionable at best: clone() and finalize().
public class Main {
public static void main(String... args) {
new FOO().clone();
new FOO().finalize();
}
interface ClonerFinalizer {
default Object clone() {System.out.println("default clone"); return this;}
default void finalize() {System.out.println("default finalize");}
}
static class FOO implements ClonerFinalizer {
#Override
public Object clone() {
return ClonerFinalizer.super.clone();
}
#Override
public void finalize() {
ClonerFinalizer.super.finalize();
}
}
}
I do not see into the head of Java language authors, so we may only guess. But I see many reasons and agree with them absolutely in this issue.
The main reason for introducing default methods is to be able to add new methods to interfaces without breaking the backward compatibility of older implementations. The default methods may also be used to provide "convenience" methods without the necessity to define them in each of the implementing classes.
None of these applies to toString and other methods of Object. Simply put, default methods were designed to provide the default behavior where there is no other definition. Not to provide implementations that will "compete" with other existing implementations.
The "base class always wins" rule has its solid reasons, too. It is supposed that classes define real implementations, while interfaces define default implementations, which are somewhat weaker.
Also, introducing ANY exceptions to general rules cause unnecessary complexity and raise other questions. Object is (more or less) a class as any other, so why should it have different behaviour?
All and all, the solution you propose would probably bring more cons than pros.
The reasoning is very simple, it is because Object is the base class for all the Java classes. So even if we have Object's method defined as default method in some interface, it will be useless because Object's method will always be used. That is why to avoid confusion, we cannot have default methods that are overriding Object class methods.
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?
This question is, to some degree, related to What is the reason why “synchronized” is not allowed in Java 8 interface methods?
The key thing to understand about default methods is that the primary design goal is interface evolution, not "turn interfaces into (mediocre) traits". While there's some overlap between the two, and we tried to be accommodating to the latter where it didn't get in the way of the former, these questions are best understood when viewed in this light. (Note too that class methods are going to be different from interface methods, no matter what the intent, by virtue of the fact that interface methods can be multiply inherited.)
The basic idea of a default method is: it is an interface method with a default implementation, and a derived class can provide a more specific implementation. And because the design center was interface evolution, it was a critical design goal that default methods be able to be added to interfaces after the fact in a source-compatible and binary-compatible manner.
The too-simple answer to "why not final default methods" is that then the body would then not simply be the default implementation, it would be the only implementation. While that's a little too simple an answer, it gives us a clue that the question is already heading in a questionable direction.
Another reason why final interface methods are questionable is that they create impossible problems for implementors. For example, suppose you have:
interface A {
default void foo() { ... }
}
interface B {
}
class C implements A, B {
}
Here, everything is good; C inherits foo() from A. Now supposing B is changed to have a foo method, with a default:
interface B {
default void foo() { ... }
}
Now, when we go to recompile C, the compiler will tell us that it doesn't know what behavior to inherit for foo(), so C has to override it (and could choose to delegate to A.super.foo() if it wanted to retain the same behavior.) But what if B had made its default final, and A is not under the control of the author of C? Now C is irretrievably broken; it can't compile without overriding foo(), but it can't override foo() if it was final in B.
This is just one example, but the point is that finality for methods is really a tool that makes more sense in the world of single-inheritance classes (generally which couple state to behavior), than to interfaces which merely contribute behavior and can be multiply inherited. It's too hard to reason about "what other interfaces might be mixed into the eventual implementor", and allowing an interface method to be final would likely cause these problems (and they would blow up not on the person who wrote the interface, but on the poor user who tries to implement it.)
Another reason to disallow them is that they wouldn't mean what you think they mean. A default implementation is only considered if the class (or its superclasses) don't provide a declaration (concrete or abstract) of the method. If a default method were final, but a superclass already implemented the method, the default would be ignored, which is probably not what the default author was expecting when declaring it final. (This inheritance behavior is a reflection of the design center for default methods -- interface evolution. It should be possible to add a default method (or a default implementation to an existing interface method) to existing interfaces that already have implementations, without changing the behavior of existing classes that implement the interface, guaranteeing that classes that already worked before default methods were added will work the same way in the presence of default methods.)
In the lambda mailing list there are plenty of discussions about it. One of those that seems to contain a lot of discussion about all that stuff is the following: On Varied interface method visibility (was Final defenders).
In this discussion, Talden, the author of the original question asks something very similar to your question:
The decision to make all interface members public was indeed an
unfortunate decision. That any use of interface in internal design
exposes implementation private details is a big one.
It's a tough one to fix without adding some obscure or compatibility
breaking nuances to the language. A compatibility break of that
magnitude and potential subtlety would seen unconscionable so a
solution has to exist that doesn't break existing code.
Could reintroducing the 'package' keyword as an access-specifier be
viable. It's absence of a specifier in an interface would imply
public-access and the absence of a specifier in a class implies
package-access. Which specifiers make sense in an interface is unclear
- especially if, to minimise the knowledge burden on developers, we have to ensure that access-specifiers mean the same thing in both
class and interface if they're present.
In the absence of default methods I'd have speculated that the
specifier of a member in an interface has to be at least as visible as
the interface itself (so the interface can actually be implemented in
all visible contexts) - with default methods that's not so certain.
Has there been any clear communication as to whether this is even a
possible in-scope discussion? If not, should it be held elsewhere.
Eventually Brian Goetz's answer was:
Yes, this is already being explored.
However, let me set some realistic expectations -- language / VM
features have a long lead time, even trivial-seeming ones like this.
The time for proposing new language feature ideas for Java SE 8 has
pretty much passed.
So, most likely it was never implemented because it was never part of the scope. It was never proposed in time to be considered.
In another heated discussion about final defender methods on the subject, Brian said again:
And you have gotten exactly what you wished for. That's exactly what
this feature adds -- multiple inheritance of behavior. Of course we
understand that people will use them as traits. And we've worked hard
to ensure that the the model of inheritance they offer is simple and
clean enough that people can get good results doing so in a broad
variety of situations. We have, at the same time, chosen not to push
them beyond the boundary of what works simply and cleanly, and that
leads to "aw, you didn't go far enough" reactions in some case. But
really, most of this thread seems to be grumbling that the glass is
merely 98% full. I'll take that 98% and get on with it!
So this reinforces my theory that it simply was not part of the scope or part of their design. What they did was to provide enough functionality to deal with the issues of API evolution.
It will be hard to find and identify "THE" answer, for the resons mentioned in the comments from #EJP : There are roughly 2 (+/- 2) people in the world who can give the definite answer at all. And in doubt, the answer might just be something like "Supporting final default methods did not seem to be worth the effort of restructuring the internal call resolution mechanisms". This is speculation, of course, but it is at least backed by subtle evidences, like this Statement (by one of the two persons) in the OpenJDK mailing list:
"I suppose if "final default" methods were allowed, they might need rewriting from internal invokespecial to user-visible invokeinterface."
and trivial facts like that a method is simply not considered to be a (really) final method when it is a default method, as currently implemented in the Method::is_final_method method in the OpenJDK.
Further really "authorative" information is indeed hard to find, even with excessive websearches and by reading commit logs. I thought that it might be related to potential ambiguities during the resolution of interface method calls with the invokeinterface instruction and and class method calls, corresponding to the invokevirtual instruction: For the invokevirtual instruction, there may be a simple vtable lookup, because the method must either be inherited from a superclass, or implemented by the class directly. In contrast to that, an invokeinterface call must examine the respective call site to find out which interface this call actually refers to (this is explained in more detail in the InterfaceCalls page of the HotSpot Wiki). However, final methods do either not get inserted into the vtable at all, or replace existing entries in the vtable (see klassVtable.cpp. Line 333), and similarly, default methods are replacing existing entries in the vtable (see klassVtable.cpp, Line 202). So the actual reason (and thus, the answer) must be hidden deeper inside the (rather complex) method call resolution mechanisms, but maybe these references will nevertheless be considered as being helpful, be it only for others that manage to derive the actual answer from that.
I wouldn't think it is neccessary to specify final on a convienience interface method, I can agree though that it may be helpful, but seemingly the costs have outweight the benefits.
What you are supposed to do, either way, is to write proper javadoc for the default method, showing exactly what the method is and is not allowed to do. In that way the classes implementing the interface "are not allowed" to change the implementation, though there are no guarantees.
Anyone could write a Collection that adheres to the interface and then does things in the methods that are absolutely counter intuitive, there is no way to shield yourself from that, other than writing extensive unit tests.
We add default keyword to our method inside an interface when we know that the class extending the interface may or may not override our implementation. But what if we want to add a method that we don't want any implementing class to override? Well, two options were available to us:
Add a default final method.
Add a static method.
Now, Java says that if we have a class implementing two or more interfaces such that they have a default method with exactly same method name and signature i.e. they are duplicate, then we need to provide an implementation of that method in our class. Now in case of default final methods, we can't provide an implementation and we are stuck. And that's why final keyword isn't used in interfaces.