这与Java 8接口有关。我有一个接口,它只有一个默认方法。我可以为这个接口创建一个匿名的实例。
public interface Itest{
default String get(){
return "My name is ITest";
}
}
public class A{
Itest itest = new Itest(){};
}
我想创建一个 Utility 函数,向其中提供一个 Interface,返回匿名类。类似于下面的东西,我想创建一个Utility函数,向其中提供一个Interface,返回匿名类。
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()函数中如何实现?
用例。我有几个这样的接口(有默认方法)。现在,如果在设置中没有这些接口的实现类,我想创建一个匿名类实例,这样就可以调用默认方法。当我只需要这些默认方法时,这样就可以省去创建实现类的工作。
这是一个非常有趣的问题。我想到的第一个解决方案是一个简单的实例化。
public static <T> T get(Class<T> clazz) throws ... {
return clazz.getDeclaredConstructor().newInstance();
}
但它的结果是:
java.lang.NoSuchMethodException: my.package.Itest.()
记住接口没有构造函数,不能直接实例化。
第一步:创建动态代理类
你必须使用 java.lang.reflect.Proxy
来创建一个动态代理类,代表一个实现接口的匿名类。
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
的lambda表达式。InvocationHandler::invoke
总是返回 null
无论调用什么参数的方法,只要它是一个 "空包装 "就可以了。
第二步:调用默认方法
只要你想调用一个默认的方法,你就可以使用一个修改后的简单技巧,答案在 如何反思性地调用Java 8默认方法?:
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
我认为不可能使用以下方法来创建接口的实例: Class<?>
. 你有没有试过绕过MyUtil类,把所有的intefaces方法都做成静态的。这将使你能够调用这些方法而无需启动它们。比如说,你可以把你的接口中需要实现的部分和需要静态化的部分分开。
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());
}
}
这将把你的接口中需要实现的部分和静态的部分分开. 希望这能帮到你。
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;
}
}
}
那么
Itest test = MyUtil.get(ITestImpl.class);