通配符和类型变量之间有什么区别?

时间:2012-08-29 21:26:24

标签: java wildcard type-variables

考虑以下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()获得相同的输出。

因此,考虑到这个例子,通配符和类型变量之间有什么区别?

3 个答案:

答案 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}部分。