简体   繁体   English

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

[英]Why won't Java resolve this <generic> method signature?

I broke a build today with code I think should work: 我今天用一个我认为应该可以工作的代码破坏了一个构建:

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());
    }
}

The Eclipse Java compiler has no problem with this code, but Oracle's javac fails with this message: 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

The obvious thing to do is to help-out the Oracle compiler by adding a cast to the Collections.emptyList() , but of course that causes its own compiler error (for both Eclipse and javac ): 显而易见的事情是通过向Collections.emptyList()添加强制转换来帮助Oracle编译器,但是这当然会导致其自身的编译器错误(对于Eclipse javac ):

 /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());

I'm well aware that Java's support for generics is officially terrible, but this seems like a common case that ought to work. 我很清楚Java对泛型的支持在官方上是很糟糕的,但这似乎是应该起作用的常见情况。 I know I can just instantiate an empty list manually with the correct data type, but that's wasteful. 我知道我可以使用正确的数据类型手动实例化一个空列表,但这很浪费。 I know I can split-up this line of code into two (one with a declaration of List<String> and assignment to Collections.emptyList() and another with the call to Map<Integer,List<String>>.put() , but that's just more code for no good reason. 我知道我可以将这一行代码分成两部分(一个带有List<String>的声明并分配给Collections.emptyList() ,另一个带有对Map<Integer,List<String>>.put()的调用Map<Integer,List<String>>.put() ,但这只是没有理由的更多代码

Is there something else I can do to convince Oracle's javac that this code is valid? 我还能说服Oracle的javac此代码有效吗?

Update: Using Eclipse Luna (not sure compiler version) and Oracle Java 1.8.0_151. 更新:使用Eclipse Luna(不确定编译器版本)和Oracle Java 1.8.0_151。

Update 2: looks like this was caused by the presence of -source 1.5 as one of the arguments to the compiler. 更新2:看起来这是由于-source 1.5作为编译器的参数之一而引起的。 Using the default source for javac does not cause any errors. 使用javac的默认source不会导致任何错误。 Strange that Collections.emptyList() behaves differently across versions when it hasn't changed since Java 1.5. 奇怪的是,自Java 1.5以来, Collections.emptyList()不同版本之间的行为不同。 There must have been some kind of change to the erasure-handling across versions that makes this work differently at different source-compatibility levels. 跨版本的擦除处理必须进行某种更改,以使其在不同的源兼容性级别上以不同的方式工作。

In some versions of Java (pre-Java 8, including Java 8 with a source-compatibility setting less than 1.8 ) you need to specify the generic type so that emptyList will return a generic list rather than a raw one. 在某些版本的Java中(Java 8之前的版本,包括Java 8,其源兼容性设置小于1.8 ),您需要指定通用类型,以便emptyList将返回通用列表而不是原始列表。 You can do that by using: 您可以使用以下方法做到这一点:

Collections.<String>emptyList()

In more recent Java versions, the compiler can deduce the required generic type from the context, so you don't need to specify it. 在较新的Java版本中,编译器可以从上下文中推断出所需的泛型类型,因此您无需指定它。 This deduction was added in Java 8 so that you don't have to specify the generic type at every step in the chain when using a stream. 此推论是在Java 8添加的,因此您在使用流时不必在链的每个步骤中都指定通用类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM