I have an interface in Kotlin that I want to have default implementations so that implementing classes will only have to implement a subset of the methods. Example:
interface PersonInterface {
val firstname: String?
get() = null
val lastName: String?
get() = null
val phoneNumbers: List<String>?
get() = null
val interests: List<List<String>>?
get() = emptyList()
}
This in my understanding would create default implementations for the methods to return null or an empty list or whatever I would have as defaults in general.
But if I create the following class in Java (which I expected it would compile):
public class Employee implements PersonInterface {
}
I get:
Class Employee must either be declared abstract or implement abstract
method getFirstName in PersonInterface
Is it possible to use default interface implementation defined in Kotlin from Java?
According to documentation (https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html):
Starting from JDK 1.8, interfaces in Java can contain default methods. To make all non-abstract members of Kotlin interfaces default for the Java classes implementing them, compile the Kotlin code with the -Xjvm-default=all compiler option
Note: Prior to Kotlin 1.4, to generate default methods, you could use the #JvmDefault annotation on these methods. Compiling with -Xjvm-default=all in 1.4 generally works as if you annotated all non-abstract methods of interfaces with #JvmDefaultand compiled with -Xjvm-default=enable. However, there are cases when their behavior differs. Detailed information about the changes in default methods generation in Kotlin 1.4 is provided in this post on the Kotlin blog.
Related
Consider the following Java interface
interface Foo {
String getValue();
}
In Kotlin, get/set functions are converted to properties, so I would expect the implementation to look like this
class FooImpl : Foo {
val value: String get() = "Hello, World!"
}
But I actually have to implement the method as it is in the interface
class FooImpl {
override fun getValue(): String {
return "Hello, World!";
}
}
Why?
Kotlin makes an explicit difference between methods and properties. They are not considered the same thing; it just so happens that both are compiled down to methods in the end since the JVM doesn't natively support properties. As such, a method cannot implement a property since they're fundamentally different.
The reason why you can't implement a Java getter with a property is the same reason as why you can't implement a Kotlin-defined fun getX(): String with an override val x: String; they're just not compatible.
The confusion here seems to stem from how Kotlin allows you to access Java getters with a property-like syntax, i.e. val foo = obj.x is equivalent to val foo = obj.getX() if the class is defined in Java.
This is strictly a one-way relationship to make Kotlin code that interoperates with Java code slightly more compact and "Kotlin-like"; this syntactical shortcut doesn't extend to implementing the method as if it were a property.
Additionally, if you were to implement a method as a property, that would probably lead to strange effects. Arguably, it would be both a method and a property at the same time, which would not only be weird, but would likely lead to a lot of other unexpected behaviors and edge cases in the language. (For instance, how would it be treated when using reflection?)
An interface in Java is similar to a class, but the body of an
interface can include only abstract methods and final fields
(constants).
Recently, I saw a question, which looks like this
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
According to the interface definition, only abstract methods are allowed. Why does it allow me to compile the above code? What is the default keyword?
On the other hand, when I was trying to write below code, then it says modifier default not allowed here
default class MyClass{
}
instead of
class MyClass {
}
Can anyone tell me the purpose of the default keyword? Is it only allowed inside an interface? How does it differ from default (no access modifier)?
It's a new feature in Java 8 which allows an interface to provide an implementation. Described in Java 8 JLS-13.5.6. Interface Method Declarations which reads (in part)
Adding a default method, or changing a method from abstract to default, does not break compatibility with pre-existing binaries, but may cause an IncompatibleClassChangeError if a pre-existing binary attempts to invoke the method. This error occurs if the qualifying type, T, is a subtype of two interfaces, I and J, where both I and J declare a default method with the same signature and result, and neither I nor J is a subinterface of the other.
What's New in JDK 8 says (in part)
Default methods enable new functionality to be added to the interfaces of libraries and ensure binary compatibility with code written for older versions of those interfaces.
Default methods were added to Java 8 primarily to support lambda expressions. The designers (cleverly, in my view) decided to make lambdas syntax for creating anonymous implementations of an interface. But given lambdas can only implement a single method they would be limited to interfaces with a single method which would be a pretty severe restriction. Instead, default methods were added to allow more complex interfaces to be used.
If you need some convincing of the claim that default was introduced due to lambdas, note that the straw man proposal of Project Lambda, by Mark Reinhold, in 2009, mentions 'Extension methods' as a mandatory feature to be added to support lambdas.
Here's an example demonstrating the concept:
interface Operator {
int operate(int n);
default int inverse(int n) {
return -operate(n);
}
}
public int applyInverse(int n, Operator operator) {
return operator.inverse(n);
}
applyInverse(3, n -> n * n + 7);
Very contrived I realise but should illustrate how default supports lambdas. Because inverse is a default it can easily be overriden by a implementing class if required.
A new concept is introduced in Java 8 called default methods. Default methods are those methods which have some default implementation and helps in evolving the interfaces without breaking the existing code. Lets look at an example:
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork() {
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements SimpleInterface {
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
and the output is:
Do Some Work implementation in the class
DoSomeOtherWork implementation in the interface
Something that was overlooked in the other answers was its role in annotations. As far back as Java 1.5, the default keyword came about as a means to provide a default value for an annotation field.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Processor {
String value() default "AMD";
}
It usage was overloaded with the introduction of Java 8 to allow one to define a default method in interfaces.
Something else that was overlooked: the reason that the declaration default class MyClass {} is invalid is due to the way that classes are declared at all. There's no provision in the language that allows for that keyword to appear there. It does appear for interface method declarations, though.
Default methods in an interface allow us to add new functionality without breaking old code.
Before Java 8, if a new method was added to an interface, then all the implementation classes of that interface were bound to override that new method, even if they did not use the new functionality.
With Java 8, we can add the default implementation for the new method by using the default keyword before the method implementation.
Even with anonymous classes or functional interfaces, if we see that some code is reusable and we don’t want to define the same logic everywhere in the code, we can write default implementations of those and reuse them.
Example
public interface YourInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
The new Java 8 feature (Default Methods) allows an interface to provide an implementation when its labeled with the default keyword.
For Example:
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
Interface Test uses the default keyword which allows the interface to provide a default implementation of the method without the need for implementing those methods in the classes that uses the interface.
Backward compatibility:
Imagine that your interface is implemented by hundreds of classes, modifying that interface will force all the users to implement the newly added method, even though its not essential for many other classes that implements your interface.
Facts & Restrictions:
1-May only be declared within an interface and not within a class or
abstract class.
2-Must provide a body
3-It is not assumed to be public or abstract as other normal methods used in an interface.
A very good explanation is found in The Java™ Tutorials, part of the explanation is as follows:
Consider an example that involves manufacturers of computer-controlled cars who publish industry-standard interfaces that describe which methods can be invoked to operate their cars. What if those computer-controlled car manufacturers add new functionality, such as flight, to their cars? These manufacturers would need to specify new methods to enable other companies (such as electronic guidance instrument manufacturers) to adapt their software to flying cars. Where would these car manufacturers declare these new flight-related methods? If they add them to their original interfaces, then programmers who have implemented those interfaces would have to rewrite their implementations. If they add them as static methods, then programmers would regard them as utility methods, not as essential, core methods.
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.
Default methods enable you to add new functionality to the interfaces of your apps. It can also be used to have a multi inheritance.
In addition to default methods, you can define static methods in interfaces. This makes it easier for you to organize helper methods
I read that in Java "interfaces cannot be instantiated - they can only be implemented by classes or extended by other interfaces".
However I can perfectly write:
val set = setOf<String>("one", "two")
in Kotlin, with set being of type Set<String>.
Doesn't this contradict my first statement as I'm instantiating the Set?
I read that in Java "interfaces cannot be instantiated - they can only be implemented by classes or extended by other interfaces"
What this means is just that you can't write
Set<String> set = new Set<String>(...);
(don't confuse with new Set<String> { ... } which creates an anonymous class implementing Set and instantiates that class). You can write Set.of("one", "two") though this method was only added in Java 9. It is a factory method, just like Kotlin setOf, not "instantiating an interface".
The Kotlin equivalent to the illegal new Set would be
val set = Set<String>(...)
which is also not allowed.
Though Kotlin intentionally blurs the line between constructors and methods; it would be perfectly in line with other types in the standard library to define a factory method called Set which would be called in the same way, or an operator fun invoke in the companion object. See the List method for an example.
An interface in Java is similar to a class, but the body of an
interface can include only abstract methods and final fields
(constants).
Recently, I saw a question, which looks like this
interface AnInterface {
public default void myMethod() {
System.out.println("D");
}
}
According to the interface definition, only abstract methods are allowed. Why does it allow me to compile the above code? What is the default keyword?
On the other hand, when I was trying to write below code, then it says modifier default not allowed here
default class MyClass{
}
instead of
class MyClass {
}
Can anyone tell me the purpose of the default keyword? Is it only allowed inside an interface? How does it differ from default (no access modifier)?
It's a new feature in Java 8 which allows an interface to provide an implementation. Described in Java 8 JLS-13.5.6. Interface Method Declarations which reads (in part)
Adding a default method, or changing a method from abstract to default, does not break compatibility with pre-existing binaries, but may cause an IncompatibleClassChangeError if a pre-existing binary attempts to invoke the method. This error occurs if the qualifying type, T, is a subtype of two interfaces, I and J, where both I and J declare a default method with the same signature and result, and neither I nor J is a subinterface of the other.
What's New in JDK 8 says (in part)
Default methods enable new functionality to be added to the interfaces of libraries and ensure binary compatibility with code written for older versions of those interfaces.
Default methods were added to Java 8 primarily to support lambda expressions. The designers (cleverly, in my view) decided to make lambdas syntax for creating anonymous implementations of an interface. But given lambdas can only implement a single method they would be limited to interfaces with a single method which would be a pretty severe restriction. Instead, default methods were added to allow more complex interfaces to be used.
If you need some convincing of the claim that default was introduced due to lambdas, note that the straw man proposal of Project Lambda, by Mark Reinhold, in 2009, mentions 'Extension methods' as a mandatory feature to be added to support lambdas.
Here's an example demonstrating the concept:
interface Operator {
int operate(int n);
default int inverse(int n) {
return -operate(n);
}
}
public int applyInverse(int n, Operator operator) {
return operator.inverse(n);
}
applyInverse(3, n -> n * n + 7);
Very contrived I realise but should illustrate how default supports lambdas. Because inverse is a default it can easily be overriden by a implementing class if required.
A new concept is introduced in Java 8 called default methods. Default methods are those methods which have some default implementation and helps in evolving the interfaces without breaking the existing code. Lets look at an example:
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork() {
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements SimpleInterface {
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
and the output is:
Do Some Work implementation in the class
DoSomeOtherWork implementation in the interface
Something that was overlooked in the other answers was its role in annotations. As far back as Java 1.5, the default keyword came about as a means to provide a default value for an annotation field.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Processor {
String value() default "AMD";
}
It usage was overloaded with the introduction of Java 8 to allow one to define a default method in interfaces.
Something else that was overlooked: the reason that the declaration default class MyClass {} is invalid is due to the way that classes are declared at all. There's no provision in the language that allows for that keyword to appear there. It does appear for interface method declarations, though.
Default methods in an interface allow us to add new functionality without breaking old code.
Before Java 8, if a new method was added to an interface, then all the implementation classes of that interface were bound to override that new method, even if they did not use the new functionality.
With Java 8, we can add the default implementation for the new method by using the default keyword before the method implementation.
Even with anonymous classes or functional interfaces, if we see that some code is reusable and we don’t want to define the same logic everywhere in the code, we can write default implementations of those and reuse them.
Example
public interface YourInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
class SimpleInterfaceImpl implements YourInterface{
/*
* Not required to override to provide an implementation
* for doSomeOtherWork.
*/
#Override
public void doSomeWork() {
System.out.println("Do Some Work implementation in the class");
}
/*
* Main method
*/
public static void main(String[] args) {
SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
simpObj.doSomeWork();
simpObj.doSomeOtherWork();
}
}
The new Java 8 feature (Default Methods) allows an interface to provide an implementation when its labeled with the default keyword.
For Example:
interface Test {
default double getAvg(int avg) {
return avg;
}
}
class Tester implements Test{
//compiles just fine
}
Interface Test uses the default keyword which allows the interface to provide a default implementation of the method without the need for implementing those methods in the classes that uses the interface.
Backward compatibility:
Imagine that your interface is implemented by hundreds of classes, modifying that interface will force all the users to implement the newly added method, even though its not essential for many other classes that implements your interface.
Facts & Restrictions:
1-May only be declared within an interface and not within a class or
abstract class.
2-Must provide a body
3-It is not assumed to be public or abstract as other normal methods used in an interface.
A very good explanation is found in The Java™ Tutorials, part of the explanation is as follows:
Consider an example that involves manufacturers of computer-controlled cars who publish industry-standard interfaces that describe which methods can be invoked to operate their cars. What if those computer-controlled car manufacturers add new functionality, such as flight, to their cars? These manufacturers would need to specify new methods to enable other companies (such as electronic guidance instrument manufacturers) to adapt their software to flying cars. Where would these car manufacturers declare these new flight-related methods? If they add them to their original interfaces, then programmers who have implemented those interfaces would have to rewrite their implementations. If they add them as static methods, then programmers would regard them as utility methods, not as essential, core methods.
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.
Default methods enable you to add new functionality to the interfaces of your apps. It can also be used to have a multi inheritance.
In addition to default methods, you can define static methods in interfaces. This makes it easier for you to organize helper methods
Consider the following little example:
package prv.rli.codetest;
import java.lang.reflect.Method;
public class BreakingInterfaces {
interface Base {
BaseFoo foo();
interface BaseFoo {
}
}
interface Derived extends Base {
DerivedFoo foo();
interface DerivedFoo extends BaseFoo {
}
}
public static void main(String[] args) {
dumpDeclaredMethods(Derived.class);
}
private static void dumpDeclaredMethods(Class<?> class1) {
System.out.println("---" + class1.getSimpleName() + "---");
Method[] methods = class1.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("----------");
}
}
If you compile the above example with jdk1.7.0.55 the output is:
---Derived---
public abstract BreakingInterfaces$Derived$DerivedFoo BreakingInterfaces$Derived.foo()
----------
But when using jdk1.8.0.25 the output is:
---Derived---
public abstract prv.rli.codetest.BreakingInterfaces$Derived$DerivedFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
public default prv.rli.codetest.BreakingInterfaces$Base$BaseFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
----------
Does anybody know, whether this is a bug in jdk1.8.0.25 or why the public default Method resurfaces here?
getDeclaredMethods() behaves correctly here as it tells you exactly what it has found in the class. If you feed in an interface compiled with Java 7 target (or an older compiler) you will see no difference to the output of the Java 7 implementation of getDeclaredMethods().
It’s the compiler which behaves differently. When compiling such a sub-interface in Java 8, a bridge method will be generated which will not be generated for a Java 7 target as it is not even possible for the Java 7 target.
The reason why bridge methods are generated for interfaces now is that you usually have more implementation classes than interfaces, therefore having a default bridge method in the interface saves you from adding that bridge method to every implementation. Further, it makes lambda class generation much easier if there is only one abstract method and no bridge method to implement.
When an interface hierarchy requires bridge methods but provides no defaults, the compiler has to generate code using LambdaMetafactory.altMetafactory rather than LambdaMetafactory.metafactory specifying every bridge method that is required.
Pardon the furstration, but it must be in a parallel universe where the Javadoc wording adequately explains this behavior: https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredMethods--. An array of "all the declared methods" turns out to be an array of "all declared methods by the user and by some under-the-hood implementation detail explained on StackOverflow". Even worse, I'm seeing something weird about annotations: I'm overriding a generic method while applying an annotation, and both abstract&default methods returned by getDeclaredMethods() have the annotation, but only the abstract one has the correct non-generic parameters. So it seems to me this implementation detail partly defeats the purpose of searching for a method by annotation.