多态性与Java ArrayLists中的泛型有何不同?

时间:2013-09-29 23:01:13

标签: java generics polymorphism

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

我也看到很多关于ArrayList<T>ArrayList<?>等内容的注释。这些都是一样的吗?可以存储T超类及其所有子类,而?只是一个占位符?

基本上,ArrayList<CLASSNAME>之类的内容与{1}}的区别在于您只有一个字母。

3 个答案:

答案 0 :(得分:1)

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

public <T> void method()

而不是:

public void method()

或类似:

public class Whatever<T>

而不是:

public class Whatever

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

因此,ArrayList<T>ArrayList<Shape>之间的区别在于ArrayList<T>包含T类型的对象,而ArrayList<Shape>包含Shape类型的对象}。诀窍是T是传递给类型T的参数的任何类型,因此它可以变化。

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

答案 1 :(得分: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类中的String替换T.

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

答案 2 :(得分:0)

当您在声明类型/类时表达ArrayList<T>,在创建ArrayList实例时表达ArrayList<String>并将其与类型参数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) { .. }

}