为什么以下带有方法引用的强制转换不产生编译错误?

2022-09-01 18:53:33
public class SomeClass{

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

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

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


答案 1

规格:

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

如果需要可接受的完整正式定义,请参阅 15.13.2。方法引用的类型


答案 2

这称为 特殊 。例如,您真正关心过多少次退货类型?即使它确实返回。void compatibility ruleList#addtrue/false

这里几乎相同,您可以调用一个方法,但忽略其结果。如果您将使用者重写为 lambda 表达式,则更有意义:

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

如果我从JLS中没记错的话,只有一些类型是允许的。

 increment/decrement operations
 method invocation
 assignment 
 instance creation

推荐