为什么Java不会解决这个<generic>方法签名?

时间:2017-12-12 22:59:26

标签: java generics compiler-errors

我今天用我认为应该有效的代码打破了构建:

import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class EmptyListTest {
    public static void main(String[] args) {
        HashMap<Integer,List<String>> map = new HashMap<Integer,List<String>>();

        map.put(Integer.valueOf(0), Collections.emptyList());
    }
}

Eclipse Java编译器对此代码没有任何问题,但Oracle的javac失败并显示以下消息:

src/java/EmptyListTest.java:9: error: no suitable method found for put(Integer,List<Object>)
map.put(Integer.valueOf(0), Collections.emptyList());
            ^
     method Map.put(Integer,List<String>) is not applicable
       (argument mismatch; List<Object> cannot be converted to List<String>)
     method AbstractMap.put(Integer,List<String>) is not applicable
       (argument mismatch; List<Object> cannot be converted to List<String>)
     method HashMap.put(Integer,List<String>) is not applicable
       (argument mismatch; List<Object> cannot be converted to List<String>)
1 error
4 warnings

显而易见的事情是通过向Collections.emptyList()添加强制转换来帮助Oracle编译器,但当然这会导致自己的编译器错误(对于Eclipse { {1}}):

javac

我很清楚Java对泛型的支持是官方可怕的,但这似乎是应该起作用的常见情况。我知道我可以用正确的数据类型手动实例化一个空列表,但这很浪费。我知道我可以将这行代码分成两行(一行声明为 /Users/chris/Documents/Eclipse/chadis-web/src/java/EmptyListTest.java:9: error: incompatible types: List<Object> cannot be converted to List<String> map.put(Integer.valueOf(0), (List<String>)Collections.emptyList()); ,作业分配给List<String>,另一行则调用Collections.emptyList(),但是只是更多代码没有充分理由。

我可以采取其他措施来说服甲骨文Map<Integer,List<String>>.put()此代码有效吗?

更新:使用Eclipse Luna(不确定编译器版本)和Oracle Java 1.8.0_151。

更新2:看起来这是由于javac作为编译器的参数之一而引起的。使用-source 1.5的默认source不会导致任何错误。奇怪的是javac在版本自Java 1.5以来没有发生变化时表现不同。对于跨版本的擦除处理必定会有某种变化,这使得在不同的源兼容级别上工作方式有所不同。

1 个答案:

答案 0 :(得分:3)

在某些Java版本(Java 8之前,包括源兼容性设置小于1.8的Java 8)中,您需要指定泛型类型,以便emptyList返回通用列表而不是原始的。你可以使用:

来做到这一点
Collections.<String>emptyList()

在更新的Java版本中,编译器可以从上下文中推导出所需的泛型类型,因此您无需指定它。此推论为added in Java 8,因此您在使用流时不必在链中的每个步骤都指定泛型类型。