有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

(我还测试了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;
    }
}

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

想法,就像这类事情的惯常做法一样,看不出有任何问题

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

(如果它是一个bug,那么我必须向Oracle报告一个bug。如果它是一个特性,那么我必须报告一个bug,让IDEA认为它没问题。)


共 (1) 个答案

  1. # 1 楼答案

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

    在第二个return语句中,justnew 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;
        }
    }
    

    这将编译并正确推断HashSet<>(10)的正确值类型应为String