在Java 8中,类java.util.Optional(javadoc)类提供"Maybe"Monad或Option Type的功能.
更直接:
public final class java.util.Optional <T> extends Object
容器对象,可能包含也可能不包含非null值.如果存在值,则isPresent()将返回true,get()将返回该值.
其中一种方法是:
<U>可选<U>地图(功能<?super T,?extends U> mapper)
如果存在值,则将提供的映射函数应用于该值,如果结果为非null,则返回描述结果的Optional.
问题是为什么map()在类型上使用类型通配符U.
我对类型通配符的理解很简单:
? super T从指定从该组由子类路径给定类型的一些Object到T(两者Object并T包括)联合在拉出任何subinterfacing路径上找到的组接口"作为sidedish"通过implements.
并? extends U简单地从扩展U(U包括)的类集合中指定一些类型.
所以可以写一下:
<U>可选<U>地图(功能<?super T,U> mapper)
没有丢失信息.
或不?
不完全的.
A Function<? super T, U>与a不同Function<? super T, ? extends U>.
例如,Optional<CharSequence>即使我传递Function<Object, String>给方法,我仍然可以得到一个.如果方法被定义为<U> Optional<U> map(Function<? super T, U> mapper),那么这是不可能的.
那是因为泛型是不变的:<T>不一样<? extends T>.这是用Java语言实现的设计决策.
让我们看看Jon Skeet如何解释如果泛型不是不变的会发生什么:
class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }
Run Code Online (Sandbox Code Playgroud)
public void ouch() {
List<Dog> dogs = Arrays.asList(new Dog(), new Dog());
List<Animal> animals;
// This would be legal, right? Because a list of dogs is a list of animals.
List<Animal> animals = dogs;
// This would be legal, right? Because a cat could be added to a
// list of animals, because a cat is an animal.
animals.add(new Cat());
// Unfortunately, we have a confused cat.
}
Run Code Online (Sandbox Code Playgroud)
虽然我不完全确定你在评论中的意思,但我会试着详细说明.
如果你有完全控制Function您提供的,不要紧的方法的签名是否Function<? super T, U>还是Function<? super T, ? extends U>,你只是适应您的Function相应.但是该方法的作者可能希望该方法尽可能灵活,允许人们提供Function第二个参数也是其子类U,而不仅仅是U它自己.实际上,你将其下限U扩展到某个子类型U.
因此该函数应该真正阅读,
<U> Optional<? the-most-general-but-fixed-supertype-of U> map(Function<? super T, U> mapper)但表达方式会很尴尬.
我确实很尴尬.此外,您提出的符号与实际方法签名之间存在差异map(),这涉及下界和上界的含义.
阅读更多:
| 归档时间: |
|
| 查看次数: |
118 次 |
| 最近记录: |