2

我正在Core Java volume-1 by Horstmann, Cay.S阅读generics。我无法理解教科书的一些解释。我给出了作者引用的示例代码。其次是书中的文字和我的问题。

 class Employees{ }

class Manager extends Employees { }

class Pair<T>{

    private T first;
    private T second;

    Pair(T first, T second){
        this.first=first;
        this.second=second;
    }


    void setFirst(T value){
        first=value;
    }

    T getFirst(){
        return first;
    }

}


public class WildCardGenerics {

    public static void main(String[] args){


        Manager ceo = new Manager();
        Manager cfo=new Manager();

        Employees clerk = new Employees();

        Pair<Manager> managers= new Pair<>(ceo,cfo);
        Pair<? extends Employees> employees=managers;

        employees.setFirst(clerk);



    }
    }

从书中:

"""没有损坏是可能的。调用setFirst是一个type error。要了解原因,让我们仔细看看 type Pair<? extends Employee>。它的方法如下所示:

? extends Employee getFirst()
void setFirst(? extends Employee)

这使得无法调用该setFirst方法。compiler唯一知道它需要一些subtype,但Employees它不知道是哪种类型。它拒绝pass any specific type——毕竟 ?可能不匹配它。"""

问题:我不明白为什么它拒绝传递任何特定类型。那么这个方法接受什么? ? extends Employee-- 表示包括 Employee 和 Employee 的任何子类型。所以通过员工应该是合法的吗?

从书中:

pair<? super Manager> has methods:
void setFirst(? super Manager)
? super Manager getFirst()

编译器不知道该setFirst方法的确切类型,因此不能用 type 的对象调用它Employee or Object,而只能用Managersubtypeas来调用它executive

问题:所以在这里我说该方法可以接受任何 Manager 对象或扩展 Manager 对象(类似于上面绑定的 subytpe)。我不清楚为什么?

从书中:

Intuitively speaking, wildcards with supertype bounds let you write to a generic object, while wildcards with subtype bounds let you read from a generic object.

问题:我根本无法遵循它。听上去很简单,但不符合逻辑的意思。

4

2 回答 2

2

以下赋值是合法的,只要ClerkEmployees[sic]。

Pair<? extends Employees> employees = new Pair<Clerk>(clerk1, clerk2);

你不应该能够调用setFirst和传递 a Manager,因为在这里,它真的是Pair<Clerk>

T这说明了为什么如果存在? extends通配符,Java 不允许调用其中包含泛型类型参数的方法 ( )。编译器不知道它到底是哪个类 - Employee?一个子类?哪个子类?由于类型擦除,JVM 无法检查类型安全性,因此编译器必须禁止所有此类调用,除了null可以强制转换为任何引用类型并且始终允许。

? super Employee下界是Employee。可能是Pair<Object>。但是,传递一个Employee或一个它的子类是安全的,因为它们是任何? super Employee.

于 2014-02-12T22:44:12.550 回答
1

总是读? extends T作“一些CAP#1扩展的T”和? super T“一些扩展的”。CAP#2T

现在您的示例更具可读性:

“不可能有损坏。对 setFirst 的调用是类型错误。要了解原因,让我们仔细看看 type Pair< some CAP#1 extending Employee >。它的方法如下所示:

CAP#1 getFirst()
void setFirst( CAP#1 value )

由于is 是一种虚构的类型,因此您不能使用,CAP#1调用,因为您无法知道is或它的某个随机子类型。 是一种逆变方法;它使用泛型类型的实例。setFirst()EmployeeCAP#1EmployeesetFirst()

但是,无论如何CAP#1,它都 extends Employee,因此您可以调用getFirst()并将结果分配给Employee-typed 变量。 getFirst()协变的;它产生泛型类型的实例。

Pair< ? extends Employee >所以你问,如果你不能在这样的变量上使用一半的方法,你到底为什么想要一个 type的变量?

因为您可以使用通配符类型做的一件事是解决 Java 中的一些差异问题。无论我有 aPair< Employee >或 aPair< Manager >还是 a Pair< SomeClassExtendingManager >,我都可以将那个东西分配给 type 的变量Pair< ? extends Employee >。即使其中没​​有逆变方法,我也无法将 a 分配给Pair< Manager >type 的变量,因为类型系统无法解决这个问题。Pair< Employee >Pair

于 2014-02-12T23:03:15.343 回答