hi.*_*ish 62 java lambda java-10
允许var在Java 10中分配如下字符串:
var foo = "boo";
Run Code Online (Sandbox Code Playgroud)
虽然不允许为其分配lambda表达式,例如:
var predicateVar = apple -> apple.getColor().equals("red");
Run Code Online (Sandbox Code Playgroud)
为什么不能推断的λ或方法引用类型时,它可以推断出休息等String,ArrayList,用户类等?
Bri*_*etz 58
这与此无关var.它与lambda是否具有独立类型有关.方法var是它在RHS上计算初始化器的独立类型,并推断出.
自从它们在Java 8中引入以来,lambda表达式和方法引用没有独立类型 - 它们需要一个目标类型,它必须是一个功能接口.
如果你试试:
Object o = (String s) -> s.length();
Run Code Online (Sandbox Code Playgroud)
你也得到一个类型错误,因为编译器不知道你打算将lambda转换为什么功能接口.
要求推理var只会让它变得更难,但由于更容易回答的问题无法解决,更难的问题也无法解决.
请注意,您可以通过其他方式(例如强制转换)提供目标类型,然后它可以工作:
var x = (Predicate<String>) s -> s.isEmpty();
Run Code Online (Sandbox Code Playgroud)
因为现在RHS有一个独立的类型.但是最好通过提供x清单类型来提供目标类型.
Jor*_*nee 54
推理过程基本上只给变量赋予其初始化表达式的类型.一些微妙之处:
- 初始化程序没有目标类型(因为我们尚未推断它).需要这种类型的多表达式(如lambdas,方法引用和数组初始值设定项)将触发错误.
因为lambda表达式本身没有类型,所以无法推断它var.
...同样,可以设置默认规则.
当然,你可以想出一种方法来解决这个限制.为什么开发人员做出不这样做的决定真的取决于猜测,除非参与决策的人能在这里回答.如果您有兴趣,可以在openjdk邮件列表中查询:http://mail.openjdk.java.net/mailman/listinfo
如果我猜测,他们可能不希望在var一组特定的功能接口类型的上下文中绑定lambda推理,这将排除任何第三方功能接口类型.更好的解决方案是推断(Apple) -> boolean可以转换为兼容的功能接口类型的通用函数类型(即).但是JVM没有这样的函数类型,并且在创建lambda表达式的项目中已经做出了不实现它们的决定.如果你对具体原因感兴趣,请问开发者.
Kar*_*ldt 27
对于那些说这是不可能的,不受欢迎的或不想要的人,我只想指出Scala可以通过仅指定参数类型来推断lambda的类型:
val predicateVar = (apple: Apple) => apple.getColor().equals("red")
Run Code Online (Sandbox Code Playgroud)
在Haskell中,因为它getColor是一个独立的函数而不是附加到一个对象,并且因为它完全是Hindley-Milner推断,所以你甚至不需要指定参数类型:
predicateVar = \apple -> getColor apple == "red"
Run Code Online (Sandbox Code Playgroud)
这非常方便,因为程序员明确指定的不是简单的类型,而是更复杂的类型.
换句话说,它不是Java 10中的一个功能.这是它们的实现和以前的设计选择的限制.
要回答这个问题,我们必须详细了解 lambda 是什么以及它是如何工作的。
首先我们应该了解什么是 lambda:
一个 lambda 表达式总是实现一个函数式接口,所以当你必须提供一个函数式接口时Runnable,而不是必须创建一个实现该接口的全新类,你可以只使用 lambda 语法来创建一个函数式接口的方法需要。请记住,尽管 lambda 仍然具有它正在实现的功能接口的类型。
考虑到这一点,让我们更进一步:
这在 Runnable 的情况下效果很好,我可以像这样创建一个新线程,new Thread(()->{//put code to run here});而不是创建一个全新的对象来实现功能接口。这是有效的,因为编译器知道它Thread()采用 Runnable 类型的对象,因此它知道 lambda 表达式必须是什么类型。
但是,在将 lambda 分配给局部变量的情况下,编译器不知道此 lambda 正在实现什么功能接口,因此无法推断var应该是什么类型。由于它可能正在实现用户创建的功能接口,或者它可能是runnable接口,因此无法知道。
这就是 lambda 不能与 var 关键字一起使用的原因。
正如几个人已经提到的,应该var推断什么类型,为什么要推断?
该声明:
var predicateVar = apple -> apple.getColor().equals("red");
Run Code Online (Sandbox Code Playgroud)
是不明确的,没有有效的理由编译器应该挑选Function<Apple, Boolean>过Predicate<Apple>或反之亦然假设apple在lambda标识符表示Appleisntance。
另一个原因是lambda本身没有可说的类型,因此编译器无法推断出它。
同样,“如果可能的话”可以想象一下开销,因为每次将lambda分配给var变量时,编译器都必须遍历所有功能接口并确定哪个功能接口最合适。
| 归档时间: |
|
| 查看次数: |
3782 次 |
| 最近记录: |