0

如果我有ArrayList<Shape>,我的印象是在该列表中我可以存储类Shape的对象或作为Shape.

我还看到了很多类似ArrayList<T>or的符号ArrayList<?>。这些是一样的吗?T可以存储超类及其所有子类,而只是?一个占位符?

基本上,类似的东西与你只有一个字母的地方有什么ArrayList<CLASSNAME>不同。ArrayList<T>

4

3 回答 3

1

首先,区别不在于它是否像您想象的那样是一个字母。它是否T是通用参数的名称。如果您声明如下方法:

public <T> void method()

相对于:

public void method()

或类似的课程:

public class Whatever<T>

相对于:

public class Whatever

thenT是一个通用参数。然后,您可以在任何您想要的地方使用它,就好像它是一个真实的类名一样,并且在编译时T将替换一个真实的类名。T但这不是最好的描述,所以假设T类型是传递给类型 T 的参数的任何类型。因此,在任何给定时刻,T都有一个真正的类名值。

ArrayList<T>因此,和之间的区别在于ArrayList<Shape>ArrayList<T>持有 type 的对象T,而ArrayList<Shape>持有 type 的对象Shape。诀窍在于T将任何类型传递给 type 的参数T,因此它可以变化。

免责声明:类型T实际上不会随着时间而改变。在大多数情况下,编译器会将其替换为Object. 但是,编译器擅长隐藏这一点,考虑T更改是个好主意。

于 2013-09-29T23:19:14.120 回答
1

首先,ArrayList 不能像这样引用 Shape 的任何子类:

ArrayList<Shape> blah = new ArrayList<Square>

但是你可以这样做:

ArrayList<? extends Shape> blah = new ArrayList<Square>

多态性不适用于类型参数。它仅适用于以下对象:

Collection<String> blah = new ArrayList<String>

但是你必须了解使用T的目的。T用于为类和方法声明类型参数。

这样当你声明一个带有参数 T 的类时:

 public class ArrayList <T>

当类被实例化为对象时,T 充当占位符。

所以在这种情况下:

 ArrayList<String>

您在 ArrayList 类中将 T 替换为 String 。

顺便说一句,您不应该使用 T 作为参数的类型。因为 T 没有真正定义,它只是一个占位符。

于 2013-09-29T23:20:34.717 回答
0

ArrayList<T>在声明类型/类以及ArrayList<String>创建 ArrayList 实例并将其与类型参数 String 关联时表达。

例如:

// class declaration
public class ArrayList<T> extends ... implements ... {
  ...

// Creating an arraylist of string
ArrayList<String> stringArray = new ArrayList<String>

您可以将泛型视为类型变量。因此,不要创建一个仅适用于 String 的类:

public class MyArray {

  String get(int index) { ... }

}

您可以创建一个适用于任意类型的数组类

public class MyArray<T> {

  T get(int index) { .. }

}
于 2013-09-29T23:19:33.853 回答