While going through spring security modules I came across this piece of code inside the Principal Interface class. My understanding is that Interfaces do not implement anything concrete.
What is the reason for the below piece of code inside an Interface ?
public interface Principal {
//other method definitions
public default boolean implies(Subject subject) {
if (subject == null)
return false;
return subject.getPrincipals().contains(this);
}
}
Those are called default methods; and were introduced with Java8.
Quoting the Oracle tutorial:
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
Meaning: starting with java8, we actually can add behavior into interfaces. The idea is to make it easier to enhance existing interfaces - not to provide a "generic" mixin/trait concept to Java.
In other words: according to the people behind Java, the main reason for default was the need to enhance a lot of existing collection interfaces to support the new stream paradigm.
It is also worth pointing out that Java8 interfaces also allow for static methods:
In addition to default methods, you can define static methods in interfaces. (A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods.)
This is a default method for an interface, available since Java 8.
It's a feature that allows developers to add new methods to an interface without breaking the existing implementations of these. It provides flexibility to allow interface define implementation which will use as default in the situation where a concrete class fails to provide an implementation for that method.
Refactoring an existing interface from a framework or even from the
JDK is complicated. Modify one interface breaks all classes that
extends the interface which means that adding any new method could
break millions of lines of code. Therefore, default methods have
introduced as a mechanism to extending interfaces in a backward
compatible way.
Another potential usage would be to just call other methods from the interface like in a forEach option where you get a list parameter and call another method that accepts just one element.
My personal opinion is that default methods should be used as less as possible and to not contain any business logic. It's mainly made for keeping old interfaces (10+ years old) retro-compatible.
More details: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
https://dzone.com/articles/interface-default-methods-java
I am confused with a line in Oracle Java docs here under the heading Interfaces In Java, which says:
Method bodies exist only for default methods and static methods.
As we cannot define method body in interface, I am confused if this line has some other meaning. Appreciate if somebody can help me in understanding this.
In Java 8, interfaces may contain default implementations for their methods, as well as implemented static methods.
Default methods and static methods are new features of java 8. Prior to java 8 it was not possible to define then in an interface.
Default methods have for example the benefit of changing extending interfaces (no in the inheritance sense) with other new methods for wich you have to may a default body so that existing implementations a not broken.
Static methods in interfaces have for example the benefit of sparing the need for the creation of other classes (utility/helper classes for example) of with the only pupose is to work on instances instances of that interface.
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.
I use Java but I have a better background with C#. I've been reading Java's default and static methods in interfaces. I think I understood how default methods in interfaces would be useful. For instance, we have extension methods in C#. One thing it helps language designers is that they could freely add new methods for interfaces such as Where, Select, etc. where lambda expressions can be used without breaking binary code compatibility. So default methods in Java's interfaces can help in the same way.
But when it comes to static methods in Java interfaces, it is where I am not sure how useful it would be. Can anyone explain me why static methods added to interfaces and in what cases they are useful for us developers. I also would like to hear if there are different reasons for default method other than what I mentioned.
But when it comes to static methods in Java interfaces, it is where I am not sure how useful it would be.
It negates the case for separate "utility" classes whose sole purpose is to house static methods that are all related to one particular interface.
Collections is always the example that springs to mind for me - if static methods were allowed on interfaces since the beginning, then this entire class wouldn't be necessary and the static methods could just belong to the Collection interface (which makes sense, because they all operate on Collection types.)
Of course, backwards compatibility means that we can't just do away with design like this in the API right away, but it means future library design can take it into consideration and hopefully produce slightly cleaner APIs because of it.
I often find myself wanting to do it. It can be very useful when you want to store some useful information or extra states.
So my question is, is there a very good/strong reason why this is forbidden?
Thanks
EDIT:
Thanks a lot for all these answers. So it sounds like there's no right-or-wrong answer to this.
Assuming I accept the fact that these classes are not to be subclassed, what's the point of not marking a Control class final, but prohibiting subclassing - effectively demoting the exception/error from compile-time to run-time?
EDIT^2:
See my own answer to this: apparently, these classes are overrideable, but requires explicit acknowledgement by the overrider.
Thanks
It doesn't look like anybody mentioned this in any of the answers, but SWT does provide an overrideable checkSubclass() method; precisely where the Unextendable exception is thrown. Override the method to a no-op and effectively make extending legal. I guess to leave this option open is ultimately the reason that the class is not made final and the extension error not made compile-time instead of run-time.
Example:
#Override
protected void checkSubclass() {
// allow subclass
System.out.println("info : checking menu subclass");
}
Designing components for inheritance is hard, and can limit future implementation changes (certainly if you leave some methods overridable, and call them from other methods). Prohibiting subclassing restricts users, but means it's easier to write robust code.
This follows Josh Bloch's suggestion of "design for inheritance or prohibit it". This is a bit of a religious topic in the dev community - I agree with the sentiment, but others prefer everything to be as open to extension as possible.
It is very hard to create class that can be safely subclassed. You have to think about endless use cases and protect you class very well. I believe that this is a general reason to mark API class as final.
As for your follow-up question:
what's the point of not marking a
Control class final, but prohibiting
subclassing - effectively demoting the
exception/error from compile-time to
run-time?
It's not possible for SWT to subclass the Control class, if they mark it final. But they have to internally. So they defer the checking to runtime.
BTW, if you want an insane hack, you can still subclass Control or any other SWT class, by putting your subclass into the org.eclipse.swt.widgets package. But I never really had to do that.
The method description of org.eclipse.swt.widgets.Widget.checkSubclass() says:
Checks that this class can be subclassed.
The SWT class library is intended to be subclassed only at specific,
controlled points (most notably, Composite and Canvas when
implementing new widgets). This method enforces this rule unless it is
overridden.
IMPORTANT: By providing an implementation of this method that allows a
subclass of a class which does not normally allow subclassing to be
created, the implementer agrees to be fully responsible for the fact
that any such subclass will likely fail between SWT releases and will
be strongly platform specific. No support is provided for user-written
classes which are implemented in this fashion.
The ability to subclass outside of the allowed SWT classes is intended
purely to enable those not on the SWT development team to implement
patches in order to get around specific limitations in advance of when
those limitations can be addressed by the team. Subclassing should not
be attempted without an intimate and detailed understanding of the
hierarchy.
Throws: SWTException
ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass