我正在查看流接口,发现了这种方法:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
我找不到“?扩展R”而不是R的任何原因:
<R> Stream<R> map(Function<? super T, R> mapper);
那么,如果我像上面那样做,会有什么区别?是不是?我传递的R变量是多少?它将扩展R我找不到原因。
答案 0 :(得分:7)
它使用? extends R
来允许将map
所采用的函数声明为返回R
的子类型
例如,给定此流:
Stream<Number> numberStream = Stream.of(1, 2L);
在随后的map
调用中,R
是Number
,但是函数的类型为Function<Number, Integer>
:
Function<Number, Integer> function = n -> Integer.valueOf(n.intValue());
Stream<Number> numberStream2 = numberStream.map(function); //would have failed
如果不使用? extends R
,则function
将是无效的参数(将需要Function<Number, Number>
)
答案 1 :(得分:0)
? extends R
意味着您可以传递其类是由R
的子类R
派生的对象。
因此map函数可以生成R
和R's subclass
作为结果。那是合理的。
例如,如果我们有以下类:
Animal
,Groose (extends Animal)
,Egg
Function<Egg, Groose> hatching
您可以编写以下代码:
List<Egg> eggs = getEggs();
List<Animal> myPets = eggs.stream().map(hatching)....
您可以看到您的map
函数要求使用Animal
类型(R
),但是您的映射器返回Groose
类型(即? extends R
)。如果map
函数写为<R> Stream<R> map(Function<? super T, R> mapper);
,则必须添加从Groose
到Animal
的另一次转换。
您可以参考this answer并了解<? extends T>
。
答案 2 :(得分:0)
在Java中,泛型是不变的,这意味着即使S扩展了P,以下代码也会引发编译错误-
List<S> list1 = neww ArrayList<>();
List<P> list2 = list1 ; // compile error
但是如果您有Listthen,则可以执行以下操作:
List<S> list1 = neww ArrayList<>();
List<? extends P> list2 = list1 ;