1

This is related to Java 8 interfaces. I have an interface which has only a default method. I can create an anonymous instance of this interface.

public interface Itest{
    default String get(){
            return "My name is ITest";
    }
}

public class A{
     Itest itest = new Itest(){};
}

I want to create an Utility function to which provided an Interface, returns the anonymous class. Something like the following

class MyUtil{
    public static <T> T get(Class<T> interface){
        // returns the anonymous class for the interface argument
        // Something like return new interface(){};
    }
}

public class A{
     Itest itest = MyUtil.get(Itest.class);
}

Some one help me if its possible and how to achieve it inside the MyUtil.get() function?

Usecase: I have few such interfaces(with default methods). Now if there is no implementation class available for these interfaces in a setup, I want to create anonymous class instance so that can call the default methods. This will save the effort to create the implementation classes when i just need these default methods itself.

D_K
  • 13
  • 3
  • 4
    Why exactly do you want to do that? What is your end goal? Why would `MyUtil.get(...)` help you with your goal? Because you just can't instantiate an interface from a `Class>` like you want to do, even if your interface contains only default method. You might get away with it by using a [`Proxy`](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Proxy.html) but it's *hard*. – Olivier Grégoire Jun 10 '20 at 09:59
  • Thanks for the suggestion @OlivierGrégoire. Regarding the usecase: I will have many interfaces with default methods. For each interface there can be multiple implementation based on the platform. But mostly will use the default method. Therefore wanted to avoid creating empty impl classes if possible. Hence was looking to create a Util method which can either create a newInstance() if the implementation class is available or return an anonymous class. This Util method will help me handle these interfaces at one place. Hope this answers the question. – D_K Jun 10 '20 at 13:20

3 Answers3

0

I don't think it is possible to create instances of an interface using Class<?>. Have you tried bypassing the MyUtil class and just make all the intefaces methods static. This would enable you to call those methods without having to initiate them. For example:

public interface Itest {
    static String get() {
        return "My name is ITest";
    }
}


public class TryingItest {

    public static void main(String[] args) {
        System.out.println(Itest.get());
    }

}

This will separate the parts of your interface which need implementing and those that are static. Hope this helps.

Chandz
  • 21
  • 4
  • Thanks for the solution. But then i had a different use case. There can be multiple impl classes for an interface based on the platform. Most of the impl classes will use the default method which may not be static. So was trying if I can avoid creating these empty impl classes and only implement the one needed.MyUtil.get() can then provide the impl class(if exists) or create the anonymous class. Also I will be having multiple such interfaces. Hence was looking to create an Util method to resolve all the interfaces. – D_K Jun 10 '20 at 13:14
0

This is very interesting question. The first solution that came to my mind was a simple instantiation:

public static <T> T get(Class<T> clazz) throws ... {
    return clazz.getDeclaredConstructor().newInstance();
}

But it results in:

java.lang.NoSuchMethodException: my.package.Itest.()

Remember interfaces have no constructors and cannot be instantiated directly.

Step 1: Create dynamic proxy class

You have to use java.lang.reflect.Proxy to create a dynamic proxy class representing an anonymous class implementing interface.

public static <T> T get(Class<T> clazz) {
    return (T) java.lang.reflect.Proxy.newProxyInstance(
        clazz.getClassLoader(),
        new java.lang.Class[] { clazz },
        (proxy, method, args) -> null
    );
}

Usage:

Itest itest = MyUtil.get(Itest.class);
System.out.println(itest.getClass().getName());  // com.sun.proxy.$Proxy2
System.out.println(itest instanceof Shit.Itest); // true

// all methods invokation are completely ignored (returning null)
System.out.println(itest.get());                 // null 

The lambda expression for the InvocationHandler::invoke always returns null regardless what method with whaat arguments is called as long as it is an "empty wrapper".

Step 2: Invoke default method

As long as you want to call a default method, you can use a modified simple trick answered at How do I invoke Java 8 default methods reflectively:

public static <T> T get(Class<T> clazz) {
    return (T) java.lang.reflect.Proxy.newProxyInstance(
        clazz.getClassLoader(),
        new java.lang.Class[]{clazz},
        (proxy, method, args) -> {
            if (method.isDefault()) {
                return MethodHandles.lookup()
                    .in(method.getDeclaringClass())
                    .unreflectSpecial(method,method.getDeclaringClass())
                    .bindTo(proxy)
                    .invokeWithArguments(args);
            }
            return null;
        }
    );
}

Here we go:

Itest itest = MyUtil.get(Itest.class);
System.out.println(itest.getClass().getName());  // com.sun.proxy.$Proxy2
System.out.println(itest instanceof Shit.Itest); // true

// default methods are invoked, the implementation is taken from the interface
System.out.println(itest.get());                 // My name is ITest
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • Thanks for the snippet. It works on Java 8 with some additional changes based on [link](https://stackoverflow.com/a/58800339/12011111) ``final Constructor constructor = Lookup.class.getDeclaredConstructor(Class.class); constructor.setAccessible(true) ; `` – D_K Jun 10 '20 at 17:23
  • So, is you issue resolved? I am glad I pointed you at least to a right direction. – Nikolas Charalambidis Jun 10 '20 at 17:34
-1
interface Itest{
    default String get(){
            return "My name is ITest";
    }
}

class ITestImpl implements Itest {

}

class MyUtil{
    public static <T extends Itest> T get(Class<T> impl) {
        try {
            return impl.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }
}

then

Itest test = MyUtil.get(ITestImpl.class);
SoT
  • 898
  • 1
  • 15
  • 36
  • 1
    Tested that? I'm pretty sure this will fail if `impl` represents an `interface` – Gyro Gearless Jun 10 '20 at 10:21
  • There can be multiple impl classes based on the platform. Most of the impl classes will use the default method. So was trying if I can avoid creating these empty impl classes and only implement the one needed.MyUtil.get() can then provide the impl class or create the anonymous class. – D_K Jun 10 '20 at 13:08