Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有人能解释一下这些java泛型方法的声明吗?_Java_Generics_Declaration - Fatal编程技术网

有人能解释一下这些java泛型方法的声明吗?

有人能解释一下这些java泛型方法的声明吗?,java,generics,declaration,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> { p

我正在阅读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! 
} 
接口集合
{ 
公共图书馆(c组);
公共布尔addAll(集合
该方法已具有与其关联的类型(布尔值)

这就是返回类型。该方法的完整类型是“采用
集合
(对于某些
T
)参数并返回
布尔值
”的方法


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

尝试在不使用
的情况下编译它

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


另一方面,接口中不需要public。默认情况下,接口中的方法是public的,因此可以节省一些输入。

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

此处使用的
(在方法声明中,返回类型之前)是泛型类型声明。您可以定义新的泛型类型以在方法中使用:

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

这里有几个例子,它将非常有用:

public List<?> transform(List<?> in);
//vs
public <T> List<T> transform(List<T> in);
公共列表转换(列表中);
//vs
公共列表转换(列表中);
在上面的示例中,您可以将返回类型与输入类型关联起来。第一个示例无法将两个通配符的运行时类型关联起来

public void add(List<?> list, Object obj);
//vs
public <T> void add(List<? super T> list, T obj);
公共作废添加(列表,对象obj);
//vs

public void add(ListThe?只是一个通配符。这意味着该方法将接受任何类型的集合

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

如果方法的返回类型根据传入的类型而变化,则可以更好地说明这种差异

假设你开始的方法是

对象getRandomElement(集合c)

这将接受任何集合,但无法约束其返回类型。因此,调用方必须将结果强制转换回它期望的任何类型——这应该可以工作,但会引发不安全的类型转换警告

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

T getRandomElement(集合c)


在这种情况下,如果您使用
集合调用此方法
,编译器知道它将返回
字符串

,如果您理解PEC,那么您将理解这些。请查看Oracle/Sun JDK 6中的此处,使用了第一个示例,因此我不知道您是否会使用第二个。为什么它比
公共bo更好olean containsAll(集合c);
?但为什么这比看似功能等价的
公共布尔containsAll(集合c)
?同样,为什么不
公共布尔addAll(收集更好,因为方法的主体或定义可以引用类型T,代码可以避免强制转换,并由编译器保证类型安全。有关进一步的解释,请参阅我的答案。@Dave Costa:我没有看到您的答案,但使用
是否有助于其他方法无关紧要。我们现在讨论的是我自己thods,它似乎没有提供任何好处。@Mark——刚刚完成了我的回答。是的,你是对的,它在这些方法声明中没有任何区别——尽管t参数可能在实现体中被引用。但我认为原始问题更一般。说得好。我认为这是一个好问题经验法则是,只有当您具有参数化的返回类型(如
Collections.emptyList()
)或需要将返回类型或其他参数与参数化或泛型参数关联时,才需要type参数。
  public boolean containsAll(Collection<T> c);
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);