有人可以解释这些java泛型方法的声明吗?

时间:2011-01-14 15:13:28

标签: java generics declaration

我正在阅读Gilad Bracha撰写的“Java编程语言中的泛型”,我对一种声明风格感到困惑。以下代码位于第8页:

interface Collection<E> 
{ 
    public boolean containsAll(Collection<?> c); 
    public boolean addAll(Collection<? extends E> c); 
} 


interface Collection<E> 
{ 
    public <T> boolean containsAll(Collection<T> c);
    public <T extends E> boolean addAll(Collection<T> c); 
    // hey, type variables can have bounds too! 
} 

我的困惑来自第二次宣言。我不清楚<T>声明在以下行中的用途是什么:

    public <T> boolean containsAll(Collection<T> c);

该方法已经有一个与之关联的类型(布尔值)。

为什么要使用<T>以及它对编码器有什么作用?

我认为我的问题需要更具体一些。

你为什么要写:

  public <T> boolean containsAll(Collection<T> c);

VS

  public boolean containsAll(Collection<T> c);

我不清楚在{contains}的第一个声明中<T>的目的是什么。

6 个答案:

答案 0 :(得分:3)

  

该方法已经有一个与之关联的类型(布尔值)。

这是 return 类型。该方法的完整类型是“采用Collection<T>(对于某些T)参数并返回boolean”的方法。

这就是T的用武之地:函数的参数使用它。换句话说,可以使用不同类型作为参数调用此方法。这些类型的唯一限制是它们必须实现Collection<T>接口,它本身依赖于泛型参数T(存储在集合中的对象的类型)。

答案 1 :(得分:3)

据我所知,在这种情况下<T>根本没有提供任何有用的东西。它创建的方法在功能上完全等同于使用通配符的方法。

以下是 有用的几个示例:

public List<?> transform(List<?> in);
//vs
public <T> List<T> transform(List<T> in);

在上面,您可以将返回类型与输入类型相关联。第一个示例无法关联两个通配符的运行时类型。

public void add(List<?> list, Object obj);
//vs
public <T> void add(List<? super T> list, T obj);

在上文中,第一种方法甚至无法将obj添加到list,因为它不能被视为类型安全。第二个中的泛型参数确保list可以保存obj所属的任何类型。

答案 2 :(得分:2)

?只是一个通配符。这意味着该方法将接受任何类型的Collection。

<T>是方法的类型参数。它实质上是为通配符分配一个名称,然后可以在方法声明和定义的其他地方引用该名称。

如果方法的返回类型根据传入的类型而有所不同,则可以更好地说明差异。

假设你开始使用类似

的方法

Object getRandomElement( Collection<?> c )

这将接受任何Collection,但无法约束其返回类型。因此调用者必须将结果转换回它预期的任何类型 - 这应该可行,但会引发不安全的类型转换警告。

使用类型参数,您可以改为编写

<T> T getRandomElement( Collection<T> c )

在这种情况下,如果使用Collection<String>调用此方法,编译器将知道它将返回String

答案 3 :(得分:1)

此处使用的

<T>(在方法声明中,返回类型之前)是泛型类型声明。您可以定义要在方法中使用的新泛型类型:http://download.oracle.com/javase/tutorial/java/generics/genmethods.html

答案 4 :(得分:0)

尝试在没有<T>的情况下进行编译。

基本上,它告诉编译器这个方法包含一个泛型。在第一个例子中不需要它,因为?是一种特殊情况,第二种方法是引用接口本身定义的类型。

在不相关的注释中,接口中不需要公共。默认情况下,界面中的方法是公共的,因此可以节省一些输入。

答案 5 :(得分:0)

它声明了方法使用的泛型类型T。虽然泛型类型E对于整个接口T是相同的,但仅限于声明它的方法。