如何迭代通配符泛型?

roe*_*erj 8 java generics foreach

如何迭代通配符通用?基本上我想内联以下方法:

private <T extends Fact> void iterateFacts(FactManager<T> factManager) {
    for (T fact : factManager) {
        factManager.doSomething(fact);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果此代码在如图所示的单独方法中,则它起作用,因为泛型方法上下文允许定义通配符类型(此处T)可以迭代.如果尝试内联此方法,则方法上下文消失,并且不再迭代通配符类型.即使在Eclipse中自动执行此操作也会失败并显示以下(无法编译)代码:

...
for (FactManager<?> factManager : factManagers) {
    ...
    for ( fact : factManager) {
        factManager.doSomething(fact);
    }
    ...
}
...
Run Code Online (Sandbox Code Playgroud)

我的问题很简单:有没有办法放一些可以迭代的通配符类型,或者这是泛型的限制(意味着不可能这样做)?

irr*_*ble 5

在这种情况下,解决方法是创建一个辅助方法.

JLS有这个例子http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.10

public static void reverse(List<?> list) { rev(list);}
private static <T> void rev(List<T> list) { ... }
Run Code Online (Sandbox Code Playgroud)

问题是,我们有一个List<?>对象.我们知道它必须是List<X>一些X,我们想用代码编写代码X.内部编译器确实将通配符转换为类型变量X,但Java语言不能为程序员提供访问它的直接方法.但是如果有方法接受List<T>,我们可以将对象传递给方法.编译器推断出这个T=X并且通话很好.

如果没有类型擦除,X可以在运行时知道,那么Java肯定会给我们一种访问方式X.但是截至今天,由于X在运行时不可用,因此没有多大意义.可以提供纯粹的合成方式,这不太可能比辅助方法更简单.


Paŭ*_*ann 3

类型参数只能定义在

  • 类型(即类/接口),
  • 方法,以及
  • 构造函数。

您需要本地块的类型参数,这是不可能的。

是的,我有时也会错过这样的事情。

但这里的方法非内联并不是真正的问题 - 如果它出现内联会有所帮助的性能瓶颈,Hotspot 将再次内联它(不关心类型)。

此外,拥有一个单独的方法可以给它一个描述性的名称。


只是一个想法,如果你经常需要这个:

interface DoWithFM {
   void <T> run(FactManager<T> t);
}

...
for (FactManager<?> factManager : factManagers) {
    ...
    new DoWithFM() { public <T> run(FactManager<T> factManager) {
        for (T fact : factManager) {
            factManager.doSomething(fact);
        }
    }.run(factManager);
    ...
}
...
Run Code Online (Sandbox Code Playgroud)