在eclipse中强制转换泛型类但在javac中出错

时间:2016-04-21 15:31:52

标签: java eclipse javac

我发现Eclipse和javac之间在以下代码中的行为存在重大差异:

public class TestIncompatibleTypes {

    private static <V> void libraryMethod(Class<? extends List<V>> in) {}

    public static void main(String[] args) {
        // Eclipse warns about 'Unchecked cast'
        // Maven fails with 'incompatible types'
        Class<? extends List<String>> l = (Class<? extends List<String>>) ArrayList.class;
        libraryMethod(l);
    }
}

Eclipse会发布未经检查的广告素材&#39;警告上面的代码,但它成功编译。 Javac生成错误:

$ java -version
openjdk version "1.8.0_72-internal"
OpenJDK Runtime Environment (build 1.8.0_72-internal-b15)
OpenJDK 64-Bit Server VM (build 25.72-b15, mixed mode)
$ javac -version
javac 1.8.0_72-internal
$ javac -source 8 TestIncompatibleTypes.java
TestIncompatibleTypes.java:13: error: incompatible types: Class<ArrayList> cannot be converted to Class<? extends List<String>>
        Class<? extends List<String>> l = (Class<? extends List<String>>) ArrayList.class;
                                                                                   ^
1 error

任何人都可以解释为什么javac不允许演员?我的理解是它们在类型擦除后应该完全等效。

是否有解决方法可以在两个编译器上进行编译?

2 个答案:

答案 0 :(得分:3)

  

是否有解决方法可以在两个编译器上进行编译?

Class<? extends List<String>> clazz;
// casting to interim type
clazz = (Class<? extends List<String>>) (Class<? extends List>) ArrayList.class;
// raw types .......
clazz = (Class) ArrayList.class;

无论其!这段代码值得解释它为何起作用以及何时可能不安全:

  • java.util.ArrayList对其类型变量没有特别限制。
  • java.lang.Class是不可变的,只能用于创建新实例。

如果您使用除ArrayListClass之外的其他类型,则此相同的转换可能会导致堆污染。丢掉重要信息:

class IntegerList extends ArrayList<Integer> {}
// now we can create a new instance and put String in a List<Integer>
Class<? extends List<String>> clazz =
    (Class<? extends List<String>>) (Class<? extends List>) IntegerList.class;

(我还要注意,使用ArrayList.class仍然可能导致堆污染,而我对它的思考还不够。)

在Java 8中,我们应该首选lambda来实现创建,这可以避免这个问题:

static <V> void libraryMethod(Supplier<? extends List<V>> in) {}
void somewhere() {
    Supplier<? extends List<String>> supplier = ArrayList::new;
    libraryMethod(supplier);
}

当然,如果由于某些原因你无法使用它,那么Class偶尔会遇到麻烦的事情。

  

任何人都可以解释为什么javac不允许演员?

Java不允许&#34;横向&#34;演员,例如:

Number n = ...;
String s = (Number) n; // compiler error

我解释了它如何适用于原始类型参数herehere

简短的解释是存在这样的子类型关系:

           Class<? extends List>
            ╱                 ╲
Class<? extends List<String>>  Class<ArrayList>

两者都是Class<? extends List>的子类型,并且没有一个是子类型,也不是另一个的超类型。

答案 1 :(得分:1)

您似乎正在向Class<ArrayList>>投放Class<? extends List<String>>,但ArrayList类没有那种通用。我不确定您的<String>

是否需要Class<? extends List>通用