List 在java泛型中的含义是什么?

时间:2021-08-27 15:51:18

What does List<?> mean, does it mean simply a list of objects of unspecified type?

List 是什么意思,它是否只是一个未指定类型的对象列表?

Googling for the string <?> returns nothing useful (:

谷歌搜索字符串 返回没有任何用处(:

8 个解决方案

#1


29  

The keyword you need to get more information is Wildcards

获取更多信息所需的关键字是通配符

#2


36  

As Tom said, the ?, or unbounded wildcard, means that the type of the object is not specified. It could be unknown, could be meant for multiple possible values or might be just plain irrelevant. Your example, List<?>, is pronounced "List of unknown." It's convenient because it's flexible, but there are also some pitfalls because you can't shove random objects in and pull them out of groups of unknown with total impunity.

正如Tom所说,?或*的通配符意味着没有指定对象的类型。它可能是未知的,可能意味着多个可能的值,或者可能只是简单无关紧要。你的例子List 发音为“List of unknown”。它很方便,因为它很灵活,但也存在一些陷阱,因为你无法将随机物品推入并将它们从未知组中拉出来而完全不受惩罚。

Resources:

  • Wildcards are discussed here in the Java tutorial.
  • Java教程中讨论了通配符。

  • There's a good -- if verbose -- tutorial on generics in general by Angelika Langer available here.
  • 这里有一个很好的 - 如果详细的 - 关于仿制药的教程,由Angelika Langer提供。

  • And there's another good overview here (PDF) by Gilad Bracha; check out pages 5-7.
  • Gilad Bracha还有另一个很好的概述(PDF);请查看第5-7页。

  • Finally, if you can get your hands on Effective Java by Josh Bloch, it's got a great section on generics and the cases in which you can, can't, should and shouldn't use wildcards (chapter 5, pages 109-146 in the second edition).
  • 最后,如果你可以通过Josh Bloch开始使用Effective Java,那么它就有很多关于泛型的部分以及你可以,不能,应该和不应该使用通配符的情况(第5章,第109-146页)第二版)。

Incidentally, your Google search failed because Google doesn't truck with special characters:

顺便提一下,您的Google搜索失败了,因为Google没有使用特殊字符:

With some exceptions, punctuation is ignored (that is, you can't search for @#$%^&*()=+[]\ and other special characters).

除了一些例外,标点符号被忽略(也就是说,你不能搜索@#$%^&*()= + [] \和其他特殊字符)。

-Google help page

- 谷歌帮助页面

(EDIT: I must have been really tired when I wrote this last night. Cleaned up formatting/added a little info.)

(编辑:我昨晚写这篇文章时一定很累。清理格式化/添加了一些信息。)

#3


4  

Sounds like you should look for some documentation on Java generics.

听起来你应该寻找一些关于Java泛型的文档。

The List<?> means that it is an object based on a currently unspecified type. That specification is made when the class is instantiated.

List 表示它是基于当前未指定类型的对象。在实例化类时会生成该规范。

For example:

List<String> listOfStrings = new ArrayList<String>();

is a list of String objects.

是String对象的列表。

#4


4  

To answer this question I need to explain Unbounded Wildcards and Bounded Wildcards.
The content of this post has been assembled from java documentation.

要回答这个问题,我需要解释Unbounded Wildcards和Bounded Wildcards。这篇文章的内容是从java文档中汇编而来的。

1. Unbounded Wildcards

The unbounded wildcard type is specified using the wildcard character (?), for example, List<?>. This is called a list of unknown type. There are two scenarios where an unbounded wildcard is a useful approach:

使用通配符(?)指定*通配符类型,例如List 。这称为未知类型的列表。有两种情况,*通配符是一种有用的方法:

  • If you are writing a method that can be implemented using functionality provided in the Object class.

    如果您正在编写可以使用Object类中提供的功能实现的方法。

  • When the code is using methods in the generic class that don't depend on the type parameter. For example, List.size or List.clear. In fact, Class<?> is so often used because most of the methods in Class<T> do not depend on T.

    当代码使用泛型类中不依赖于类型参数的方法时。例如,List.size或List.clear。事实上,经常使用Class ,因为Class 中的大多数方法都不依赖于T.

2. Bounded Wildcards

Consider a simple drawing application that can draw shapes such as rectangles and circles. To represent these shapes within the program, you could define a class hierarchy such as this:

考虑一个简单的绘图应用程序,可以绘制矩形和圆形等形状。要在程序中表示这些形状,您可以定义类层次结构,例如:

public abstract class Shape {
    public abstract void draw(Canvas c);
}

public class Circle extends Shape {
    private int x, y, radius;
    public void draw(Canvas c) {
        ...
    }
}

public class Rectangle extends Shape {
    private int x, y, width, height;
    public void draw(Canvas c) {
        ...
    }
}

These classes can be drawn on a canvas:

这些类可以在画布上绘制:

public class Canvas {
    public void draw(Shape s) {
        s.draw(this);
   }
}

Any drawing will typically contain a number of shapes. Assuming that they are represented as a list, it would be convenient to have a method in Canvas that draws them all:

任何绘图通常都包含许多形状。假设它们被表示为一个列表,在Canvas中有一个方法可以方便地绘制它们:

public void drawAll(List<Shape> shapes) {
    for (Shape s: shapes) {
        s.draw(this);
   }
}

Now, the type rules say that drawAll() can only be called on lists of exactly Shape: it cannot, for instance, be called on a List<Circle>. That is unfortunate, since all the method does is read shapes from the list, so it could just as well be called on a List<Circle>. What we really want is for the method to accept a list of any kind of shape: public void drawAll(List shapes) { ... } There is a small but very important difference here: we have replaced the type List<Shape> with List<? extends Shape>. Now drawAll() will accept lists of any subclass of Shape, so we can now call it on a List<Circle> if we want.

现在,类型规则说drawAll()只能在精确Shape的列表上调用:例如,它不能在List 上调用。这很不幸,因为所有方法都是从列表中读取形状,所以它也可以在List 上调用。我们真正想要的是接受任何形状列表的方法:public void drawAll(List shapes){...}这里有一个小但非常重要的区别:我们已经用类型List 替换了名单 。现在drawAll()将接受Shape的任何子类的列表,因此我们现在可以在List 上调用它,如果需要的话。

List<? extends Shape> is an example of a bounded wildcard. The ? stands for an unknown type, however, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.

名单 是有界通配符的示例。的?代表一种未知类型,但是,在这种情况下,我们知道这种未知类型实际上是Shape的子类型。 (注意:它可能是Shape本身,或者是某些子类;它不需要字面上扩展Shape。)我们说Shape是通配符的上限。

Similarly, the syntax ? super T, which is a bounded wildcard, denotes an unknown type that is a supertype of T. A ArrayedHeap280<? super Integer>, for example, includes ArrayedHeap280<Integer>, ArrayedHeap280<Number>, and ArrayedHeap280<Object>. As you can see in the java documentation for Integer class, Integer is a subclass of Number that in turn is a subclass of Object.

同样,语法? super T是一个有界通配符,表示一个未知类型,它是T的超类型.AlledHeap280 包括ArrayedHeap280 ,ArrayedHeap280 和ArrayedHeap280 。正如你在Integer类的java文档中看到的那样,Integer是Number的子类,而Number又是Object的子类。

#5


3  

List is an interface you can implement yourself and also implemented by some of the Java collections, like Vector.

List是一个你可以自己实现的接口,也可以通过一些Java集合实现,比如Vector。

You can provide compile-time typing information using the angled brackets. The most generic type would be Object, which would be List<Object>. The <?> you see is indicating a List of some subclass of Object or an Object. This is like saying List<? extends Object>, or List<? extends Foo>, where the List contains objects of some subclass of Foo or objects of Foo itself.

您可以使用带角度的括号提供编译时键入信息。最通用的类​​型是Object,它是List 。您看到的 表示Object或Object的某个子类的List。这就像说List ,或List ,其中List包含Foo的某些子类的对象或Foo本身的对象。

You can't instantiate a List; it's an interface, not an implementation.

您无法实例化List;它是一个接口,而不是一个实现。

#6


2  

List<?> stands for List<? extends Object> so in Collection<E> you will find containsAll(Collection<?> c) which allows you to write

List 代表List 所以在Collection 中你会发现containsAll(Collection c)允许你编写

List<Object> objs = Arrays.<Object>asList("one",2,3.14,4);
List<Integer> ints = Arrays.asList(2,4);
assert objs.containsAll(ints);//true

#7


0  

When you take an element out of a Collection, you must cast it to the type of element that is stored in the collection. Besides being inconvenient, this is unsafe. The compiler does not check that your cast is the same as the collection's type, so the cast can fail at run time.

从集合中取出元素时,必须将其强制转换为集合中存储的元素类型。除了不方便之外,这是不安全的。编译器不会检查您的强制转换是否与集合的类型相同,因此强制转换可能会在运行时失败。

Generics provides a way for you to communicate the type of a collection to the compiler, so that it can be checked. Once the compiler knows the element type of the collection, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection.

泛型提供了一种将集合类型传递给编译器的方法,以便可以检查它。一旦编译器知道集合的元素类型,编译器就可以检查您是否一直使用了集合,并且可以对从集合中取出的值插入正确的强制转换。

chk dis pdf

chk dis pdf

#8


-1  

You are probably looking at the template based List class. You can create a list of strings by List<String> myList = new MyList<String>(); as an example. Check the documentation for all the types it supports. It should support any object type, but if there is a sort functionality you have to supply some compare functions.

您可能正在查看基于模板的List类。您可以通过List myList = new MyList ()创建字符串列表;举个例子。检查文档中是否支持所有类型。它应该支持任何对象类型,但如果有排序功能,则必须提供一些比较功能。

Note that in the example above MyList is a concrete class that implements the List interface in Java. It can be ArrayList.

请注意,在上面的示例中,MyList是一个在Java中实现List接口的具体类。它可以是ArrayList。

EDIT: I assumed List as a concrete class by mistake. Fixed the error above. Thanks Jon.

编辑:我错误地将List列为具体类。修正了上面的错误。谢谢乔恩。

#1


29  

The keyword you need to get more information is Wildcards

获取更多信息所需的关键字是通配符

#2


36  

As Tom said, the ?, or unbounded wildcard, means that the type of the object is not specified. It could be unknown, could be meant for multiple possible values or might be just plain irrelevant. Your example, List<?>, is pronounced "List of unknown." It's convenient because it's flexible, but there are also some pitfalls because you can't shove random objects in and pull them out of groups of unknown with total impunity.

正如Tom所说,?或*的通配符意味着没有指定对象的类型。它可能是未知的,可能意味着多个可能的值,或者可能只是简单无关紧要。你的例子List 发音为“List of unknown”。它很方便,因为它很灵活,但也存在一些陷阱,因为你无法将随机物品推入并将它们从未知组中拉出来而完全不受惩罚。

Resources:

  • Wildcards are discussed here in the Java tutorial.
  • Java教程中讨论了通配符。

  • There's a good -- if verbose -- tutorial on generics in general by Angelika Langer available here.
  • 这里有一个很好的 - 如果详细的 - 关于仿制药的教程,由Angelika Langer提供。

  • And there's another good overview here (PDF) by Gilad Bracha; check out pages 5-7.
  • Gilad Bracha还有另一个很好的概述(PDF);请查看第5-7页。

  • Finally, if you can get your hands on Effective Java by Josh Bloch, it's got a great section on generics and the cases in which you can, can't, should and shouldn't use wildcards (chapter 5, pages 109-146 in the second edition).
  • 最后,如果你可以通过Josh Bloch开始使用Effective Java,那么它就有很多关于泛型的部分以及你可以,不能,应该和不应该使用通配符的情况(第5章,第109-146页)第二版)。

Incidentally, your Google search failed because Google doesn't truck with special characters:

顺便提一下,您的Google搜索失败了,因为Google没有使用特殊字符:

With some exceptions, punctuation is ignored (that is, you can't search for @#$%^&*()=+[]\ and other special characters).

除了一些例外,标点符号被忽略(也就是说,你不能搜索@#$%^&*()= + [] \和其他特殊字符)。

-Google help page

- 谷歌帮助页面

(EDIT: I must have been really tired when I wrote this last night. Cleaned up formatting/added a little info.)

(编辑:我昨晚写这篇文章时一定很累。清理格式化/添加了一些信息。)

#3


4  

Sounds like you should look for some documentation on Java generics.

听起来你应该寻找一些关于Java泛型的文档。

The List<?> means that it is an object based on a currently unspecified type. That specification is made when the class is instantiated.

List 表示它是基于当前未指定类型的对象。在实例化类时会生成该规范。

For example:

List<String> listOfStrings = new ArrayList<String>();

is a list of String objects.

是String对象的列表。

#4


4  

To answer this question I need to explain Unbounded Wildcards and Bounded Wildcards.
The content of this post has been assembled from java documentation.

要回答这个问题,我需要解释Unbounded Wildcards和Bounded Wildcards。这篇文章的内容是从java文档中汇编而来的。

1. Unbounded Wildcards

The unbounded wildcard type is specified using the wildcard character (?), for example, List<?>. This is called a list of unknown type. There are two scenarios where an unbounded wildcard is a useful approach:

使用通配符(?)指定*通配符类型,例如List 。这称为未知类型的列表。有两种情况,*通配符是一种有用的方法:

  • If you are writing a method that can be implemented using functionality provided in the Object class.

    如果您正在编写可以使用Object类中提供的功能实现的方法。

  • When the code is using methods in the generic class that don't depend on the type parameter. For example, List.size or List.clear. In fact, Class<?> is so often used because most of the methods in Class<T> do not depend on T.

    当代码使用泛型类中不依赖于类型参数的方法时。例如,List.size或List.clear。事实上,经常使用Class ,因为Class 中的大多数方法都不依赖于T.

2. Bounded Wildcards

Consider a simple drawing application that can draw shapes such as rectangles and circles. To represent these shapes within the program, you could define a class hierarchy such as this:

考虑一个简单的绘图应用程序,可以绘制矩形和圆形等形状。要在程序中表示这些形状,您可以定义类层次结构,例如:

public abstract class Shape {
    public abstract void draw(Canvas c);
}

public class Circle extends Shape {
    private int x, y, radius;
    public void draw(Canvas c) {
        ...
    }
}

public class Rectangle extends Shape {
    private int x, y, width, height;
    public void draw(Canvas c) {
        ...
    }
}

These classes can be drawn on a canvas:

这些类可以在画布上绘制:

public class Canvas {
    public void draw(Shape s) {
        s.draw(this);
   }
}

Any drawing will typically contain a number of shapes. Assuming that they are represented as a list, it would be convenient to have a method in Canvas that draws them all:

任何绘图通常都包含许多形状。假设它们被表示为一个列表,在Canvas中有一个方法可以方便地绘制它们:

public void drawAll(List<Shape> shapes) {
    for (Shape s: shapes) {
        s.draw(this);
   }
}

Now, the type rules say that drawAll() can only be called on lists of exactly Shape: it cannot, for instance, be called on a List<Circle>. That is unfortunate, since all the method does is read shapes from the list, so it could just as well be called on a List<Circle>. What we really want is for the method to accept a list of any kind of shape: public void drawAll(List shapes) { ... } There is a small but very important difference here: we have replaced the type List<Shape> with List<? extends Shape>. Now drawAll() will accept lists of any subclass of Shape, so we can now call it on a List<Circle> if we want.

现在,类型规则说drawAll()只能在精确Shape的列表上调用:例如,它不能在List 上调用。这很不幸,因为所有方法都是从列表中读取形状,所以它也可以在List 上调用。我们真正想要的是接受任何形状列表的方法:public void drawAll(List shapes){...}这里有一个小但非常重要的区别:我们已经用类型List 替换了名单 。现在drawAll()将接受Shape的任何子类的列表,因此我们现在可以在List 上调用它,如果需要的话。

List<? extends Shape> is an example of a bounded wildcard. The ? stands for an unknown type, however, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.

名单 是有界通配符的示例。的?代表一种未知类型,但是,在这种情况下,我们知道这种未知类型实际上是Shape的子类型。 (注意:它可能是Shape本身,或者是某些子类;它不需要字面上扩展Shape。)我们说Shape是通配符的上限。

Similarly, the syntax ? super T, which is a bounded wildcard, denotes an unknown type that is a supertype of T. A ArrayedHeap280<? super Integer>, for example, includes ArrayedHeap280<Integer>, ArrayedHeap280<Number>, and ArrayedHeap280<Object>. As you can see in the java documentation for Integer class, Integer is a subclass of Number that in turn is a subclass of Object.

同样,语法? super T是一个有界通配符,表示一个未知类型,它是T的超类型.AlledHeap280 包括ArrayedHeap280 ,ArrayedHeap280 和ArrayedHeap280 。正如你在Integer类的java文档中看到的那样,Integer是Number的子类,而Number又是Object的子类。

#5


3  

List is an interface you can implement yourself and also implemented by some of the Java collections, like Vector.

List是一个你可以自己实现的接口,也可以通过一些Java集合实现,比如Vector。

You can provide compile-time typing information using the angled brackets. The most generic type would be Object, which would be List<Object>. The <?> you see is indicating a List of some subclass of Object or an Object. This is like saying List<? extends Object>, or List<? extends Foo>, where the List contains objects of some subclass of Foo or objects of Foo itself.

您可以使用带角度的括号提供编译时键入信息。最通用的类​​型是Object,它是List 。您看到的 表示Object或Object的某个子类的List。这就像说List ,或List ,其中List包含Foo的某些子类的对象或Foo本身的对象。

You can't instantiate a List; it's an interface, not an implementation.

您无法实例化List;它是一个接口,而不是一个实现。

#6


2  

List<?> stands for List<? extends Object> so in Collection<E> you will find containsAll(Collection<?> c) which allows you to write

List 代表List 所以在Collection 中你会发现containsAll(Collection c)允许你编写

List<Object> objs = Arrays.<Object>asList("one",2,3.14,4);
List<Integer> ints = Arrays.asList(2,4);
assert objs.containsAll(ints);//true

#7


0  

When you take an element out of a Collection, you must cast it to the type of element that is stored in the collection. Besides being inconvenient, this is unsafe. The compiler does not check that your cast is the same as the collection's type, so the cast can fail at run time.

从集合中取出元素时,必须将其强制转换为集合中存储的元素类型。除了不方便之外,这是不安全的。编译器不会检查您的强制转换是否与集合的类型相同,因此强制转换可能会在运行时失败。

Generics provides a way for you to communicate the type of a collection to the compiler, so that it can be checked. Once the compiler knows the element type of the collection, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection.

泛型提供了一种将集合类型传递给编译器的方法,以便可以检查它。一旦编译器知道集合的元素类型,编译器就可以检查您是否一直使用了集合,并且可以对从集合中取出的值插入正确的强制转换。

chk dis pdf

chk dis pdf

#8


-1  

You are probably looking at the template based List class. You can create a list of strings by List<String> myList = new MyList<String>(); as an example. Check the documentation for all the types it supports. It should support any object type, but if there is a sort functionality you have to supply some compare functions.

您可能正在查看基于模板的List类。您可以通过List myList = new MyList ()创建字符串列表;举个例子。检查文档中是否支持所有类型。它应该支持任何对象类型,但如果有排序功能,则必须提供一些比较功能。

Note that in the example above MyList is a concrete class that implements the List interface in Java. It can be ArrayList.

请注意,在上面的示例中,MyList是一个在Java中实现List接口的具体类。它可以是ArrayList。

EDIT: I assumed List as a concrete class by mistake. Fixed the error above. Thanks Jon.

编辑:我错误地将List列为具体类。修正了上面的错误。谢谢乔恩。