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

时间:2018-03-08 12:40:06

标签: 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; 
    }
}

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

2 个答案:

答案 0 :(得分:26)

来自the spec

  

如果lambda的主体是一个语句表达式(即,一个   表达可以作为一个声明独立存在),它是   与产生空白的函数类型兼容; 任何结果都是简单的   丢弃。

方法参考也是如此。

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

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"
    }
}

如果您想要接受完整的正式定义,请参阅15.13.2. Type of a Method Reference

答案 1 :(得分:12)

这称为特殊void compatibility rule。例如,您实际关注List#add返回类型的次数是多少?即使它确实返回true/false

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

Consumer<Integer> c = x -> {
   SomeClass.someFunction(x);
   return;     
}

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

 increment/decrement operations
 method invocation
 assignment 
 instance creation