Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.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
为什么要编译这个Java8方法引用?_Java_Java 8_Method Reference - Fatal编程技术网

为什么要编译这个Java8方法引用?

为什么要编译这个Java8方法引用?,java,java-8,method-reference,Java,Java 8,Method Reference,我目前正在深入研究Java8特性,如Lambdas和方法引用。玩了一会儿,我想到了以下示例: public class ConsumerTest { private static final String[] NAMES = {"Tony", "Bruce", "Steve", "Thor"}; public static void main(String[] args) { Arrays.asList(NAMES).forEach(Objects::requireNo

我目前正在深入研究
Java8
特性,如Lambdas和方法引用。玩了一会儿,我想到了以下示例:

public class ConsumerTest {

  private static final String[] NAMES = {"Tony", "Bruce", "Steve", "Thor"};

   public static void main(String[] args) {
      Arrays.asList(NAMES).forEach(Objects::requireNonNull);
   }
}
Map<String, String> map = new HashMap<>();

map.put("1", "a");

map.put("1", "A"); // Who cares about the returned value "a"?
我的问题是:

为什么主方法中的行要编译

如果我理解正确,那么引用方法的签名必须与函数接口的SAM签名相对应。在这种情况下,消费者需要以下签名:

void accept(T t);
但是,
requirennoull
方法返回
T
,而不是void:

public static <T> T requireNonNull(T obj)
public static T requirennull(T obj)

Java语言规范第8版规定:

如果T是函数接口类型(),并且表达式与从T派生的基本目标类型的函数类型一致,则方法引用表达式在赋值上下文、调用上下文或转换上下文中与目标类型T兼容

[……]

如果以下两项均为真,则方法引用表达式与函数类型一致:

  • 函数类型标识与引用对应的单个编译时声明
  • 以下情况之一是正确的:
    • 函数类型的结果无效。
    • 函数类型的结果是R,将捕获转换()应用于所选编译时声明的调用类型()的返回类型的结果是R'(其中R是可用于推断R的目标类型),R和R'都不是空的,并且R'在赋值上下文中与R兼容
(强调矿山)

因此,函数类型的结果是void,这一事实足以让它匹配

还特别提到匹配方法时使用void。对于lambda表达式,有在中引用的void兼容块()的概念,但对于方法引用没有等效的定义

我还没有找到更具体的解释(但是JLS是一个很难破解的问题,所以我可能遗漏了一些相关的章节),但我认为这与以下事实有关:您也可以自己将非void方法作为语句调用(无赋值,
return
等))

还说:

为了确定编译时结果,如果调用方法的结果为void,则方法调用表达式是表达式语句;如果调用方法的结果为non void,则返回语句的表达式

当方法引用的编译时声明是签名多态性时,此确定的效果是:

  • 方法调用的参数类型是相应参数的类型
  • 方法调用为void或具有返回类型的Object,这取决于包含方法调用的调用方法是void还是具有返回类型

因此,生成的方法调用将是无效的,以匹配函数类型。

除了@Mark Rotterveel的确切答案中所述的内容外,它是编译的,因为在Java中,您可以忽略任何方法调用的结果,如以下示例中所示:

public class ConsumerTest {

  private static final String[] NAMES = {"Tony", "Bruce", "Steve", "Thor"};

   public static void main(String[] args) {
      Arrays.asList(NAMES).forEach(Objects::requireNonNull);
   }
}
Map<String, String> map = new HashMap<>();

map.put("1", "a");

map.put("1", "A"); // Who cares about the returned value "a"?
Map Map=newhashmap();
地图放置(“1”、“a”);
地图。放置(“1”、“A”);//谁在乎返回值“a”?
由于在
forEach()
consumer块中没有返回任何内容,因此根据规范,它是有效的。

考虑
myList.forEach(myOtherList::add)
。您是否关心
列表。add
返回始终为
true的
布尔值?如果
myOtherList::add
不起作用,那将是一种痛苦。