和的区别是什么?

时间:2022-09-01 17:19:21

What is the difference between this method declaration:

这个方法声明的区别是什么?

public static <E extends Number> List<E> process(List<E> nums){

and

 public static List<Number> process(List<Number> nums){

Where would you use the former?

你会在哪里使用前者?

2 个解决方案

#1


46  

The first allows process of a List<Integer>, a List<Double>, etc. The second doesn't.

第一个允许处理列表 、列表 等。第二个不允许。

Generics in Java are invariant. They're not covariant like arrays.

Java中的泛型是不变量。它们不像数组那样是协变的。

That is, in Java, Double[] is a subtype of Number[], but a List<Double> is NOT a subtype of List<Number>. A List<Double>, however, is a List<? extends Number>.

也就是说,在Java中,Double[]是Number[]的子类型,但是List 不是List 的子类型。但是,List 是List 。

There are good reasons for generics being invariant, but that's also why the extends and super type are often necessary for subtyping flexibility.

泛型具有不变性有很好的理由,但这也是为什么扩展和超类型对于子类型灵活性通常是必要的。

See also

  • Java Tutorials/Generics/Subtyping
    • Explains why generics invariance is a good thing
    • 解释为什么泛型不变性是一件好事
  • Java教程/泛型/子类型化解释了为什么泛型不变性是一件好事
  • More fun with wildcards
    • Explains some uses of super and extends for bounded wildcards
    • 解释超级和有界通配符扩展的一些用法
  • 通配符的更多乐趣解释了super的一些用法,并扩展了有界通配符
  • Java Generics: What is PECS?
    • This discusses the "Producer extends Consumer super" principle
    • 论述了“生产者延伸消费者超级”原则
    • Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
    • 有效的Java第二版,第28项:使用有界通配符来增加API的灵活性
  • Java泛型:什么是PECS?本文讨论了“生产者扩展消费者超级”原则有效的Java第二版,第28项:使用有界通配符来增加API的灵活性

#2


11  

The latter method (the one without <E extends Number>) will only accept a parameter of exactly type List<Number> and will it always return a List<Number>. For example, it will not accept List<Integer>.

后一种方法(没有 )只会接受一个完全类型列表的参数 ,并且它总是返回一个列表 。例如,它不会接受List 的扩展名>

The former method (the one with <E extends Number>) is a generic method, meaning it can accept different types of Lists and it will return the same type of List, as long as the Lists are lists of something that extends Number, e.g. List<Integer>.

前一种方法(具有 的方法)是一种通用方法,这意味着它可以接受不同类型的列表,并且它将返回相同类型的列表,只要列表是扩展数字的列表,例如List 扩展号>

Example:

例子:

import java.util.ArrayList;
import java.util.List;

public class ProcessGenerics {

    List<Number>  listNumber  = new ArrayList<Number>();
    List<Integer> listInteger = new ArrayList<Integer>();
    List<Double>  listDouble  = new ArrayList<Double>();


    public static
        List<Number> processWithoutExtends(List<Number> nums){ return nums; }

    List<Number>  resultN = processWithoutExtends(listNumber);  // OK
  //List<Integer> resultI = processWithoutExtends(listInteger); // compile-error - method not applicable
  //List<Double>  resultD = processWithoutExtends(listDouble);  // compile-error - method not applicable


    public static <E extends Number>
        List<E> processWithExtends(List<E> nums){ return nums; }

    List<Number>  resultN2 = processWithExtends(listNumber);  // OK
    List<Integer> resultI2 = processWithExtends(listInteger); // OK
    List<Double>  resultD2 = processWithExtends(listDouble);  // OK

}

See a similar explanation in the Wildcards chapter in the Generics Lesson in the Java Tutorials:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html

在Java教程的泛型课程中可以看到类似的解释:http://java.sun.com/docs/books/tutorial/java/generics/subtyp.html

See also How to cast a list of inheriting objects to a collection of objects in Java? Both questions are really about generics and subtypes, e.g. whether List<Integer> is a subtype of List<Number> (it's not!!!).

请参见如何将继承对象的列表强制转换为Java中的对象集合?这两个问题都是关于泛型和子类型的,例如List 是否是List 的子类型(不是!!)

#1


46  

The first allows process of a List<Integer>, a List<Double>, etc. The second doesn't.

第一个允许处理列表 、列表 等。第二个不允许。

Generics in Java are invariant. They're not covariant like arrays.

Java中的泛型是不变量。它们不像数组那样是协变的。

That is, in Java, Double[] is a subtype of Number[], but a List<Double> is NOT a subtype of List<Number>. A List<Double>, however, is a List<? extends Number>.

也就是说,在Java中,Double[]是Number[]的子类型,但是List 不是List 的子类型。但是,List 是List 。

There are good reasons for generics being invariant, but that's also why the extends and super type are often necessary for subtyping flexibility.

泛型具有不变性有很好的理由,但这也是为什么扩展和超类型对于子类型灵活性通常是必要的。

See also

  • Java Tutorials/Generics/Subtyping
    • Explains why generics invariance is a good thing
    • 解释为什么泛型不变性是一件好事
  • Java教程/泛型/子类型化解释了为什么泛型不变性是一件好事
  • More fun with wildcards
    • Explains some uses of super and extends for bounded wildcards
    • 解释超级和有界通配符扩展的一些用法
  • 通配符的更多乐趣解释了super的一些用法,并扩展了有界通配符
  • Java Generics: What is PECS?
    • This discusses the "Producer extends Consumer super" principle
    • 论述了“生产者延伸消费者超级”原则
    • Effective Java 2nd Edition, Item 28: Use bounded wildcards to increase API flexibility
    • 有效的Java第二版,第28项:使用有界通配符来增加API的灵活性
  • Java泛型:什么是PECS?本文讨论了“生产者扩展消费者超级”原则有效的Java第二版,第28项:使用有界通配符来增加API的灵活性

#2


11  

The latter method (the one without <E extends Number>) will only accept a parameter of exactly type List<Number> and will it always return a List<Number>. For example, it will not accept List<Integer>.

后一种方法(没有 )只会接受一个完全类型列表的参数 ,并且它总是返回一个列表 。例如,它不会接受List 的扩展名>

The former method (the one with <E extends Number>) is a generic method, meaning it can accept different types of Lists and it will return the same type of List, as long as the Lists are lists of something that extends Number, e.g. List<Integer>.

前一种方法(具有 的方法)是一种通用方法,这意味着它可以接受不同类型的列表,并且它将返回相同类型的列表,只要列表是扩展数字的列表,例如List 扩展号>

Example:

例子:

import java.util.ArrayList;
import java.util.List;

public class ProcessGenerics {

    List<Number>  listNumber  = new ArrayList<Number>();
    List<Integer> listInteger = new ArrayList<Integer>();
    List<Double>  listDouble  = new ArrayList<Double>();


    public static
        List<Number> processWithoutExtends(List<Number> nums){ return nums; }

    List<Number>  resultN = processWithoutExtends(listNumber);  // OK
  //List<Integer> resultI = processWithoutExtends(listInteger); // compile-error - method not applicable
  //List<Double>  resultD = processWithoutExtends(listDouble);  // compile-error - method not applicable


    public static <E extends Number>
        List<E> processWithExtends(List<E> nums){ return nums; }

    List<Number>  resultN2 = processWithExtends(listNumber);  // OK
    List<Integer> resultI2 = processWithExtends(listInteger); // OK
    List<Double>  resultD2 = processWithExtends(listDouble);  // OK

}

See a similar explanation in the Wildcards chapter in the Generics Lesson in the Java Tutorials:
http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html

在Java教程的泛型课程中可以看到类似的解释:http://java.sun.com/docs/books/tutorial/java/generics/subtyp.html

See also How to cast a list of inheriting objects to a collection of objects in Java? Both questions are really about generics and subtypes, e.g. whether List<Integer> is a subtype of List<Number> (it's not!!!).

请参见如何将继承对象的列表强制转换为Java中的对象集合?这两个问题都是关于泛型和子类型的,例如List 是否是List 的子类型(不是!!)