Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么可以';Java编译器没有弄明白这一点吗?_Java_Generics_Collections - Fatal编程技术网

为什么可以';Java编译器没有弄明白这一点吗?

为什么可以';Java编译器没有弄明白这一点吗?,java,generics,collections,Java,Generics,Collections,为什么编译器无法从以下示例中的Collections.emptySet()推断结果的正确类型 import java.util.*; import java.io.*; public class Test { public interface Option<A> { public <B> B option(B b, F<A,B> f); } public interface F<A,B> {

为什么编译器无法从以下示例中的Collections.emptySet()推断结果的正确类型

import java.util.*;
import java.io.*;

public class Test {
    public interface Option<A> {
        public <B> B option(B b, F<A,B> f);
    }

    public interface F<A,B> {
        public B f(A a);
    }

    public Collection<String> getColl() {
        Option<Integer> iopt = null;

        return iopt.option(Collections.emptySet(), new F<Integer, Collection<String>>() {
            public Collection<String> f(Integer i) {
                return Collections.singleton(i.toString());
            }
        });
    }
}
import java.util.*;
导入java.io.*;
公开课考试{
公共接口选项{
公共B选项(B、F);
}
公共接口F{
公共B f(A);;
}
公共集合getColl(){
选项iopt=null;
返回iopt.option(Collections.emptySet(),new F()){
公共集合f(整数i){
returncollections.singleton(i.toString());
}
});
}
}
以下是编译器错误消息:

knuttycombe@knuttycombe-ubuntu:~/tmp/java$ javac Test.java 
Test.java:16: <B>option(B,Test.F<java.lang.Integer,B>) in 
Test.Option<java.lang.Integer> cannot be applied to (java.util.Set<java.lang.Object>,
<anonymous Test.F<java.lang.Integer,java.util.Collection<java.lang.String>>>)
            return iopt.option(Collections.emptySet(), new F<Integer, Collection<String>>() {
                   ^
1 error
knuttycombe@knuttycombe-ubuntu:~/tmp/java$javac Test.java
java:16:中的选项(B,Test.F)
无法将Test.Option应用于(java.util.Set,
)
返回iopt.option(Collections.emptySet(),new F()){
^
1错误
当然,下面的getColl()实现是可行的:

    public Collection<String> getColl() {
        Option<Integer> iopt = null;

        Collection<String> empty = Collections.emptySet();
        return iopt.option(empty, new F<Integer, Collection<String>>() {
            public Collection<String> f(Integer i) {
                return Collections.singleton(i.toString());
            }
        });
    }
公共集合getColl(){ 选项iopt=null; Collection empty=Collections.emptySet(); 返回iopt.option(空,新F(){ 公共集合f(整数i){ returncollections.singleton(i.toString()); } }); }
集合上的类型安全方法的全部目的是避免单例集合出现这种问题(与使用静态变量相反)那么,编译器是否根本无法跨多个泛型级别执行推理?发生了什么事?

Java需要大量的人手来进行推理。在很多情况下,类型系统可以更好地进行推理,但在您的情况下,以下操作将起作用:

print("Collections.<String>emptySet();");
打印(“Collections.emptySet();”;

这看起来像是一个类型转换问题-即,需要将
对象
(在
集合
,这将是空集的类型)转换为
字符串
。一般情况下,向下转换并不安全。

集合。清空设置()
不是一个
集合
,除非Java知道它需要一个
集合
。在这种情况下,编译器似乎对它尝试确定类型的顺序有些愚蠢,并尝试确定
集合的返回类型。emptySet()
在尝试确定B的预期模板参数类型之前,实际上是
字符串


解决方案是明确说明您需要
Collections.emptySet()
,如GaryF所述。

首先,您可以将问题缩小到以下代码:

public class Test { 
    public void option(Collection<String> b) {
    }

    public void getColl() {
        option(Collections.emptySet());
    }
}
公共类测试{
公共无效选项(集合b){
}
public void getColl(){
选项(Collections.emptySet());
}
}

这不起作用,您需要一个临时变量,否则编译器无法推断类型。下面是对这个问题的一个很好的解释:

Java可以做得更好的一个例子,Java 7正在考虑这样做:Map model=new HashMap();太好了,我以前没有看到过这种语法。谢谢!只需使用Bloch在《有效Java》第二版中介绍的GenericFactory…很好的文章。非常具体地说,回答原始问题的关键点似乎是:“类型推断不考虑方法调用。”