java - 执行特定的参数化类方法

标签 java generics methods

我有这个(简化的)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您检查提供的参数是否可以安全地转换为 MyInterfacetype() 。如果是的话你可以转换整个 MyInterfacearg的类型。这是未检查的,因为编译器无法将其验证为编译时,但当您手动进行检查时,可以忽略此警告。

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/

相关文章:

java - 红5 1.0.7M10 : Could not find or load main class Files

c# - 我们应该为新项目选择 Java 而不是 C# 吗?

java - Ping Sweep,能够进入某个范围

php - 您可以从 PHP 中的方法中获取方法名称吗?

java - 本程序无法显示网页:

c# - 从通用列表底部删除重复项

java - Spring Data JPA 如何为多个实体构建通用存储库?

java - 如何创建一个方法来接受并返回任何类型的 ObjectProperty<?>?

java - 在不同的 Java 方法中访问变量

java - 可以接受一个或两个参数但不能超过两个的函数