为什么这个泛型方法有一个额外的 ?

时间:2020-12-29 20:45:00

I learned java generics some time ago, but now I'm learning collections and found some code that I don't understand. Here is the code:

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

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

It is from class java.util.Collections.

它来自类java.util.Collections。

My question is why there is:

我的问题是为什么会有:

<E> List<E>

and not only

不仅

List<E>

Obviously I am missing something, can someone clarify this for me?

很明显我错过了什么,有人能帮我澄清一下吗?

4 个解决方案

#1


11  

In <E> List<E>, the first <E> denotes that E is a type parameter. If you hadn't specified it, then Java would think the E in E value referred to an actual class named E, and ask you to import it. See generic methods.

列表 中,第一个 表示E是一个类型参数。如果您没有指定它,那么Java会认为E的E值指向一个名为E的实际类,并要求您导入它。看到泛型方法。

#2


13  

You use the <E> to typify the method you are defining.

您使用 来类型化所定义的方法。

The most common example of generics is to have a typified class like this:

泛型最常见的例子是有一个类型化的类:

public class SomeClass<E> {
    ...
}

Then, when you are creating a new object of that class you define the type directly like this:

然后,当您创建该类的新对象时,您直接定义类型如下:

new SomeClass<String>();

That way any method in that class that refers to , will treat as a String, for that instance.

这样,类中引用的任何方法,都将被视为字符串。

Now consider a static method (which is not bound to any particular instance of a class), in order to typify that method you have use another kind of typification which applies to methods, like this:

现在考虑一个静态方法(它不绑定到类的任何特定实例),为了对该方法进行类型化,您使用了另一种类型的类型化,这种类型化适用于方法,如下所示:

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

You use the <E> before the return type to say "this particular method will consider some E when it executes". What <E> will be is decided when you invoke the method:

在返回类型之前使用 表示“这个特定的方法在执行时将考虑某些E”。当您调用该方法时,将决定 的值:

nCopies(3, "a");

In this example <E> will be a String, so the return type will be a List<String>.

在本例中, 将是一个字符串,因此返回类型将是一个列表

Finally, you can even mix them both:

最后,你甚至可以将两者混合:

public class SomeClass<E> {
    public <F> void doSomething(E e, F f){
        ...
    }
}

In this case, if you have an instance of SomeClass, the E in the doSomething method will always be String (for that instance), but the F can be anything you want it to be.

在本例中,如果您有一个SomeClass的实例,doSomething方法中的E将始终是String(对于该实例),但是F可以是您希望的任何值。

#3


3  

The <E> is required to tell the compiler that you intend to use E as a type parameter, the same way you do when you make a generic class (e.g. public interface List<E>).

需要 告诉编译器您打算使用E作为类型参数,就像您创建泛型类时所做的那样(例如,public interface List )。

Since there is no rule (only conventions) on interface or class names being more than one character, and no rule (only conventions) that type parameter names have to be one character, the compiler would not know you intended it to be a type parameter rather than a concrete class name.

由于接口或类名上没有规则(只有约定)是多于一个字符,而且类型参数名称必须是一个字符的规则(只有约定),因此编译器不会知道您希望它是一个类型参数,而不是一个具体的类名。

Edit

A lot of people have been saying this is directly related to static methods. That is not true. You can have an instance method that is generic on its own type parameters as well (though typically, the type parameters will be related to the class type parameters).

很多人都说这与静态方法直接相关。这是不正确的。您还可以拥有一个实例方法,该方法在自己的类型参数上也是通用的(尽管通常,类型参数将与类类型参数相关)。

Here's an example of where you could have this:

这里有一个例子可以说明这一点:

public class MyList<E> {

    public <N super E> MyList<N> createCopy() {
        //...
    }
}

This method would allow you to create a copy of the list but not restrain you to using the same type as the list you have, but rather allowing you to use a supertype. For example:

该方法允许您创建列表的副本,但不限制您使用与列表相同的类型,而是允许您使用超类型。例如:

MyList<Integer> integers = createList(1, 2, 5);
MyList<Number> numbers = integers.createCopy();

#4


2  

List<E> is the return type for the method whereas <E> is the type being passed in (This is inferred by the compiler from what is being passed as E value).

List 是方法的返回类型,而 是被传入的类型(编译器从以E值传递的内容推断出这一点)。

static <E> List<E> someMethod(E myObject)
{
    E objectOfMyType = myObject;
    List<E> myList = new ArrayList<E>();
    ...
    return myList; 
}

This would be called as:

这将称为:

MyObject o = new MyObject();
List<MyObject> myList = SomeClass.someMethod(o);

IMHO the syntax for methods is kinda goofy, but there you have it. The relavent Oracle tutorial is here: http://download.oracle.com/javase/tutorial/extra/generics/methods.html

方法的语法有点傻,但是你已经知道了。relavent Oracle教程在这里:http://download.oracle.com/javase/tutorial/extra/generics/methods.html。

#1


11  

In <E> List<E>, the first <E> denotes that E is a type parameter. If you hadn't specified it, then Java would think the E in E value referred to an actual class named E, and ask you to import it. See generic methods.

列表 中,第一个 表示E是一个类型参数。如果您没有指定它,那么Java会认为E的E值指向一个名为E的实际类,并要求您导入它。看到泛型方法。

#2


13  

You use the <E> to typify the method you are defining.

您使用 来类型化所定义的方法。

The most common example of generics is to have a typified class like this:

泛型最常见的例子是有一个类型化的类:

public class SomeClass<E> {
    ...
}

Then, when you are creating a new object of that class you define the type directly like this:

然后,当您创建该类的新对象时,您直接定义类型如下:

new SomeClass<String>();

That way any method in that class that refers to , will treat as a String, for that instance.

这样,类中引用的任何方法,都将被视为字符串。

Now consider a static method (which is not bound to any particular instance of a class), in order to typify that method you have use another kind of typification which applies to methods, like this:

现在考虑一个静态方法(它不绑定到类的任何特定实例),为了对该方法进行类型化,您使用了另一种类型的类型化,这种类型化适用于方法,如下所示:

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

You use the <E> before the return type to say "this particular method will consider some E when it executes". What <E> will be is decided when you invoke the method:

在返回类型之前使用 表示“这个特定的方法在执行时将考虑某些E”。当您调用该方法时,将决定 的值:

nCopies(3, "a");

In this example <E> will be a String, so the return type will be a List<String>.

在本例中, 将是一个字符串,因此返回类型将是一个列表

Finally, you can even mix them both:

最后,你甚至可以将两者混合:

public class SomeClass<E> {
    public <F> void doSomething(E e, F f){
        ...
    }
}

In this case, if you have an instance of SomeClass, the E in the doSomething method will always be String (for that instance), but the F can be anything you want it to be.

在本例中,如果您有一个SomeClass的实例,doSomething方法中的E将始终是String(对于该实例),但是F可以是您希望的任何值。

#3


3  

The <E> is required to tell the compiler that you intend to use E as a type parameter, the same way you do when you make a generic class (e.g. public interface List<E>).

需要 告诉编译器您打算使用E作为类型参数,就像您创建泛型类时所做的那样(例如,public interface List )。

Since there is no rule (only conventions) on interface or class names being more than one character, and no rule (only conventions) that type parameter names have to be one character, the compiler would not know you intended it to be a type parameter rather than a concrete class name.

由于接口或类名上没有规则(只有约定)是多于一个字符,而且类型参数名称必须是一个字符的规则(只有约定),因此编译器不会知道您希望它是一个类型参数,而不是一个具体的类名。

Edit

A lot of people have been saying this is directly related to static methods. That is not true. You can have an instance method that is generic on its own type parameters as well (though typically, the type parameters will be related to the class type parameters).

很多人都说这与静态方法直接相关。这是不正确的。您还可以拥有一个实例方法,该方法在自己的类型参数上也是通用的(尽管通常,类型参数将与类类型参数相关)。

Here's an example of where you could have this:

这里有一个例子可以说明这一点:

public class MyList<E> {

    public <N super E> MyList<N> createCopy() {
        //...
    }
}

This method would allow you to create a copy of the list but not restrain you to using the same type as the list you have, but rather allowing you to use a supertype. For example:

该方法允许您创建列表的副本,但不限制您使用与列表相同的类型,而是允许您使用超类型。例如:

MyList<Integer> integers = createList(1, 2, 5);
MyList<Number> numbers = integers.createCopy();

#4


2  

List<E> is the return type for the method whereas <E> is the type being passed in (This is inferred by the compiler from what is being passed as E value).

List 是方法的返回类型,而 是被传入的类型(编译器从以E值传递的内容推断出这一点)。

static <E> List<E> someMethod(E myObject)
{
    E objectOfMyType = myObject;
    List<E> myList = new ArrayList<E>();
    ...
    return myList; 
}

This would be called as:

这将称为:

MyObject o = new MyObject();
List<MyObject> myList = SomeClass.someMethod(o);

IMHO the syntax for methods is kinda goofy, but there you have it. The relavent Oracle tutorial is here: http://download.oracle.com/javase/tutorial/extra/generics/methods.html

方法的语法有点傻,但是你已经知道了。relavent Oracle教程在这里:http://download.oracle.com/javase/tutorial/extra/generics/methods.html。