Java 8:目标类型上下文目标类型在您的示例中

2022-09-04 07:10:43

在阅读文章Lambda的状态时,我来到了目标类型主题,我对以下段落有点困惑:

ActionListener l = (ActionEvent e) -> ui.dazzle(e.getModifiers());

此方法的含义是,同一个 lambda 表达式在不同的上下文中可以具有不同的类型:

Callable<String> c = () -> "done";

PrivilegedAction<String> a = () -> "done";

在第一种情况下,lambda 表达式表示 的实例。在第二种情况下,同一表达式表示特权操作的实例。() -> "done"Callable

编译器负责推断每个 lambda 表达式的类型。它使用表达式出现的上下文中预期的类型;此类型称为目标类型。lambda 表达式只能出现在目标类型为函数接口的上下文中。

你能用一个简单的方式解释一下与引用的段落有关的这些要点吗:

  1. 目标类型
  2. 上下文

如果您还提供代码片段,我将不胜感激。


答案 1

上下文

上下文是在代码中使用表达式的方式。这不仅仅是 lambda 表达式 - 它是任何表达式,如 、 或 .a+ba++Math.random()

可能上下文的示例:

  • 赋值:取表达式 。如果将其赋值给变量,则会在赋值上下文中使用它:a+b

    c = a+b;
    
  • 方法或构造函数的参数:。这是当您将其传递给某个方法调用时:

    System.out.println(a+b);
    
  • 返回值:在语句中使用表达式时:return

    return a+b;
    
  • 数组索引:当表达式是数组的索引时:

    x[a+b] = 3;
    

目标类型

目标类型是给定上下文中预期的类型。例如,如果您有一个定义为以下内容的方法:

public int myMethod() { ... }

则其主体中语句中的任何表达式都应具有 类型 。因此,如果您有此内容:returnint

return a+b;

里面,预计会解析为可分配给 int 的或某些东西。myMethoda+bint

现在,假设你有这个方法:

public void anotherMethod( double d );

然后,当您调用它并将表达式作为参数传递时,该表达式应为 类型 。所以像这样的电话:double

anotherMethod(a+b);

期望解析为 .这就是它的目标类型a+bdouble

在您的示例中

在声明中:

Callable<String> c = () -> "done";

表达式是 lambda 表达式 。它在赋值上下文中使用(它被赋值给 )。目标类型是因为当您将任何内容分配给 时,这是预期的。() -> "done"cCallable<String>c


有关更正式的讨论,请参阅 Java 语言规范,第 5 章


答案 2

lambda 表达式是函数接口的实例。但是lambda表达式本身不包含有关它正在实现的功能接口的信息;该信息是从其使用的上下文中推断出来的。例如,表达式

x -> 2 * x 

可以是功能接口的实例

interface IntOperation { int operate(int i); } 

所以写是合法的

IntOperation iop = x -> x * 2; 

此处赋值右侧的表达式的预期类型是 IntOperation。这称为 lambda 表达式的目标类型。显然,lambda 表达式可以与不同的功能接口类型兼容,因此,同一个 lambda 表达式在不同的上下文中可以具有不同的目标类型。例如,给定一个接口

interface DoubleOperation { double operate(double i); } 

写也是合法的

DoubleOperation dop = x -> x * 2; 

lambda 表达式的目标类型必须是函数接口,并且要与目标类型兼容,lambda 表达式必须具有与接口的函数类型相同的参数类型,其返回类型必须与函数类型兼容,并且只能引发函数类型允许的异常。

礼貌:lambda 表达式的类型是什么?

让我添加一个关于 Lambda 的资源。这似乎非常有助于在 Lambdas 的上下文中清楚地理解许多概念。该资源是 LAMBDA 常见问题解答。{免责声明:我与本网站没有任何关系。我只是碰巧访问了这个网站,所以我想推荐它,以便人们可以从中受益。希望它有帮助。


推荐