Photo by Christian Kaindl on Unsplash
As a Java developer for years, you may have very strong sense about how Java should be. Object-oriented, single inheritance, multiple interface implementation, generic, etc. But things change slightly since the born of Java 8. Have you ever try how to declare optional functions in interface?
Java 8 brings lots of modern and powerful new features — Lambda, Stream, etc. Though brand new features come with brand new syntax which we don’t familiar, the fundamental of Java still stand firmly. But it will be a breaking change for some feature like stream if we want to support in the interface layer. Let’s say if we want to add new functions in an existing interface, all the implementation should update or it will break. There will be a big compatible issue for us, so here comes the idea of default methods. Which allow us to add function implementation into an interface. So upgrade to Java 8 won’t be a headache for us.
If you’re interested in Lambda, you can check it out here — Lambda Expression in Java
As you can imagine, it’s hard to add new functions into an existing interface because we need to add implementations all over the world. So we decide add implementations into interface itself directly. Here is a basic example:
public interface A {
default void a() {// add implementation here}}
Yes, that simple. If you place the key word default
in front of the function declaration in interface then you can add the implementation just like a normal function does.
With this new feature, we can achieve some things that we can’t do before, even some evil things.
If we have a function in interface which we want to label it as optional, we can add an empty implementation to it.
public interface A {
**default void a() {}**}
public Class realA implement A {// no need to implement a() again}
Beside the redundant smell, you should ask yourself if your interface takes too much responsibility which we can divide into different part. There’s no right or wrong, but do think one more second before you start to write.
Java doesn’t support multiple inheritance, but since the interface now can have implementation, it almost like a multiple inheritance-able language.
public interface A {default void common() {System.out.println("This is common a.");}}
public interface B {default void common() {System.out.println("This is common b.");}}
public Class realAB implement A, B {public void test() {common();}}
Which one will the common()
execute? A or B? The result is compile fail. Multi-inheritance is not only Java 8’s problem and here is the common solution: we should provide the context to the compiler.
public Class realAB implement A, B {public void test() {A.super.common(); // execute AB.super.common(); // execute B}}
Problem solved. But we should try to avoid the duplicate naming situation if possible.
If an interface contains some common implementations. It’s the best match for default methods. Here is a simple example.
public interface Callback<T> {void success(T t);
default void fail(String msg) {LogUtils.log(msg);UIUtils.showError(msg);}}
public Class ClassA implement Callback<A> {
public void success(A a) {// success A}}
public Class ClassB implement Callback<B> {
public void success(B b) {// success B}}
If every fail()
function has same logic, there’s no need to repeat ourself.
Default methods bring a new world to develop Java applications. But we still need to distinguish different role between Class, abstract Class and interface. We should leverage the power of default methods but still comply with our ground rule — an interface is an interface, not a Class or abstract Class.
Default Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)_This beginner Java tutorial describes fundamentals of programming in the Java programming language_docs.oracle.com