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

Tre*_*kaz 11 java generics lambda compiler-errors

我从Java 8u5更新到8u45,一些以前工作的代码不再编译.问题是,发生这种情况的时间有一半,这是故意的改变,所以我无法弄清楚它是否是一个错误.

(我也测试了u25,每个版本都和u45一样.)

但实质上,它与方法的多个返回点有关.例如:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

IDEA,就像通常的这种事情一样,看不出任何问题.

我已经知道了修复 - 替换HashSet<>HashSet<String>.但是我们通过代码普遍使用了这种结构,所以在我花时间改变它之前,我想知道:这是一个bug,还是旧行为的bug?

(如果这是一个错误,那么我必须向Oracle报告一个错误.如果它是一个功能,那么我必须向IDEA报告一个错误,认为它没关系.)

mor*_*ano 5

据我所知,它是一个bug并且来自Oracle,它没有正确地推断出目标类型的类型(句子返回期望返回的类型),而是以某种方式比较两个返回句子的上限:( return Collections.<String>emptySet();return new HashSet<>(10);).

在第二个return语句中,just的上限new HashSet<>(10)Object,但是类型可以从确实的返回类型推断出来<String>.尝试作为测试注释掉第一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将编译,它将正确推断HashSet<>(10)应该是正确的值类型String.