Java 8 Default Methods Explained in 5 minutes
In my previous articles, we have looked at Java 8 Lambda Expressions and Streams. In this article will be looking at Defaults Methods which is another cool feature of Java 8.
Default methods enable us to add new functionalities to interfaces without breaking the classes that implements that interface. Lets take a look at the example below.
public class MyClass implements InterfaceA {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
@Override
public void saySomething() {
System.out.println("Hello World");
}
}
interface InterfaceA {
public void saySomething();
}
The code above shows class MyClass
implementing InterfaceA
’s method saySomething()
. Now lets add a new method called sayHi()
to InterfaceA
. By doing so, we have introduce a problem to class MyClass
as it will not compile until we provide implementation for method sayHi()
.
This is when Defaults methods becomes useful. By Adding the keyword default before the method’s access modifier, we do not have to provide implementation for the method sayHi()
in class MyClass
.
In ‘the strictest sense’, Default methods are a step backwards because they allow you to ‘pollute’ your interfaces with code. But they provide the most elegant and practical way to allow backwards compatibility. It made it much easier for Oracle to update all the Collections classes and for you to retrofit your existing code for Lambda.
public class MyClass implements InterfaceA {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
@Override
public void saySomething() {
System.out.println("Hello World");
}
}
interface InterfaceA {
public void saySomething();
default public void sayHi() {
System.out.println("Hi");
}
}
Note that we have to provide implementation for all default methods. So default methods provides us the flexibility to allow methods to be implemented in interfaces. The implementation will be used as default if a concrete class does not provide implementation for that method.
Conflicts with Multiple Interface.
Since classes in java can implement multiple interfaces, there could be a situation where 2 or more interfaces has a default method with the same signature hence causing conflicts as java will not know what methods to use at a time. This will then result in a compilation error with the message MyClass
inherits unrelated defaults for sayHi()
from types InterfaceA
and InterfaceB
.
Lets take a look at the example below.
public class MyClass implements InterfaceA, InterfaceB {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
@Override
public void saySomething() {
System.out.println("Hello World");
}
}
interface InterfaceA {
public void saySomething();
default public void sayHi() {
System.out.println("Hi from InterfaceA");
}
}
interface InterfaceB {
default public void sayHi() {
System.out.println("Hi from InterfaceB");
}
}
In order to work around situations like this,We will have to provide implementation for sayHi()
method in the class MyClass
therefore overriding both methods in InterfaceA
and InterfaceB
.
public class MyClass implements InterfaceA, InterfaceB {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
@Override
public void saySomething() {
System.out.println("Hello World");
}
@Override
public void sayHi() {
System.out.println("implemetation of sayHi() in MyClass");
}
}
interface InterfaceA {
public void saySomething();
default public void sayHi() {
System.out.println("Hi from InterfaceA");
}
}
interface InterfaceB {
default public void sayHi() {
System.out.println("Hi from InterfaceB");
}
}
If we want to specifically invoke one of the sayHi()
methods in either InterfaceA
or InterfaceB
, we can also do as follows:
public class MyClass implements InterfaceA, InterfaceB {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
@Override
public void saySomething() {
System.out.println("Hello World");
}
@Override
public void sayHi() {
InterfaceA.super.sayHi();
}
}
interface InterfaceA {
public void saySomething();
default public void sayHi() {
System.out.println("Hi from InterfaceA");
}
}
interface InterfaceB {
default public void sayHi() {
System.out.println("Hi from InterfaceB");
}
}
Hopefully you have found this quick guide useful.
相关文章
- Java反射机制应用实践
- 深入探讨Java中的异常与错误处理
- 研究学习Kotlin的一些方法
- 数据显示Java热度持续下落,日子屈指可数?
- 2017年5月编程语言排行榜:Java与C语言优势正开始缩小
- Java多线程之内置锁与显示锁
- Java线程池的理论与实践
- 白话阿里巴巴Java开发手册(编程规约)
- 关于Java你不知道的十件事
- Java服务化系统线上应急和技术攻关,你必须掌握的Linux命令
- Java实现高斯模糊和图像的空间卷积
- Java阻塞队列实现原理分析
- NPM使用技巧
- Node.js对Java开发者而言是什么?
- Java反射机制应用实践
- 理解RxJava中的Single和Completable
- 2017年你不能错过的Java类库
- 大规模集群下的Hadoop NameNode
- 从源码解密Spark内存管理
- 2017年3月编程语言排行榜:Swift首次进入前十