Calling Interface Default Method without Implementation in Java

Since Java 8, interfaces can have default methods. The default methods are already implemented in the interface, so if any class implements this interface then the class does not need to implement the method. It can simply refer to the method defined in the interface.

This Java tutorial discusses different ways to invoke/execute the interface default methods using the proxy objects which gives us freedom to not implement the interface in a class.

For demo purposes, we will use the interface Movable which has 3 methods:

  • move(): does not accept or return anything.
  • moveWithParamAndReturn(): accepts and returns a String value. You can change the types based on your requirements.
  • moveToImplement(): is non-default method that can only be invoked after a class implements the interface.
interface Movable {

  default void move() {
    System.out.println("Inside Movable.move()");
  }

  default String moveWithParamAndReturn(String param) {
    System.out.println("Inside Movable.moveWithParamAndReturn()");
    return STR."\{param}-returned";
  }

  void moveToImplement();
}

we will use the Proxy class that provides support for creating dynamic implementations of interfaces at runtime.

1. Calling Interface Default Methods (JDK 16 and Later)

Starting with JDK 16, we can use InvocationHandler.invokeDefault() method for invoking default methods. This method invokes the specified default method on the given proxy instance with the given parameters.

Let us see a demo of this method on Movable interface and call its default methods.

Movable movableProxy = (Movable) Proxy.newProxyInstance(
    Movable.class.getClassLoader(),
    new Class<?>[]{Movable.class}, (o, m, p) -> {
      if (m.isDefault()) {
        return InvocationHandler.invokeDefault(o, m, p);
      }
      return null;
    });

// invoke interface methods
movableProxy.move();
String returnedValue = movableProxy.moveWithParamAndReturn("lion");
System.out.println(returnedValue);

The program output:

Inside Movable.move()
Inside Movable.moveWithParamAndReturn()   //The parameter value is "lion"
lion-returned

2. Calling Interface Default Methods (Before Java 16)

After the introduction of the Java platform module system, Java Reflection API stopped providing access to non-public class members because the new module system relies on strong encapsulation.

But, we can use the MethodHandles class to call the default methods in an interface. The MethodHandles class exposes lookup methods for creating method handles for fields and methods. Once we have a Lookup, we can rely on its findSpecial() method to gain access to the default methods of an interface.

Movable movableProxy = (Movable) Proxy.newProxyInstance(
  Movable.class.getClassLoader(),
  new Class<?>[]{Movable.class}, (o, m, p) -> {
    if (m.isDefault()) {
      // Adjust the method type as per the default method's signature
      MethodType methodType;
      if (m.getName().equals("move")) {
        methodType = MethodType.methodType(void.class);
      } else if (m.getName().equals("moveWithParamAndReturn")) {
        methodType = MethodType.methodType(String.class, String.class);
      } else {
        throw new UnsupportedOperationException("Unknown default method: " + m.getName());
      }
      return MethodHandles.lookup()
          .findSpecial(Movable.class, m.getName(),
              methodType,
              Movable.class)
          .bindTo(o)
          .invokeWithArguments(p);
    }
    return null;
  });

movableProxy.move();
returnedValue = movableProxy.moveWithParamAndReturn("lion");
System.out.println(returnedValue);

The Program output:

Inside Movable.move()
Inside Movable.moveWithParamAndReturn()   //The parameter value is "lion"
lion-returned

3. Conclusion

This short Java tutorial listed two ready-to-use code snippets for invoking the default methods in an interface without implementing the interface in a class. This can be useful when we do not want to create a throw-away instance of a class just to call an interface default method.

Happy Learning !!

Source Code on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.