Monday, April 10, 2023

Default Methods and Multiple Inheritance in Java 8

Ever since Java 8 introduced default and static methods in JDK 8, it's become possible to define non-abstract methods in interfaces. Since Java, one class can implement multiple interfaces and because there can be concrete methods in interfaces, the diamond problem has surfaced again. What will happen if two interfaces have methods o the same name and a Java class inherit from it? Many Java programmer also asks me the question that, is Java 8 is also supporting multiple inheritances of classes? Well, it's not but the doubt is genuine because the interface with methods is similar to an abstract class or in that any Class in Java.

In theory, it does look like that but in detail, you will find that Java designers have made sure that the diamond problem should not occur because of default methods on the interface from Java 8 onwards.

If you look closely, you will find that multiple inheritances of classes are not supported in Java 8, instead, the compiler will do additional checks to avoid ambiguity in calling default methods and Diamond problem, which could come if a class implements two interfaces that contain the default methods with the same name.

We'll explore this concept with a proper code example in the coming section but let me tell you that this feature is so underrated yet it has made the biggest impact in terms of evolving JDK API.

Without default and static methods on an interface, it wasn't possible to add new methods on an interface and put the years of learning Java designer has after publishing JDK API.

Now, we have methods like putIfAbsent() on Map interface and comparing() on Comparator class which makes day-to-day coding in Java more effective. All this is possible because of default methods and static methods on the interface.

Btw, Java 8 is not just about default methods, it's full of useful features like lambda expressions, Stream API, new Date Time API, and many minor API changes like the join() method on String. If you are interested to learn those gems, I suggest you join the Java New Features (Java 12, Java 11, Java 10, Java9 & Java8) course on Udemy. One of the short and sweet courses to learn Java 8 to Java 12 in a quick time.




An Example of Diamond Problem with Default Methods

Here is an example to explain that concept. As shown below, this code will not compile in Java 8, because of ambiguity in calling the default method write() from a class, which extends both Poet and Writer interface.

interface Poet {
    default void write() {
        System.out.println("Poet's default method");
    }
}

interface Writer {
    default void write() {
        System.out.println("Writer's default method");
    }
}

public class Multitalented implements Poet, Writer{
   
    public static void main(String args[]){
        Multitalented john = new Multitalented();
        john.write();  // which write method to call, from Poet
                       // or, from Writer
    }
}

Output:
Compile Time Error : class Multitalented inherits unrelated 
defaults for write() from types Poet and Writer


You can see that both Poet and Writer interface have a default method write() and when we have created a class Multitalented, which implements both Poet and Writer it gets the write() method from both super interface Poet and Writer.

Now, the problem is not that we have implemented two interfaces with default methods of the same name. The Actual problems come when we created an object of a Multitalented class and called the write() method on its object.

At this point in time, the compiler doesn't know that which write() method should call because of ambiguity and that results in the compiler error you have seen above.

Btw, if you are not familiar with how to interface and class works in Java, and how the compiler resolves a particular method call, I suggest you first read a comprehensive Java course like The Complete Java MasterClass on Udemy. It's one of the best courses and also very affordable. It's also the most up-to-date and recently updated for Java 11.

Default Methods, Multiple Inheritance and Diamond Problem in Java 8



How to avoid Diamond Problem With Default Methods in Java 8

In order to solve this error, you need to override the write() method in your implementation class i.e. class Multitalented here, this will remove the ambiguity, making the compiler happy enough to compile this class.

public class Multitalented implements Poet, Writer{
   
    @Override
    public void write(){
        System.out.println("Writing stories now days");
    }
   
    public static void main(String args[]){
        Multitalented john = new Multitalented();
        john.write();  // This will call Multitalented#write() method
    }
}
Output:
Writing stories now days

So until you don't create ambiguity by using default methods on interfaces, you are fine to use it. If it creates ambiguity, the compiler will alert you by throwing a compile-time error "inherits unrelated defaults".


Related Java 8 Tutorials
If you are interested in learning more about the new features of Java 8, here are my earlier articles covering some of the important concepts of Java 8:
  • 5 Free Courses to learn Java 8 and Java 9 (courses)
  • 5 Books to Learn Java 8 from Scratch (books)
  • How to join String in Java 8 (example)
  • 10 Advanced Core Java Courses for Developers (courses)
  • How to use filter() method in Java 8 (tutorial)
  • 10 Free courses for Fullstack Java developers (free courses)
  • How to format/parse the date with LocalDateTime in Java 8? (tutorial)
  • How to use Stream class in Java 8 (tutorial)
  • How to convert List to Map in Java 8 (solution)
  • 20 Examples of Date and Time in Java 8 (tutorial)
  • How to use peek() method in Java 8 (example)
  • How to sort the map by keys in Java 8? (example)
  • How to sort the may by values in Java 8? (example)
  • 10 examples of Optional in Java 8? (example)
  • Difference between abstract class and interface in Java 8? (answer)
  • Top 5 Online Courses to Master Java 8 Concepts (courses)

Thanks for reading this article so far. If you like this explanation of default methods, multiple interfaces, and diamond problems in Java then please share it with your friends and colleagues. If you have any questions or feedback then please drop a comment.

P. S.: If you just want to learn more about new features in Java 8 then please see the course What's New in Java 8. It explains all the important features of Java 8 like lambda expressions, streams, functional interfaces, Optional, new Date Time API, and other miscellaneous changes.

4 comments:

  1. You have to remove one interface from the successful example otherwise it gives you compilation error like below

    "Default methods are allowed only in interfaces with source level 1.8 or greater."

    ReplyDelete
  2. Thats because you are not using Java 1.8.

    ReplyDelete
  3. You can choose in the Multitalented overriden method which one to use:

    @Override
    public void write() {
    Poet.super.write();
    }



    ReplyDelete
  4. "Ever since Java 8 introduced default and static methods in JDK 8, it's become possible to define non-abstract methods in interfaces"

    This is such a bad addition to the java language. It ruins the purpose of a interface by basically turning it into an abstract class.

    ReplyDelete

Feel free to comment, ask questions if you have any doubt.