我有这个(简化的)java接口(interface)
public interface MyInterface<T> {
public String run( T arg );
}
以及一些实现该接口(interface)的类,即
public final class SomeImplementation1 implements MyInterface<String> {
@Override
public String run( String arg) {
// do something with arg and return a string
}
}
和
public final class SomeImplementation2 implements MyInterface<CustomClass> {
@Override
public String run( CustomClass arg) {
// do something with arg and return a string
}
}
现在,我有一个用于所有这些实现的全局资源管理器,它将所有这些实现实例化在列表中以供以后使用。我想要实现的是这样的,这显然给了我一个错误
public final class MyInterfaceManager {
private List<MyInterface<?>> elements = new List<MyInterface<?>>();
public MyInterfaceManager() {
elements.put( new SomeImplementation1() );
elements.put( new SomeImplementation2() );
// more implementations added
}
// this is what I would like to achieve
public <T> void run( T arg ) {
for( MyInterface<?> element: elements ) {
String res = element.run( arg ); // ERROR
}
}
}
因为“arg 无法通过方法调用转换转换为 ? 的 capture#1”。
一个可能的解决方案是在循环内执行 instanceof
测试,并将元素连同参数一起转换为其真实类型,就像这样
public <T> void run( T arg ) {
for( MyInterface<T> element: elements ) {
if (element instanceof SomeImplementation2) {
String res = ((SomeImplementation2)element).run( (CustomClass)arg );
} else if // other tests here ...
}
}
但我不喜欢它,它一点也不优雅,而且它迫使我做很多 instanceof
和强制转换。
所以,我想知道是否有更好的方法来实现这一目标。
感谢您的帮助:)
最佳答案
您正在遇到type erasure 。您需要将另一个方法添加到 interface
返回 Class
与类型参数 <T>
相关的实例,这将允许您对 Class
进行运行时检查.
我会这样完成这个:
public interface MyInterface<T> {
String run( T arg );
Class<T> type();
}
所以interface
返回其类型。注意:所有interface
成员是public
默认情况下 - 不需要额外的 public
.
public final class SomeImplementation1 implements MyInterface<String> {
@Override
public String run(final String arg) {
return arg;
}
@Override
public Class<String> type() {
return String.class;
}
}
@SuppressWarnings({"unchecked"})
public static <T> String run(final T arg) {
for (final MyInterface<?> element : elements) {
if (element.type().isAssignableFrom(arg.getClass())) {
return ((MyInterface<T>) element).run(arg);
}
}
throw new IllegalArgumentException("No element found.");
}
逻辑是对于每个 MyInterface
您检查提供的参数是否可以安全地转换为 MyInterface
的type()
。如果是的话你可以转换整个 MyInterface
到arg
的类型。这是未检查的,因为编译器无法将其验证为编译时,但当您手动进行检查时,可以忽略此警告。
public static void main(String[] args) throws Exception {
elements = new LinkedList<>();
elements.add(new SomeImplementation1());
System.out.println(run("test"));
System.out.println(run(1));
}
输出:
test
Exception in thread "main" java.lang.IllegalArgumentException: No element found.
at com.XXX.App.run(App.java:33)
at com.XXX.App.main(App.java:55)
正如预期的那样。
关于java - 执行特定的参数化类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19016447/