Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.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
返回lambda的Java lambda_Java_Lambda_Functional Programming_Java 8 - Fatal编程技术网

返回lambda的Java lambda

返回lambda的Java lambda,java,lambda,functional-programming,java-8,Java,Lambda,Functional Programming,Java 8,在新的JDK8函数式编程领域,我正在尝试做一件似乎相对基本的事情,但我无法让它工作。我有这个工作代码: import java.util.*; import java.util.concurrent.*; import java.util.stream.*; public class so1 { public static void main() { List<Number> l = new ArrayList<>(Arrays.asList(1, 2

在新的JDK8函数式编程领域,我正在尝试做一件似乎相对基本的事情,但我无法让它工作。我有这个工作代码:

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

public class so1 {
   public static void main() {
      List<Number> l = new ArrayList<>(Arrays.asList(1, 2, 3));
      List<Callable<Object>> checks = l.stream().
               map(n -> (Callable<Object>) () -> {
                  System.out.println(n);
                  return null;
               }).
               collect(Collectors.toList());
   }
}
import java.util.*;
导入java.util.concurrent.*;
导入java.util.stream.*;
公共类so1{
公共静态void main(){
listl=newarraylist(Arrays.asList(1,2,3));
列表检查=l.stream()。
映射(n->(可调用)(->{
系统输出println(n);
返回null;
}).
collect(Collectors.toList());
}
}
它获取一个数字列表并生成一个可以打印出来的函数列表。然而,显式转换为Callable似乎是多余的。对我和我来说都是这样。我们都同意,这也应该起作用:

List<Callable<Object>> checks = l.stream().
       map(n -> () -> {
          System.out.println(n);
          return null;
       }).
       collect(Collectors.toList());
List checks=l.stream()。
地图(n->()->{
系统输出println(n);
返回null;
}).
collect(Collectors.toList());
但是,我得到一个错误:

so1.java:10: error: incompatible types: cannot infer type-variable(s) R
      List<Callable<Object>> checks = l.stream().map(n -> () -> {System.out.println(n); return null;}).collect(Collectors.toList());
                                                    ^
    (argument mismatch; bad return type in lambda expression
      Object is not a functional interface)
  where R,T are type-variables:
    R extends Object declared in method <R>map(Function<? super T,? extends R>)
    T extends Object declared in interface Stream
1 error
so1.java:10:错误:不兼容的类型:无法推断类型变量R
列表检查=l.stream().map(n->()->{System.out.println(n);返回null;}).collect(Collectors.toList());
^
(参数不匹配;lambda表达式中的返回类型错误)
对象不是功能接口)
其中R,T是类型变量:

R扩展方法映射中声明的对象(函数我还没有深入研究类型推断如何与lambdas一起工作的确切规则。不过,从一般语言设计的角度来看,编写语言规则使编译器能够理解我们认为应该理解的所有内容并不总是可能的。我曾是Ada语言编译器的编译器维护人员,我对这里有很多语言设计问题。Ada在很多情况下使用类型推断(如果不查看包含该结构的整个表达式,就无法确定结构的类型,我认为这个Java lambda表达式也是如此)。有一些语言规则会导致编译器在理论上只有一种可能的解释的情况下,拒绝一些模棱两可的表达式。如果我没记错的话,其中一个原因是有人发现一种情况,即如果一条规则能让编译器找出正确的解释,那么编译器就需要ke 17通过表达式来正确解释它


因此,虽然我们可能认为编译器“应该”能够在特定情况下找出某些东西,但这显然是不可行的。

您遇到了适用于方法调用接收器的Java 8目标类型的限制对于参数类型,它不适用于调用方法的对象或表达式

这里,
l.stream()。
地图(n->()->{
系统输出println(n);
返回null;
})
collect(Collectors.toList())
方法调用的接收者,因此它不考虑目标类型
List

如果目标类型为know,则很容易证明嵌套lambda表达式有效,例如

static <T> Function<T,Callable<Object>> toCallable() {
    return n -> () -> {
        System.out.println(n); 
        return null;
    };
}
toCallable()的静态函数{
返回n->()->{
系统输出println(n);
返回null;
};
}
工作没有问题,你可以用它来解决你原来的问题

List<Callable<Object>> checks = l.stream()
    .map(toCallable()).collect(Collectors.toList());
List checks=l.stream()
.map(toCallable()).collect(collector.toList());
您还可以通过引入一个helper方法来解决这个问题,该方法将第一个表达式的角色从methodreceiver更改为一个参数

// turns the Stream s from receiver to a parameter
static <T, R, A> R collect(Stream<T> s, Collector<? super T, A, R> collector) {
    return s.collect(collector);
}
//将来自接收器的流转换为参数

静态R collect(流s,收集器我遇到了同样的问题,并且能够通过显式地将泛型类型参数指定为
map
来解决它,如下所示:

List<Callable<Object>> checks = l.stream().
   <Callable<Object>>map(n -> () -> {
      System.out.println(n); 
      return null;
   }).
   collect(Collectors.toList());
List checks=l.stream()。
地图(n->()->{
系统输出println(n);
返回null;
}).
collect(Collectors.toList());

首先,您必须知道编译器如何获取lambda表达式的类型。它是通过目标类型实现的,这意味着您将lambda表达式指定给的变量的类型。在您的情况下,如果

Function<Integer, Callable<Object>> fn = n -> () -> { System.out.println(n); return null; }
函数fn=n->()->{System.out.println(n);返回null;}
这就是lambda获取其类型的方式:
函数

然后,您必须查看泛型类型中的类型推断: map的返回类型是
Stream
,R将由传递到函数中的参数类型决定。如果
map(x->“some string”)
,则结果是
Stream
。现在问题是,R的类型是lambda的类型。但是lambda需要一个目标类型,即变量R


工作代码之所以有效,是因为它显式地将lambda强制转换为一个类型。

与强制转换相比,我更喜欢
map(…)
的显式类型参数
l.stream().map(…)
相关:我可能需要几周的时间才能理解这一点,但我想我会接受;)
Function<Integer, Callable<Object>> fn = n -> () -> { System.out.println(n); return null; }