Java 这个深奥的泛型错误是编译器错误还是新的限制?(推断类型不符合上限)

Java 这个深奥的泛型错误是编译器错误还是新的限制?(推断类型不符合上限),java,generics,lambda,compiler-errors,Java,Generics,Lambda,Compiler Errors,我将Java8U5更新为8u45,一些以前的工作代码不再编译。问题是,有一半的时候,这是一个故意的改变,所以我不知道这是否是一个bug (我还测试了u25,每个版本都与u45做相同的事情。) 但本质上,它与方法的多个返回点有关。e、 g: import java.sql.Connection; import java.util.Collections; import java.util.HashSet; import java.util.Set; public class CompilerIs

我将Java8U5更新为8u45,一些以前的工作代码不再编译。问题是,有一半的时候,这是一个故意的改变,所以我不知道这是否是一个bug

(我还测试了u25,每个版本都与u45做相同的事情。)

但本质上,它与方法的多个返回点有关。e、 g:

import java.sql.Connection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class CompilerIssue
{
    public Set<String> test(int value)
    {
        return perform(connection -> {
            if (value % 2 == 0)
            {
                return Collections.<String>emptySet();
            }
            else
            {
                return new HashSet<>(10);
            }
        });
    }

    <V> V perform(BusinessLogic<V> logic)
    {
        // would usually get a connection
        return null;
    }

    interface BusinessLogic<V>
    {
        V execute(Connection connection) throws Exception;
    }
}
导入java.sql.Connection;
导入java.util.Collections;
导入java.util.HashSet;
导入java.util.Set;
公共类编译器问题
{
公共设置测试(int值)
{
返回执行(连接->{
如果(值%2==0)
{
返回集合;
}
其他的
{
返回新的哈希集(10);
}
});
}
V执行(业务逻辑)
{
//通常会有一个连接
返回null;
}
接口业务逻辑
{
V执行(连接)抛出异常;
}
}
javac提供:

Error:(12, 23) java: incompatible types: inferred type does not conform to upper bound(s)
    inferred: java.util.Set<? extends java.lang.Object>
    upper bound(s): java.util.Set<java.lang.String>,java.lang.Object
错误:(12,23)java:不兼容的类型:推断的类型不符合上限

推断:java.util.Set据我所知,它是一个bug,来自Oracle,它没有正确地从目标类型(语句return期望返回的类型)推断出类型,而是以某种方式比较了两个return语句的上限:(
return Collections.emptySet();
返回新的哈希集(10);

在第二个return语句中,newhashset(10)
的上限将是
Object
,但是可以从返回类型推断出类型,返回类型实际上是
。尝试将第一个return语句注释掉,并返回null,然后编译:

public class CompilerIssue
{
    public Set<String> test(int value)
    {
        return perform(connection -> {
            if (value % 2 == 0)
            {
                return null; // COMMENTED OUT FOR TESTING PURPOSES Collections.<String>emptySet();
            }
            else
            {
                return new HashSet<>(10);
            }
        });
    }

    <V> V perform(BusinessLogic<V> logic)
    {
        // would usually get a connection
        return null;
    }

    interface BusinessLogic<V>
    {
        V execute(Connection connection) throws Exception;
    }
}
公共类编译器问题
{
公共设置测试(int值)
{
返回执行(连接->{
如果(值%2==0)
{
return null;//出于测试目的注释掉集合。emptySet();
}
其他的
{
返回新的哈希集(10);
}
});
}
V执行(业务逻辑)
{
//通常会有一个连接
返回null;
}
接口业务逻辑
{
V执行(连接)抛出异常;
}
}

这将编译并正确推断
HashSet(10)
的正确值类型应该是
String

我也希望
Collections.emptySet()
可以工作,但它会导致相同的错误。@xehpuk是的,如果使用Collections.emptySet()和新的HashSet,您也会因此得到错误。似乎新的行为(bug或其他)是每个返回点都会被查看,但所有返回点都必须是显式的,而旧的行为似乎更像是相反的,您只需要将其中一个显式化,它就意味着其余的返回点。