Java:从作为参数传递的接口创建匿名类

Java:从作为参数传递的接口创建匿名类,java,generics,interface,anonymous-class,Java,Generics,Interface,Anonymous Class,这与Java8接口有关。我有一个只有默认方法的接口。我可以创建此接口的匿名实例 public interface Itest{ default String get(){ return "My name is ITest"; } } public class A{ Itest itest = new Itest(){}; } 我想创建一个实用函数,为其提供一个接口,返回匿名类。类似于下面的内容 class MyUtil{ public

这与Java8接口有关。我有一个只有默认方法的接口。我可以创建此接口的匿名实例

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

public class A{
     Itest itest = new Itest(){};
}
我想创建一个实用函数,为其提供一个接口,返回匿名类。类似于下面的内容

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);
}

如果可能,有人会帮助我,以及如何在MyUtil.get函数中实现它


用例:我很少有这样的带有默认方法的接口。现在,如果设置中没有可用于这些接口的实现类,我想创建匿名类实例,以便调用默认方法。当我只需要这些默认方法本身时,这将节省创建实现类的工作量。

我认为使用类创建接口实例是不可能的。您是否尝试过绕过MyUtil类,将所有的intefaces方法都设置为静态。这将使您能够调用这些方法,而无需启动它们。例如:

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;
        }
    }
}
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());
    }

}

这将分离接口中需要实现的部分和静态的部分。希望这有帮助。

这是一个非常有趣的问题。我想到的第一个解决方案是一个简单的实例:

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

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 
的lambda表达式始终返回null,只要它是空包装器,则不管调用哪个具有what参数的方法

步骤2:调用默认方法

只要您想调用默认方法,就可以使用修改后的简单技巧,回答如下:


你到底为什么要这么做?你的最终目标是什么?为什么MyUtil会得到。。。帮助你实现你的目标?因为即使您的接口只包含默认方法,也不能像您希望的那样从类实例化接口。你可能会通过使用a来逃脱,但这很难。谢谢你的建议@OlivierGrégoire。关于用例:我将有许多带有默认方法的接口。对于每个接口,可以有基于平台的多个实现。但大多数情况下将使用默认方法。因此,我们希望尽可能避免创建空的impl类。因此,我们希望创建一个Util方法,该方法可以在实现类可用时创建一个新实例,也可以返回一个匿名类。这个Util方法将帮助我在一个地方处理这些接口。希望这能回答问题。测试过了吗?我敢肯定,如果impl代表一个接口,那么这将失败。基于这个平台,可以有多个impl类。大多数impl类将使用默认方法。因此,我正在尝试是否可以避免创建这些空的impl类,而只实现所需的一个。MyUtil.get然后可以提供impl类或创建匿名类。感谢您提供的解决方案。但是我有一个不同的用例。基于平台的接口可以有多个impl类。大多数impl类将使用默认方法,该方法可能不是静态的。因此,我正在尝试是否可以避免创建这些空的impl类,并且只实现所需的类。MyUtil.get然后可以提供impl classif exists或创建匿名类。此外,我将有多个这样的接口。因此,我们希望创建一个Util方法来解析所有接口。感谢您的代码片段。它在Java 8上工作,并根据最终构造函数=Lookup.class.getDeclaredConstructorClass.class进行了一些额外的更改;constructor.setAccessibletrue;那个么,你们的问题解决了吗?我很高兴我至少为你指出了一个正确的方向。
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
    );
}
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 
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;
        }
    );
}
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