猿问

Java 通配符有界泛型

我正在努力使用 Java 8 通配符泛型。


假设一个泛型类(来自 Core Java 书籍)称为 Pair<T>


class Pair<T> {

    private T first;

    private T second;


    public Pair() {

        first = null;

        second = null;

    }

    public Pair(T first, T second) {

        this.first = first;

        this.second = second;

    }

    public T getFirst() { return first; }

    public T getSecond() { return second; }

    public void setFirst(T newValue) { first = newValue; }

    public void setSecond(T newValue) { second = newValue; }

}

假设有以下类层次结构:

base Employee(层次结构的顶部),然后

Manager扩展Employee,然后

Executive扩展Manager


下面的代码有效,但我不明白为什么允许它。


Pair<? super Manager> pm2 = 

    new Pair<>(

      new Employee(1,"Yuri"), // Employee is super of Manager

      new Executive()); // Executive is not super of Manager 

// why Executive is allowed in above Pair<T> ?


Employee ex1 = (Employee) pm2.getFirst(); // OK

Manager ex2 = (Manager) pm2.getSecond(); // OK

Executive ex3 = (Executive) pm2.getSecond(); // why is allowed?

我不明白为什么 Executive 在上面工作,因为它不是超级类型,而是经理的子类型。


是因为 Java 8 编译器会转换吗?超级店长到对象,所以任何事情都会被允许?


森栏
浏览 163回答 1
1回答

MMTTMM

当您声明时:Pair<? super Manager> pm2 = ...Pair接受泛型的方法可以替换泛型 byManager和它的子类(在您的情况下Executive)。所以从逻辑上讲,当您使用泛型调用方法时,您将得到以下结果:Pair<? super Manager> pm2 = ...;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;pm2.setFirst(new Executive());&nbsp; // compilepm2.setFirst(new Manager());&nbsp; // compilepm2.setFirst(new Employee()); // doesn't compile最后就像你没有使用任何通配符:Pair<Manager> pm2 = ...;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;pm2.setFirst(new Executive());&nbsp; // compilepm2.setFirst(new Manager());&nbsp; // compilepm2.setFirst(new Employee()); // doesn't compile因此,在您的示例中,您使用的下限通配符是无助的。事实上,它是最糟糕的,因为您将它用于从泛型类型中放入和获取东西,而下界通配符旨在放入东西,而不是从中获取东西。而您必须执行的强制转换会破坏通用目的(类型安全):Employee ex1 = (Employee) pm2.getFirst(); // OKManager ex2 = (Manager) pm2.getSecond(); // OKExecutive ex3 = (Executive) pm2.getSecond(); // why is allowed?那么我们需要如何使用Pair<? super Manager>呢?因为我们希望泛型集合Pair可以分配给其他Pair类型以“放入”东西。非常常见的用例是声明一个接受泛型类型的方法<? super>。但在这种情况下,我们希望将未知类型限制为特定类型或超类型,以防止“放置”可能危及作为参数传递的泛型类型的类型安全的东西。例如,假设您需要一个接受 a PairofManager实例并将事物放入 this 的方法Pair。您不希望客户端方法可以传递 aPair<Executive>否则如果我们添加 a 可能会破坏通用安全性Manager,因为 aManager不是Executive实例所必需的。这里是下界通配符的主要作用。示例代码来说明:public void putStuff(Pair<? super Manager> managers) {&nbsp; &nbsp; if (...){&nbsp; &nbsp; &nbsp; &nbsp;managers.setFirst(new Manager());&nbsp; &nbsp; }&nbsp; &nbsp; else if (...){&nbsp; &nbsp; managers.setFirst(new Executive());&nbsp; &nbsp;}}现在只有类型或超类型Manager的Pair泛型类型可以传递:putStuff(new Pair<Manager>(...)); // compileputStuff(new Pair<Employee>(...)); // compileputStuff(new Pair<Executive>(...)); // doesn't compile
随时随地看视频慕课网APP

相关分类

Java
我要回答