方法参考,协方差逆变

时间:2014-07-08 15:58:08

标签: java java-8

我刚刚发现java 8允许引用具有更具体的返回类型和更一般参数的方法。

import java.util.function.Function;

public class MethodReferences {
    public static Integer function(Object o) {
        return 2;
    }

    public static void main(String[] args) {
        Function<String, Object> function = MethodReferences::function;
    }
}

这非常灵活。

但为什么他们没有将此扩展到其他案例?

例如:

import java.util.function.Function;

public class Main {


    public static void main(String[] args) {
        Function<String, Object> function = function();
    }

    private static Function<Object, Integer> function() {
        return new Function<Object, Integer>() {

            @Override
            public Integer apply(Object o) {
                return 1;
            }
        };
    }
}

编译失败:

Type mismatch: cannot convert from Function<Object,Integer> to Function<String,Object>

2 个答案:

答案 0 :(得分:9)

这是泛型的简单限制。类型系统不知道ObjectInteger中的哪一个是返回类型和参数类型,因此它不能做任何协方差/逆变智能。

如果你想表达&#34;一个超类型为X且返回Y&#34; 的子类型的函数,你会{{1 }}。事实上,如果你改变了

Function<? super X, ? extends Y>

Function<String, Object> function = function();

你的代码编译。 (Function<? super String, ? extends Object> function = function(); ? extends Object相同,但为了清楚起见,我将其写出来)

答案 1 :(得分:0)

函数在参数类型上应始终是协变的,而在返回类型上则应协变。

A2 instanceof A1B1 instanceof B2 然后

(A1 -> B1) instanceof (A2 -> B2)  // A1 -> B1  means function that takes argument of type A1 and returns value of type B1

对于函数是一等公民的任何编程语言,这都应该是正确的。函数不是Java中的一流实体,因此语言设计人员不可能强加这种差异。 (显然,上面的intanceof在Java中没有意义,因为它的功能不是任何实例。它们只是Java设计师的最后努力,以确保Java在大数据和Apache Spark时代保持相关性。所有“功能”功能是从scala借来的。