Java:从作为参数传递的接口创建匿名 class
Java: Creating an anonymus class from a interface passed as an argument
这与Java8个接口有关。我有一个只有默认方法的接口。我可以创建此接口的匿名实例。
public interface Itest{
default String get(){
return "My name is ITest";
}
}
public class A{
Itest itest = new Itest(){};
}
我想创建一个提供接口的实用函数,returns 匿名 class。类似下面的内容
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() 函数中实现它?
用例:我很少有这样的接口(有默认方法)。现在,如果在设置中没有可用于这些接口的实现 class,我想创建匿名 class 实例,以便可以调用默认方法。当我只需要这些默认方法本身时,这将节省创建实现 classes 的工作。
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);
我认为无法使用 Class<?>
创建接口实例。您是否尝试过绕过 MyUtil class 并将所有接口方法设为静态。这将使您能够调用这些方法而无需启动它们。例如:
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();
}
但结果是:
java.lang.NoSuchMethodException: my.package.Itest.()
记住接口没有构造函数,不能直接实例化。
第 1 步:创建动态代理 class
您必须使用 java.lang.reflect.Proxy
创建动态代理 class 表示匿名 class 实现接口。
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
InvocationHandler::invoke
的 lambda 表达式总是 returns null
不管调用什么方法,只要它是一个 "empty wrapper".
第 2 步:调用默认方法
只要你想调用一个默认的方法,你可以使用修改后的简单技巧在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;
}
);
}
我们开始:
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
这与Java8个接口有关。我有一个只有默认方法的接口。我可以创建此接口的匿名实例。
public interface Itest{
default String get(){
return "My name is ITest";
}
}
public class A{
Itest itest = new Itest(){};
}
我想创建一个提供接口的实用函数,returns 匿名 class。类似下面的内容
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() 函数中实现它?
用例:我很少有这样的接口(有默认方法)。现在,如果在设置中没有可用于这些接口的实现 class,我想创建匿名 class 实例,以便可以调用默认方法。当我只需要这些默认方法本身时,这将节省创建实现 classes 的工作。
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);
我认为无法使用 Class<?>
创建接口实例。您是否尝试过绕过 MyUtil class 并将所有接口方法设为静态。这将使您能够调用这些方法而无需启动它们。例如:
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();
}
但结果是:
java.lang.NoSuchMethodException: my.package.Itest.()
记住接口没有构造函数,不能直接实例化。
第 1 步:创建动态代理 class
您必须使用 java.lang.reflect.Proxy
创建动态代理 class 表示匿名 class 实现接口。
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
InvocationHandler::invoke
的 lambda 表达式总是 returns null
不管调用什么方法,只要它是一个 "empty wrapper".
第 2 步:调用默认方法
只要你想调用一个默认的方法,你可以使用修改后的简单技巧在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;
}
);
}
我们开始:
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