Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.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 为什么与lambda相关的类型推断会失败?_Java_Lambda_Java 8_Type Inference - Fatal编程技术网

Java 为什么与lambda相关的类型推断会失败?

Java 为什么与lambda相关的类型推断会失败?,java,lambda,java-8,type-inference,Java,Lambda,Java 8,Type Inference,我想理解为什么下面的内容在“引用不明确”的情况下不起作用,而它似乎不应该这样。值得向javac团队报告吗 import java.util.function.Function; import java.util.function.ToLongFunction; import org.junit.Test; public class LambdaTest { @FunctionalInterface public static interface CheckedFunction

我想理解为什么下面的内容在“引用不明确”的情况下不起作用,而它似乎不应该这样。值得向javac团队报告吗

import java.util.function.Function;
import java.util.function.ToLongFunction;
import org.junit.Test;

public class LambdaTest {

    @FunctionalInterface
    public static interface CheckedFunction<U,R>
    {
        R apply(U value) throws Exception;
    }

    @FunctionalInterface
    public static interface CheckedToLongFunction<T>
    {
        long apply(T i) throws Exception;
    }

    public static <T,R> Function<T,R> unchecked(CheckedFunction<T,R> func)
    {
        return value -> {
            try
            {
                return func.apply (value);
            }
            catch(RuntimeException e)
            {
                throw e;
            }
            catch(Exception e)
            {
                throw new RuntimeException(e);
            }
        };
    }

    public static <T> ToLongFunction<T> unchecked(CheckedToLongFunction<T> func)
    {
        return value -> {
            try
            {
                return func.apply (value);
            }
            catch(RuntimeException e)
            {
                throw e;
            }
            catch(Exception e)
            {
                throw new RuntimeException(e);
            }
        };
    }

      public void 
    bar( Function<Object,Object> fn ) { 

            System.out.println("Function"); 
        }

      @Test public void
    test() {

            bar (a -> a); //OK
            bar (unchecked (a -> a)); //Should be OK, but receive "reference to unchecked is ambiguous"
            bar (unchecked ((Object a) -> a)); //OK
        }

}
import java.util.function.function;
导入java.util.function.ToLongFunction;
导入org.junit.Test;
公共类LambdaTest{
@功能接口
公共静态接口CheckedFunction
{
R应用(U值)抛出异常;
}
@功能接口
公共静态接口CHECKEDTONGFUNCTION
{
长应用(ti)抛出异常;
}
未选中公共静态函数(CheckedFunction func)
{
返回值->{
尝试
{
返回函数应用(值);
}
捕获(运行时异常e)
{
投掷e;
}
捕获(例外e)
{
抛出新的运行时异常(e);
}
};
}
未选中公共静态ToLong函数(选中ToLongFunc函数)
{
返回值->{
尝试
{
返回函数应用(值);
}
捕获(运行时异常e)
{
投掷e;
}
捕获(例外e)
{
抛出新的运行时异常(e);
}
};
}
公共空间
bar(函数fn){
System.out.println(“函数”);
}
@测试公共空间
测试(){
条(a->a);//好的
条(未选中(a->a));//应该可以,但接收“对未选中的引用不明确”
条形图(未选中((对象a)->a));//确定
}
}
正如您所看到的,这个示例很有趣,因为
CheckedFunction
checkedTologFunction
都采用引用类型,因此显式指定lamba的输入类型似乎没有任何用处。然而,它允许代码编译

调用
unchecked(CheckedFunction)
时不应出现歧义,因为
unchecked(checkedTongFunction)
生成返回原语的lambda,而bar需要一个
对象


我特别想从JLS那里得到一个解决方案。如果JLS没有指定这一点,我可以尝试将其作为javac bug进行归档。

未选中的函数声明
(CheckedToLongFunction)
旨在返回
ToLongFunction
,而
ToLongFunction
则返回
long
。在您的参数中,您声明应该忽略此函数,因为它返回一个原语(可能会引发运行时异常)

但随着自动装箱的引入,
ToLongFunction
的原始结果可以装箱到
Long
,使其成为一个对象

因此,在与现在相同的上下文中,tolong函数可以返回
Long
Long

因此,模糊函数

1-第一阶段(§15.12.2.2)在不允许装箱或拆箱转换或使用变量算术方法调用的情况下执行重载解析。如果在此阶段没有找到适用的方法,则处理继续到第二阶段

然后

2-第二阶段(§15.12.2.3)在允许装箱和拆箱的同时执行重载解析,但仍然禁止使用变量算术方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段

你有两种方法

public static <T,R> Function<T,R> unchecked(CheckedFunction<T,R> func)
public static <T> ToLongFunction<T> unchecked(CheckedToLongFunction<T> func)
无法转换为
checkedTologFunction
实例(因为无法从该调用上下文推断
Long
的类型参数),lambda仍然适用于该函数类型

编译器无法确定是否应该将
a->a
转换为
checkedTongFunction
CheckedFunction
。由于两者都适用,调用是不明确的。不会检查调用上下文(和返回类型)以解决歧义

但在这种情况下,

bar(unchecked((Object a) -> a)); // OK
我们有一个显式类型的lambda表达式。lambda主体解析为
Object
类型的返回值,该返回值不符合
checkedTologFunction\apply(…)
方法的要求,即
Object
类型的表达式不能隐式转换为
long
类型的表达式


因此,由于还有一种适用的方法,所以选择了这种方法

类型
tolong function
不应出现在此处的图片中。调用未选中的
是不明确的。在任何情况下,
bar
需要一个
函数,而不是
tolong函数
。我想指出的是,如果指定了lambda的输入类型,则分辨率可以正常工作。指定输入类型不会解决任何自动装箱引起的歧义,因此它不是一个因素。实际上,
bar(未选中(a->new Object())
也不起作用,因此它不是指定返回类型的问题。您说调用上下文未被检查。为什么不呢?它看起来像是一个编译器错误。@AleksandrDubinsky lambda表达式
a->new Object()
仍然是隐式类型的。编译器只会走这么远。因为它是隐式类型的,所以它不会检查表达式体的类型。为什么?似乎是这样的,因为调用可以是独立的,即不作为参数或赋值给任何其他对象,所以我们不希望有两种不同的方法(规则集)来评估它。
bar(unchecked(a -> a)); // Should be OK, but receive
bar(unchecked((Object a) -> a)); // OK