当前位置: 首页 > 知识库问答 >
问题:

Java通配符有界泛型

孙文康
2023-03-14

我正在与Java8通配符泛型作斗争。

假设一个名为pair 的泛型类(来自Core Java book)

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; }
}
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?

是因为Java8编译器转换吗?超级经理反对,因此任何事情都是允许的?

共有1个答案

祁景山
2023-03-14

正如你所声明的:

Pair<? super Manager> pm2 = ...

接受泛型的方法可以用manager及其子类(在您的例子中是execution)替换泛型。

因此,从逻辑上讲,当您使用泛型调用一个方法时,您将得到以下结果:

Pair<? super Manager> pm2 = ...;        
pm2.setFirst(new Executive());  // compile
pm2.setFirst(new Manager());  // compile
pm2.setFirst(new Employee()); // doesn't compile
Pair<Manager> pm2 = ...;        
pm2.setFirst(new Executive());  // compile
pm2.setFirst(new Manager());  // compile
pm2.setFirst(new Employee()); // doesn't compile
Employee ex1 = (Employee) pm2.getFirst(); // OK
Manager ex2 = (Manager) pm2.getSecond(); // OK
Executive ex3 = (Executive) pm2.getSecond(); // why is allowed?

那么我们需要如何使用pair<?超级管理器>
因为我们希望泛型集合可以分配给其他类型来“放入”东西。
最常见的用例是声明一个接受泛型类型<?super>.
但是在本例中,我们希望将未知类型限制为特定类型或超类型,以防止“放置”可能危及作为参数传递的泛型类型的类型安全的东西。

例如,假设您需要一个方法接受管理器实例的,并将内容放在这个中。您不希望客户端方法传递 ,否则,如果我们添加管理器,它可能会破坏一般安全性,因为管理器不是必须的execution实例。下面是下界通配符的主要作用。

示例代码来说明:

public void putStuff(Pair<? super Manager> managers) {
    if (...){
       managers.setFirst(new Manager());
    }
    else if (...){
    managers.setFirst(new Executive());
   }
}

现在只能传递泛型类型的管理器的类型或超级类型:

putStuff(new Pair<Manager>(...)); // compile
putStuff(new Pair<Employee>(...)); // compile
putStuff(new Pair<Executive>(...)); // doesn't compile

 类似资料:
  • 根据Joshua Bloch的“有效Java”一书,关于如何/何时在泛型中使用有界通配符有一个规则。这个规则就是PECS(productor-extends,Comsumer-Super)。当我研究以下示例时: 根据PECS规则,上述声明是错误的。但是我希望有一个的,并向这个传递一个。为什么不做呢? 为什么要始终使用关键字?为什么使用是错误的? 当然,这也代表了Comsumer的观点。为什么消费者

  • 问题内容: 您好直接从Oracle http://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html提供的Java教程中 我知道编译时的类型擦除。而且我也知道,一个类型(无界)将被Object取代。知道在编译时如何使用无界通配符进行编译吗?只是删除它,因为它是原始类型? 提前致谢。 问题答案: 假设我们有一个

  • null 编译,我真的不明白为什么。基本上与第1行相同的问题。是的超类,如何将超类的成员放入此中? 编译。与第1行相同的问题。

  • 问题内容: 我有一个接口将对象转换为字符串: 以及用于存储所有可用转换器的地图: 现在,我有了要转换的异构数据列表,如下所示: 但是此代码无法编译: 我应该如何更改代码? 问题答案: 您面临的问题称为通配符捕获。Java无法识别将从数据中接收的类型。尝试以两种方式中的任何一种重构代码 方法1:如下 更改您的界面 方法2: 通过类型推断来捕获通配符的Helper方法 创建如下的帮助方法, 如下调用此

  • null 为什么我不能在MyList中添加对象。因为如果我们使用super,这意味着这个列表可以包含在Java类的继承制度中等于或高于number的对象。因此应该按照该语句在列表中添加新的Object()。 多谢了。

  • 上限通配符下限通配符 有人能帮我理解一下吗?