我对仿制药的工作方式感到困惑?我正在了解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宣布?它们在返回类型和参数中使用。或者我的理解是错的?
然后我在泛型教程中阅读了更多内容,然后尝试理解泛型中super
和extends
的概念以及read here然后我更多地测试compose
方法然后再次混淆super
和extends
如何在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)第二个问题是Integer
和String
与extends
和super
的关系? String
和Integer
类之间没有任何关系,没有人相互延伸,那么它是如何工作的?
我尽力解释我的问题/问题。让我知道你不明白我会再试一次。
答案 0 :(得分:1)
1)compose
函数是Interface Function<T,R>
的一部分。正如您在此界面的文档中所看到的那样:
类型参数:
T - 函数输入的类型
R - 函数结果的类型
2)问题中的super
和extends
约束不适用于T&amp; R,它们被应用于函数的泛型类型参数,作为参数传递给compose
函数。
基本上这意味着如果你有:
Function<ClassA, ClassB> one;
Function<SomeSuperClassOfC, SomeSubclassOfA> two;
然后调用
是有效的Function<ClassC, ClassB> three = one.compose(two)
答案 1 :(得分:1)
T
和R
在哪里定义?
请记住,compose
在Function
界面中声明。它不仅可以使用自己的通用参数,还可以使用类型的通用参数。 R
和T
在接口声明中声明:
interface Function<T, R> {
...
}
什么是? extends
和? super
?
?
是通配符。这意味着泛型参数可以是任何东西。 extends
和super
为通配符提供了约束。 ? super V
表示无论?
是什么,它都必须是V
或V
本身的超类。 ? extends T
表示无论?
是什么,它都必须是T
或T
本身的子类。
现在让我们来看看:
Function<Integer, String> one = (i) -> i.toString();
Function<String, Integer> two = (i) -> Integer.parseInt(i);
one.compose(two);
据此,我们可以推断T
是Integer
而R
是String
。什么是V
? V
必须是某种类型,以满足约束Function<? super V, ? extends T>
。
我们可以通过替换我们传入的参数 - Function<String, Integer>
- 来获取String super V
和Integer extends Integer
。
第二个约束已经满足,而第一个约束现在表示String
必须是V
或String
本身的超类。 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);
在这种情况下,Integer
和String
之间没有任何关系,所有关于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);
现在,我想,你明白了。