为什么这个泛型方法中还有一个额外的<e>?</e>

时间:2011-11-14 01:46:17

标签: java generics methods

前段时间我学习了java泛型,但现在我正在学习集合,发现了一些我不理解的代码。这是代码:

static <E> List<E> nCopies(int n, E value)

来自班级java.util.Collections

我的问题是为什么会有:

<E> List<E>

而不仅仅是

List<E>

显然我错过了什么,有人可以为我澄清一下吗?

5 个答案:

答案 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() {...}