泛型如何在参数中真正起作用?

时间:2017-08-28 07:09:00

标签: java generics functional-programming

我对仿制药的工作方式感到困惑?我正在了解java中的function API,我只是测试Function界面,并对compose方法感到困惑,因为compose中泛型如何工作方法

在java官方教程网站上阅读泛型我意识到如果我们在方法返回或参数中有任何泛型类型,我们必须在方法签名中声明该类型,如下所述。

以下是我在official docs tutorial中阅读的方法。

public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
    return p1.getKey().equals(p2.getKey()) &&
           p1.getValue().equals(p2.getValue());
}

上面的方法有两种类型,K,V,它们在static关键字之后的签名中声明,但是当我读取java Function API时,有一种方法称为compose和撰写的签名是

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
}

1)第一个问题在哪里是T&amp; R宣布?它们在返回类型和参数中使用。或者我的理解是错的?

然后我在泛型教程中阅读了更多内容,然后尝试理解泛型中superextends的概念以及read here然后我更多地测试compose方法然后再次混淆superextends如何在compose方法中运作?

public static void main(String... args){
    Function<Integer, String> one = (i) -> i.toString();
    Function<String, Integer> two = (i) -> Integer.parseInt(i);
    one.compose(two);
}

如上所述,我已经用lamdas声明了两个函数。一个是Integer输入和String输出,另一个是与它相反的。

2)第二个问题IntegerStringextendssuper的关系? StringInteger类之间没有任何关系,没有人相互延伸,那么它是如何工作的?

我尽力解释我的问题/问题。让我知道你不明白我会再试一次。

3 个答案:

答案 0 :(得分:1)

1)compose函数是Interface Function<T,R>的一部分。正如您在此界面的文档中所看到的那样:

  

类型参数:

     

T - 函数输入的类型

     

R - 函数结果的类型

2)问题中的superextends约束不适用于T&amp; R,它们被应用于函数的泛型类型参数,作为参数传递给compose函数。

基本上这意味着如果你有:

Function<ClassA, ClassB> one;
Function<SomeSuperClassOfC, SomeSubclassOfA> two;

然后调用

是有效的
Function<ClassC, ClassB> three = one.compose(two)

答案 1 :(得分:1)

TR在哪里定义?

请记住,composeFunction界面中声明。它不仅可以使用自己的通用参数,还可以使用类型的通用参数。 RT在接口声明中声明:

interface Function<T, R> {
    ...
}

什么是? extends? super

?是通配符。这意味着泛型参数可以是任何东西。 extendssuper为通配符提供了约束。 ? super V表示无论?是什么,它都必须是VV本身的超类。 ? extends T表示无论?是什么,它都必须是TT本身的子类。

现在让我们来看看:

Function<Integer, String> one = (i) -> i.toString();
Function<String, Integer> two = (i) -> Integer.parseInt(i);
one.compose(two);

据此,我们可以推断TIntegerRString。什么是VV必须是某种类型,以满足约束Function<? super V, ? extends T>

我们可以通过替换我们传入的参数 - Function<String, Integer> - 来获取String super VInteger extends Integer

第二个约束已经满足,而第一个约束现在表示String必须是VString本身的超类。 String不能包含子类,因此V必须为String

因此,您可以编写如下内容:

Function<String, String> f = one.compose(two);

但不是

Function<Integer, String> f = one.compose(two);

撰写Function<Integer, String>Function<String, Integer>时,您无法获得Function<Integer, String>。如果您尝试这样做,V会自动推断为Integer。但String super Integer不满意,因此编译失败。现在看到约束的使用?这是为了避免程序员编写没有意义的东西。约束的另一个用途是允许你做这样的事情:

Function<A, B> one = ...
Function<C, SubclassOfB> two  = ...
Function<SubclassOfC, B> f = one.compose(two);

在这种情况下,IntegerString之间没有任何关系,所有关于V

答案 2 :(得分:0)

我会尝试从零开始解释; interface Function<T, R> - 这是一个方法的接口,必须实现R apply (T); 在Java之前的8中我们必须写:

Function<Integer, String> one = new Function<Integer, String>() {
    @Override
    public String apply(Integer i) {
        return i.toString();
    }
};

现在你可以使用它了:

String resultApply = one.apply(5);

现在,我想,你明白了。