考虑以下Employee类和一个名为Manager-
的子类public class Employee
{
private String name;
public Employee(String name)
{
this.name = name;
}
public String getInfo()
{
return name;
}
}
public class Manager extends Employee
{
public Manager(String name)
{
super(name);
}
}
在另一个课程中,我定义了两个函数 -
import java.util.ArrayList;
public class WildCardsAndTypeVariables
{
public static <T extends Employee> void displayInfo(ArrayList<T> employees)
{
for (int i=0; i<employees.size(); i++)
{
Employee employee = (Employee) employees.get(i);
System.out.println(employee.getInfo());
}
}
public static void displayInfo2(ArrayList<? extends Employee> employees)
{
for (int i=0; i<employees.size(); i++)
{
Employee employee = (Employee) employees.get(i);
System.out.println(employee.getInfo());
}
}
public static void main(String[] args)
{
Employee e1 = new Employee("John");
Employee e2 = new Employee("Joe");
Employee e3 = new Manager("Joseph");
ArrayList<Employee> employees = new ArrayList<Employee>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
displayInfo(employees);
displayInfo2(employees);
}
}
我从displayInfo()和displayInfo2()获得相同的输出。
因此,考虑到这个例子,通配符和类型变量之间有什么区别?
答案 0 :(得分:3)
在这样的情况下,该方法只接受一个参数并且具有void
返回类型,您不会获得任何好处,或者在通配符类型版本和泛型方法版本之间的语义上没有任何差别。当您在方法签名(参数类型或返回类型)中多次使用类型变量时,泛型方法的真正功能就来了,这是一个简单的例子
public static <T extends Employee> T firstEmployee(ArrayList<T> employees) {
return employees.get(0);
}
其中说“此方法采用一个ArrayList,其成员都是Employee
(或Employee
本身的某个子类的实例),它返回的值是的实例 class“。这是你无法用通配符表达的东西。
答案 1 :(得分:1)
当您使用类型(示例T)时,您将只能发送特定类型的Concrete对象。
但是,当您使用通配符时,您正在定义对象的边界。因此,您可以传递T(或)类型为T的对象。
在你的情况下,你只有Empoylee,所以没有太大的区别。但是,让我们说你有一个类承包商,它扩展了员工。然后你会看到差异。
答案 2 :(得分:0)
您的示例存在很多问题。
在displayInfo2
中,您应该在阅读时使用? extends Employee
,而不是在传递的数组中编写Employee
个对象。例如,如果您想将Manager
数组传递给该方法,则在进行此更正之前不会进行类型检查。
一旦修复,您就不需要在任何一种方法中将调用转移到employees.get()
。
不同之处仅在于您在T
中为未知类型指定了名称(displayInfo
)。 Java中的某些情况要求您拥有该类型的名称(我将继续使用链接编辑此帖子),但在此特定示例中,您只需使用通配符即可,因为您关心的只是{{1}部分。