• Software
  • Leadership
  • Agile
  • Events
  • Other Topics
    • Finance
    • Robotics & AI
    • System Administration
    • Books
    • Life Experiences
    • Environment
  • Write and Earn
  • About Us
    • About Us
    • Our Contributors
    • Contact Us
    • Article Submission Guidelines
    • Logo demystified
  • Follow @MeJaneve
    Janeve.Me
  • Categories

    Browse through following categories for articles written by professionals.
    • Agile
      4
    • Books
      5
    • Environment
      1
    • Events and Conferences
      7
    • Featured
      9
    • Finance
      1
    • Leadership
      6
    • Life Experiences
      8
    • Robotics & AI
      1
    • Software
      30
    • System Administration
      2
  • Software
  • Leadership
  • Agile
  • Events
  • Other Topics
    • Finance
    • Robotics & AI
    • System Administration
    • Books
    • Life Experiences
    • Environment
  • Write and Earn
  • About Us
    • About Us
    • Our Contributors
    • Contact Us
    • Article Submission Guidelines
    • Logo demystified
Home » Software

Default and Static Methods in Java 8

Janeve George Posted On April 25, 2020
0
1.1K Views


0
Shares
  • Share On Facebook
  • Tweet It

java versions and java features

Default methods and Static methods were introduced in Java 8. Before Java 8, all methods in an interface were public and abstract by default. Java 8 allows developers to add new methods in interfaces without making any changes in the classes that implement these interfaces.

The need for default and static methods

Consider a scenario in which there is an interface Sortable<T> that has two methods: void sort(); and T peek();. There could be several classes that implement the interface Sortable<T>. For example: SortableNumberCollection and SortableStringCollection.

Before Java 8, If we have to now add a new method String sortAndPeek() to the Sortable<T> interface, then it would result in changing all the classes that implement the interface. It may also result in duplicate code if the logic of the method implemented by the classes is the same. This could become even more difficult if the interface is part of a library used in many software solutions or if there are hundreds of classes that may be implementing the interface.

In Java 8, this problem can be resolved by implementing a ‘default method’. A default method can be added to any existing interfaces without the need to modify the classes that implement it. The default methods provide a capability for the interface to be backward compatible. It also reduces duplicate code when the implementation of the method is supposed to be the same.

The ‘static methods’ are similar to default methods, except that they cannot be overridden by the implementing classes.

Why don’t we use Abstract classes instead of Interfaces?

The basic concept of interfaces and abstract classes is different according to OOPs principles. The abstract classes are typically used where there is an ‘is a’ relation. For example, the classes: Car, Van, Ship, and Airplane can be a subclass of an abstract class Vehicle. These classes have an ‘is a’ relationship with the abstract class. E.g: Car ‘is a’  Vehicle.

Interfaces, on the other hand, are used to specify contracts or behavior of unrelated subclasses. It has a ‘is’ relationship. For example, both Car and Van can implement an interface Drivable and implement a method boolean drive(). Unrelated classes like RemoteControlledToyCar, AngerEmotion could also implement the Drivable interface.

The Ship and Airplane classes could implement other interfaces like Sailable and Flyable respectively with very different methods. These classes have an ‘is’ relationship with the interface. E.g: Car ‘is’  Drivable.

The abstract classes are partial abstractions that could have constructors that can be called by the subclasses. The interfaces provide full abstractions and do not contain constructors.

Read more about in “When to Use Abstract Class and Interface”.

Example of default method in Java 8

Let us consider the Sortable<T> interface and the classes, SortableNumberCollection and SortableStringCollection, that implement the interface. The interface has two methods: void sort(); and T peek();.

public interface Sortable<T> {
    void sort();
    T peek();
}

The void sort(); method in the interface can be called to sort items. The T peek(); method in the interface could be used to get a particular item.

We would need a comparator class ObjectComparator to perform comparisons of two items so that it can be used for sorting.

public class ObjectComparator implements Comparator<Comparable> {
    @Override
    public int compare(Comparable o1, Comparable o2) {
        return o1.compareTo(o2);
    }
}

The SortableStringCollection is a custom collection class that holds a list of strings that could be sorted and peeked using the interface methods. The implementation of the class would be:

public class SortableStringCollection implements Sortable<String> {

    private List<String> items = new ArrayList<>();

    public void add(String item) {
        items.add(item);
    }

    @Override
    public void sort() {
        items.sort(new ObjectComparator());
    }

    @Override
    public String peek() {
        return items.get(0);
    }
}

Similarly, the SortableNumberCollection is a custom collection class that holds a list of numbers that could be sorted and peeked using the interface methods. The implementation of the class would be:

public class SortableNumberCollection implements Sortable<Integer> {

    private List<Integer> items = new ArrayList<>();

    public void add(Integer item) {
        items.add(item);
    }

    @Override
    public void sort() {
        items.sort(new ObjectComparator());
    }

    @Override
    public Integer peek() {
        return items.get(0);
    }
}

Adding a new method “before Java 8”

Now let us take the scenario when we need to add a new method T sortAndPeek(); to the Sortable<T> interface. This method would internally call the void sort(); method followed by T peek(); method. The implementation of the interface and the classes would be:

public interface Sortable<T> {
    void sort();
    T peek();
    T sortAndPeek();    // New method added.
}

All the classes that implement this interface will now have to implement the method. In our example, the SortableStringCollection and the SortableNumberCollection classes should implement this method. The implementation of the class would be:

public class SortableStringCollection implements Sortable<String> {

    private List<String> items = new ArrayList<>();

    public void add(String item) {
        items.add(item);
    }

    @Override
    public void sort() {
        items.sort(new ObjectComparator());
    }

    @Override
    public String peek() {
        return items.get(0);
    }

    @Override
    public String sortAndPeek() {    // Implemeting the new method.
        sort();
        return peek();
    }
}
public class SortableNumberCollection implements Sortable<Integer> {

    private List<Integer> items = new ArrayList<>();

    public void add(Integer item) {
        items.add(item);
    }

    @Override
    public void sort() {
        items.sort(new ObjectComparator());
    }

    @Override
    public Integer peek() {
        return items.get(0);
    }

    @Override
    public Integer sortAndPeek() {    // Implemeting the new method.
        sort();
        return peek();
    }
}

If there were 100 more such classes, it would have been a very difficult task to manage all of them.

Adding a new method in “Java 8 and above”

The ‘default methods’ in Java 8 makes it easier to add a new method T sortAndPeek(); to the Sortable<T> interface without any changes required for the classes that implement it. The implementation of the interface in java 8 would be:

public interface Sortable<T> {
    void sort();
    T peek();

    default T sortAndPeek(){    // New 'default method' added in the interface
        sort();
        return peek();
    }

}

The original SortableStringCollection and the SortableNumberCollection classes wouldn’t need any changes. The implementation of the class would remain the same:

public class SortableStringCollection implements Sortable<String> {

    private List<String> items = new ArrayList<>();

    public void add(String item) {
        items.add(item);
    }

    @Override
    public void sort() {
        items.sort(new ObjectComparator());
    }

    @Override
    public String peek() {
        return items.get(0);
    }
}
public class SortableNumberCollection implements Sortable<Integer> {

    private List<Integer> items = new ArrayList<>();

    public void add(Integer item) {
        items.add(item);
    }

    @Override
    public void sort() {
        items.sort(new ObjectComparator());
    }

    @Override
    public Integer peek() {
        return items.get(0);
    }
}

It is also possible to override the default implementation of the method in any of the classes that implement this interface if need be.

Resolving default methods in multiple inheritances

If two or more interfaces have the same default method signature and a class implements both the interfaces, it would throw a compile-time error. For example:

public interface Interface1 {
    void methodOne(String str);
    default void newMethod(){
        System.out.println("Interface1: Newly added method");
    }
}



public interface Interface2 {
    void methodTwo(String str);
    default void newMethod(){
        System.out.println("Interface2: Newly added method");
    }
}



public class InterfaceImplementation implements Interface1, Interface2{
    @Override
    public void methodOne(String str) {
        System.out.println("Overridden methodOne: " + str);
    }

    @Override
    public void methodTwo(String str) {
        System.out.println("Overridden methodTwo: " + str );
    }
}

The compilation of the class InterfaceImplementation would result in the following compile-time error message:

InterfaceImplementation inherits unrelated defaults for newMethod from types Interface1 and Interface2

To resolve this problem, we will have to override the method in the class InterfaceImplementation:

public class InterfaceImplementation implements Interface1, Interface2{
    @Override
    public void methodOne(String str) {
        System.out.println("Overridden methodOne: " + str);
    }

    // newMethod implemented to resolve the conflict.
    @Override
    public void newMethod() {
        System.out.println("InterfaceImplementation: Newly added method");
    }

    @Override
    public void methodTwo(String str) {
        System.out.println("Overridden methodTwo: " + str );
    }
}

Adding a static method in Java 8

‘Static methods’ can also be added in interfaces, just like ‘default methods’. For example, we can add a static method Direction getDefaultDirection() that would return a default direction like:

public interface Sortable<T> {

    Direction defaultDirection = Direction.DESC;

    enum Direction {
        ASC,
        DESC
    };

    void sort();
    T peek();

    static Direction getDefaultDirection(){    // 'static method' added to the interface.
        return defaultDirection;
    }
}

In the above example, the static Direction getDefaultDirection() method can be called using the class reference:

Sortable.getDefaultDirection()

See the complete source code in my github repository.

Post Views: 1,095
0
Shares
  • Share On Facebook
  • Tweet It




Author

Janeve George

A Technology Leader, Software Engineer, and Agile Methodologies enthusiast. Currently, working as Lead Software Development with Zeta Suite. He has more than 1.8 decades of experience spanning different verticals predominated by hosting, cloud, and media delivery technologies.

Local Variable Type Inference in Java 10
Read Next

Local Variable Type Inference in Java 10

  • Follow @MeJaneve
    Janeve.Me
  • Categories

    Browse through following categories for articles written by professionals.
    • Agile
      4
    • Books
      5
    • Environment
      1
    • Events and Conferences
      7
    • Featured
      9
    • Finance
      1
    • Leadership
      6
    • Life Experiences
      8
    • Robotics & AI
      1
    • Software
      30
    • System Administration
      2

  • Popular Posts

  • Recent Posts

    • 3Es to Supercharge your Career Journey and Performance Review Ratings
    • Java Asynchronous Programming using CompletableFuture - Part 1
    • The Java Stream API
    • Functional Interfaces in Java
  • Keep In Touch

    Follow us on social media to get latest articles on Programming, System Architecture, Agile Development Methodologies, Product and Project Management, Personal Development, BigData, Robotics, Upcoming Events and more...


Copyright © 2020 | Janeve.Me. All rights Reserved.
Press enter/return to begin your search