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.
Related
I know this question has been asked many times and we have articles all over the internet but I still cannot fully understand, when should I use interface or abstract class since I am using Java 15.
Most of the articles talk about the differences and use cases before Java 8 which makes sense but not when you can basically provide body for your methods in interface.
The only thing that made sense to me is non-public and non-final restrictions.
I would really appreciate if somebody can point out 1-2 examples of the scenarios where I need to choose between interface and abstract class in Java 15. Also, would be great if it can be in terms of real life projects rather than Animal or shape class examples.
Thanks !!
default methods on interface
Apparently you are referring to the feature of “default methods” implementing behavior in an interface.
You should understand that the feature was added as a way around this dilemma: How to retroactively add features leveraging streams and lambda on existing interfaces without breaking existing classes that implement those interfaces?
Many new methods were added to those interfaces such as in the Java Collections Framework. Adding methods to an existing interface would automatically break all classes implementing the interface that are lacking the newly-required methods. Being able to provide a fallback, to give an implementation where one is now required but not yet existing, would resolve the dilemma. Thus « default methods » were born.
To quote from the Oracle tutorial linked above:
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.
To quote this Answer by Brian Goetz, Java Language Architect at Oracle:
The proximate reason for adding default methods to interfaces was to support interface evolution
So this feature of adding default behavior to an interface was not meant to be a new mainstream feature in and of itself. The intent of default was not to replace abstract.
Indeed, some experienced Java experts have recommended against making a habit of writing default methods on an interface. They recommend pretty much ignoring that feature of the Java language. Continue to think of interfaces as simply defining a contract, and abstract classes as providing partial implementations meant to be completed in a subclass.
You are certainly free to write your own default methods on your interfaces. And certainly you should do so if you are in a similar situation of having published an interface that others may have implemented, and now you want to add methods. But unnecessarily adding default methods is likely to confuse other programmers who expect partial implementations on an abstract class rather than an interface.
Four situations calling for default method on an interface
In that same post linked above, Brian Goetz suggests three other cases beyond interface evolution where default methods on an interface may be appropriate. Here is a quick mention; see his post for details.
Optional methods - The default method throws an UnsupportedOperationException because we expect implementations of this interface to more often not want to implement this method.
Convenience methods
Combinators
Start with interface, move to abstract class for shared code
As for choosing between an interface and abstract class:
Generally start with an interface. Or several interfaces if you want various implementing classes to mix various contracts (see mixin).
Think twice before adding a default method. Consider if your situation meets one of the four cases recommended by Brian Goetz as discussed above.
If you come to realize that you have duplicated code across multiple classes, then consider centralizing that shared code to an abstract class to be used across subclasses.
Alternatively, use composition rather than inheritance (discussed below).
For example, you might have a class for domestic ShippingLabelUS as well as ShippingLabelCanada and ShippingLabelOverseas. All three need to convert between imperial pounds and metric kilograms. You find yourself copying that code between the classes. At this point you might consider having all three classes extend from abstract class ShippingLabel where a single copy of the weight conversion methods live.
While designing your API keep in mind that Java, like most OOP languages, has single-inheritance. So your subclasses are limited to extending only one class. To be a bit more specific about the single-versus-multiple inheritance, I will quote Brian Goetz from this PDF of a slide deck:
[regarding default methods on an interface]
Wait,is this multiple inheritance in Java?
• Java always had multiple inheritance of types
• This adds multiple inheritance of behavior
• But not of state, where most of the trouble comes from
Composition over inheritance
An alternative to using an abstract class for shared behavior is creating a separate class for specific behavior, then adding an object of that separate class to be kept as a member field on the larger class. Wise programmers often share this pearl of wisdom: Prefer composition over inheritance.
Regarding the shipping label example above, you could create a WeightConverter class, an object of which would be a member of each of the three label classes. In this arrangement, no need for the abstract class.
I've seen in several code libraries classes named Mixin with comments like:
//Mixin style implementation
public class DetachableMixin implements Detachable {}
Which is the concept under this style of implementations?
Here is a qoute from Joshua Bloch "Efective Java" (I don't think, I could explain it better myself):
Interfaces are ideal for defining mixins. Loosely speaking, a mixin is a type
that a class can implement in addition to its “primary type” to declare that it provides
some optional behavior. For example, Comparable is a mixin interface that
allows a class to declare that its instances are ordered with respect to other mutually
comparable objects. Such an interface is called a mixin because it allows the
optional functionality to be “mixed in” to the type’s primary functionality.
Abstract classes can’t be used to define mixins for the same reason that they can’t
be retrofitted onto existing classes: a class cannot have more than one parent, and
there is no reasonable place in the class hierarchy to insert a mixin.
The other answer is spot on, but it might be worth pointing out that other JVM languages go even further.
Scala for examples has traits - basically "interfaces" with method implementations. In scala, you can mix one class together with multiple traits, thereby allowing to inherit behavior from several different "places.
Basically the same concept that Java picked up with Java 8, where you know can add default method behavior to interfaces. And for the record: if I recall it correctly, Java8 interfaces and default methods are not meant to introduce a full "mixin" concept in the Java language. The idea is not that you should use this feature to achieve multiple inheritance through the back door. See this lengthy answer from Stuart Mark, one of the people driving the Java language evolution. They state:
The purpose of default methods ... is to enable interfaces to be evolved in a compatible manner after their initial publication.
A good article about implementing mixin pattern with Virtual Extension Methods since Java 8: https://kerflyn.wordpress.com/2012/07/09/java-8-now-you-have-mixins/
The virtual extension method is something new in Java. It brings another mean of expression to create new patterns and best pratices. This article provides an example of such a pattern, enabled in Java 8 due to the use of virtual extension methods. I am sure you can extract other new patterns from them. But, as I have experienced here, you should not hesitate to share them in a view to check their validaty.
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
Why did new Spliterators class appear in Java 8? Since Java 8 we have possibility to add static methods to the interfaces.
Since Spliterators class has only static method wouldn't be simpler to declare all its methods in the Spliterator interface?
The same question about Collectors/Collector pair.
Thank you.
It’s perfectly possible that this decision was made without even thinking about this brand new possibility, but simply following the established-since-twenty-years pattern.
Besides that, it can be debated whether it is really useful to add 25 to 30 static methods to an interface. It makes sense to offer a few factories for canonical implementations, but you should draw a line somewhere. It’s not feasible to add factories to all implementations to an interface, just because they are offered by the same library. But this debate would be off-topic.
Further, Spliterators does not only offer static methods, but also nested classes. Unlike static methods, these classes would pollute the name space of every implementation class, when being defined in an interface.
Collectors and Spliterators may also contain implementation-specific non-public methods and even fields.
No, is not good idea, because interface declares a contract, but class represents logic. But after add default method to interface in Java 8 we can only declare public method, but in abstract class we can add public and private abstract method, so we still can hide some logic in abstract classes. Imagine, in actual level of language you can declare only public method, and everyone can change your idea for e.q. Collection
Because there is a difference between an interface and a class. These two have different intentions. Interface declares a contract. Default methods for the interface should be used carefully, for instance, where you can't break compatibility by adding a method declaration into an interface and can't declare xxxV2 interface.
A class is an entity, which represents a unit of the program logic.
Java 8 introduced default and static methods on interfaces. So now you can have concrete implementations in your interface whether using default or static methods.
The reason Java claimed to add these two new kind of methods is "ensure binary compatibility with code written for older versions of those interfaces".
My question:
Why to distort the interface original concept that suppose to be
fully abstract in order to support existing architectural problems?
What is the difference between using an abstract class and the new version of the interface other than the ability of a class to extend multiple interfaces?
The reason java claimed to add these 2 new kind of methods is "ensure binary compatibility with code written for older versions of those interfaces".
This applies only to default methods (not static methods) and omits some context. From Goetz, State of the Lambda:
The purpose of default methods ... is to enable interfaces to be evolved in a compatible manner after their initial publication.
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.
Why to distort the interface original concept that suppose to be fully abstract in order to support existing architectural problems?
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.)
What is the difference between using an abstract class and the new version of the interface other than the ability of a class to extend multiple interfaces?
The ability of a class to extend multiple interfaces is closely related to another difference between interfaces and abstract classes, namely that interfaces cannot contain state. This is the primary difficulty with allowing multiple inheritance: if a superclass were to appear multiple times in the ancestry of a class, would that superclass' state appear just once or several times? (This is the so-called "diamond problem.")
Another difference is that abstract classes can define methods and fields to be shared with subclasses, but not with callers, by using protected and package-private access levels. Interfaces can have only public methods.
(In Java 9, support for private methods has been added. This is useful for implementation sharing among default or static methods of an interface.)
Finally, static methods in interfaces don't affect class inheritance, nor are they part of the interface's contract. They are merely a way of organizing utility methods in more convenient fashion. For example, a common use of static methods in an interface is for static factory methods. If static methods weren't allowed in interfaces, static factory methods would have to be put on a companion class. Allowing static methods in interfaces lets such methods be grouped with the interface itself, when doing so is appropriate.
The problem is, that you can never extend an Interface with a new method without breaking compatibility. Existing classes would not implement the method and therefore not run with the new version of code which use this method.
This was a major problem for the Java Class Library itself as it cannot add often asked for methods in basic interfaces (like Collections). This was the main driver for implementing default methods for interfaces.
The difference between this new method and using an abstract class (which is a quite good pattern for this problem in some cases) is, that you cannot inherit from multiple abstract classes. But you can easily implement multiple interfaces.
The static methods in interfaces are less clear, I think they are here to help you implement the default methods (if two default methods have same code, they both can call to a static method).