为什么以下使用方法引用的转换不会产生编译错误?

eit*_*ann 25 java java-8

public class SomeClass{

    public static int someFunction(int a) {
        return a;
    }

    public static void main(String[] args) {    
        Consumer<Integer> c = SomeClass::someFunction; 
    }
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么:Consumer<Integer> c = SomeClass::someFunction; 不产生编译错误,因为函数someFunction是一个带返回值的方法,而Consumer表示没有返回值的方法

Mic*_*ael 27

规格:

如果lambda的主体是一个语句表达式(即,允许独立作为语句的表达式),它与生成void的函数类型兼容; 任何结果都会被丢弃.

方法引用也是如此.

这种方式更灵活.假设在正常调用方法时不使用返回值是一个编译器错误 - 这将是令人难以置信的烦人.在某些情况下,你最终不得不使用你不关心的伪变量.

public class SomeClass
{
    public static int someFunction(int a) {
        return a;
    }

    public static void main(String[] args) {    
        someFunction(3); // "error" - ignoring return type
        int unused = someFunction(3); // "success"
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想要对可接受的内容进行完整的正式定义,请参阅15.13.2.方法参考的类型.


Eug*_*ene 12

这称为特殊void compatibility rule.例如,你有多少次真正关心List#add回归类型?即使它确实回来了true/false.

这里几乎相同,你可以调用一个方法,但忽略它的结果.如果你将你的消费者重写为lambda表达式,那就更有意义了:

Consumer<Integer> c = x -> {
   SomeClass.someFunction(x);
   return;     
}
Run Code Online (Sandbox Code Playgroud)

如果我从JLS中正确记得,那么只允许使用某些类型.

 increment/decrement operations
 method invocation
 assignment 
 instance creation
Run Code Online (Sandbox Code Playgroud)