具有无意义类型通配符的方法的Java API类

Dav*_*fer 3 java generics

在Java 8中,类java.util.Optional(javadoc)类提供"Maybe"MonadOption 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从指定从该组由子类路径给定类型的一些ObjectT(两者ObjectT包括)联合在拉出任何subinterfacing路径上找到的组接口"作为sidedish"通过implements.

? extends U简单地从扩展U(U包括)的类集合中指定一些类型.

所以可以写一下:

<U>可选<U>地图(功能<?super T,U> mapper)

没有丢失信息.

或不?

MC *_*ror 7

不完全的.

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(),这涉及下界上界的含义.

阅读更多:

  • 以下是我正在研究的这个例子:http://ideone.com/Yrfob9. (4认同)