前段时间我学习了java泛型,但现在我正在学习集合,发现了一些我不理解的代码。这是代码:
static <E> List<E> nCopies(int n, E value)
来自班级java.util.Collections
。
我的问题是为什么会有:
<E> List<E>
而不仅仅是
List<E>
显然我错过了什么,有人可以为我澄清一下吗?
答案 0 :(得分:14)
您使用<E>
来表示您定义的方法。
泛型的最常见例子是有一个这样的典型类:
public class SomeClass<E> {
...
}
然后,当您创建该类的新对象时,您可以直接定义类型:
new SomeClass<String>();
这样,该类中引用的任何方法都将视为该实例的String。
现在考虑一个静态方法(没有绑定到类的任何特定实例),为了代表该方法,您使用了另一种适用于方法的典型,如下所示:
static <E> List<E> nCopies(int n, E value)
你在返回类型之前使用<E>
来说&#34;这个特殊方法在执行时会考虑一些E&#34;。调用方法时会确定<E>
的内容:
nCopies(3, "a");
在此示例中,<E>
将是一个String,因此返回类型将为List<String>
。
最后,您甚至可以将它们混合在一起:
public class SomeClass<E> {
public <F> void doSomething(E e, F f){
...
}
}
在这种情况下,如果你有一个SomeClass的实例,doSomething方法中的E将始终是String(对于那个实例),但F可以是你想要的任何东西。
答案 1 :(得分:11)
在<E> List<E>
中,第一个<E>
表示E
是类型参数。如果您没有指定它,那么Java会认为E
中的E value
引用了名为E
的实际类,并要求您导入它。请参阅generic methods。
答案 2 :(得分:4)
<E>
需要告诉编译器您打算使用E
作为类型参数,就像创建泛型类时一样(例如public interface List<E>
)。
由于接口或类名上没有规则(只有约定)是多个字符,并且没有规则(只有约定)类型参数名称必须是一个字符,编译器不会知道你打算它是类型参数而不是具体的类名。
很多人一直在说这与静态方法直接相关。事实并非如此。您可以拥有一个在其自己的类型参数上通用的实例方法(尽管通常,类型参数将与类类型参数相关)。
以下是您可以拥有此内容的示例:
public class MyList<E> {
public <N super E> MyList<N> createCopy() {
//...
}
}
此方法允许您创建列表的副本,但不限制您使用与列表相同的类型,而是允许您使用超类型。例如:
MyList<Integer> integers = createList(1, 2, 5);
MyList<Number> numbers = integers.createCopy();
答案 3 :(得分:2)
List<E>
是方法的返回类型,而<E>
是传入的类型(这是由编译器根据{{1}传递的内容推断的}})。
E value
这将被称为:
static <E> List<E> someMethod(E myObject)
{
E objectOfMyType = myObject;
List<E> myList = new ArrayList<E>();
...
return myList;
}
恕我直言,方法的语法有点傻,但你有它。相关的Oracle教程在这里: http://download.oracle.com/javase/tutorial/extra/generics/methods.html
答案 4 :(得分:0)
简而言之:表示E
不是类。如果List<E>
是一个类(或接口),则E
将是有效的返回类型-尽管不建议这样做,但是一个类可以用单个字母命名(因为类型变量也可以用更多字母命名。 ,甚至使用现有的类名,也会使任何人感到困惑:static <Integer> List<Integer> method() {...}
。