什么时候使用Java通用WildCard?

时间:2018-09-30 15:32:12

标签: java generics

有人在评论中说,问题正在引起混乱。所以,我已经编辑了这个问题,让我知道,如果它仍然引起混乱。

考虑以下代码:

班级雇员{}

Class ContractEmployee类扩展Employee { }

PermanentEmployee类扩展了Employee { }    ...

谁能提供以下两种情况之间的基本区别? 何时使用哪个

情况:1

public <T extends Employee> void empTest(ArrayList<T> list)

public <? extends Employee> void empTest(ArrayList<?> list)

情况:2

public void empTest(ArrayList<? extends Employee> list)

public void empTest(ArrayList<T extends Employee> list)

2 个答案:

答案 0 :(得分:0)

没有完整的解释,但您将从这里开始。我们需要在泛型中遵循PECS模式。 PECS代表 P 引纸器 E xtends和 C 消费方 S 上方。

在下面的行中,
     public void empTest(ArrayList列表)
您基本上是在提供列表,该列表将在该方法内进一步用作生产者。现在,您可能知道,泛型只是编译时的错觉,并且会在运行时删除,因此mrthod empTest中的代码期望使用特定Employee的列表。例如,如果您将Fruit作为Orange和Apple的超类,则不应向消费者提供Orange和Apple的列表,而不能将其限制为Apple或Orange。是否有意义?我猜是。

答案 1 :(得分:0)

首先,您的问题是很合理的,尽管通过您的示例,很难解释/理解差异。

在所有变体中,您都想定义一个方法empTest(),该方法接受Employee的ArrayList或Employee的子类。您可以使用

public void empTest(ArrayList<? extends Employee> list) { ... }

那么,其他语法变体又意味着什么呢?我们使用另一个示例,因为您的empTest()方法不需要其他任何东西。

说,我们想使用类似addEmp(list, emp);的方式将员工添加到列表中。第一个想法可能是:

public void addEmp(ArrayList<Employee> list, Employee emp) { ... }

但是那样做不会做,因为您将无法将ArrayList<ContractEmployee>传递给方法。下次尝试:

public void addEmp(ArrayList<? extends Employee> list, Employee emp) { ... }

现在它接受列表,但是它还允许您将ArrayList<ContractEmployee>PermanentEmployee组合使用,并且不能将PermanentEmployee添加到ArrayList<ContractEmployee>允许的。编译器会将添加员工的方法正文中的行标记为非法。

因此,我们在这里需要的是检查两个地方是否使用相同类型的员工,这就是命名类型参数可用于的用途。

public <T extends Employee> void addEmp(ArrayList<T> list, T emp) { ... }

这表示:可以传入ArrayList的任何子类型的Employee,我们将其称为T。然后,emp参数还必须来自相同的子类型T(或由于正常的类继承而来自子子类型)。

如果不是Employee并没有改变方法,您甚至可以编写

public <T> void addEmp(ArrayList<T> list, T emp) { ... }

总结一下:

  • 如果需要比纯<... extends SomeClass>结构更多的可变性,请使用<SomeClass>结构。
  • 如果只是一个需要这种可变性的地方,通常就不需要为子类引入名称,因此方法的参数列表中的<? extends SomeClass>可以完成工作。
  • 如果您需要在多个地方使用相同的子类,则需要为其命名,因此请在return-type声明前使用<T extends SomeClass>之类的名称,并在不包含尖括号的情况下使用T参数列表。

关于语法: -如果您需要为type参数引入名称,请在返回类型之前完成。 -在方法返回类型或方法参数列表中,您只能使用已经存在的名称,或使用未命名的通配符构造。