1为什么需要泛型?
JDK提供了ArrayList,可以看作“可变长度”的数组:
- 比数组使用方便
public class ArrayList {
private Object[] array;
public void add(Object e){...}
public void remove(int index){...}
public Object get(int index){...}
}
如果用ArrayList存储String类型:见下面代码示例
- 需要强制转型
- 不方便,易出错
public class ArrayList {
private Object[] array;
public void add(Object e) {...}
public void remove(int index) {...}
public Object get(int index) {...}
}
ArrayList list = new ArrayList();
list.add("Hello");
String first = (String) list.get(0);
list.add(new Integer(123));
//ERROR:ClassCastException:
String second = (String) list.get(1);
如果为String单独编写一种ArrayList:
- 不需要强制转型
- 编译器强制检查放入的类型
- 问题暂时解决
public class StringArrayList {
private String[] array;
public void add(String e) {...}
public void remove(int index) {...}
public String get(int index) {...}
}
StringArrayList list = new StringArrayList();
list.add("Hello");
String first = list.get(0);
//编译错误:不允许放入非String类型
list.add(new Integer(123));
然而新的问题是,还要为其他数据类型编写ArrayList:
例如:还需要为Integer单独编写一种ArrayList
public class IntegerArrayList {
private Integer[] array;
public void add(Integer e) {...}
public void remove(int index) {...}
public String get(int index) {...}
}
还需要为其他所有class单独编写一种ArrayList:
- Long
- Double
- Person
- ...
public class XyzArrayList {
private Xyz[] array;
public void add(Xyz e) {...}
public void remove(int index) {...}
public Xyz get(int index) {...}
}
但是这样的必须把Array变成一种模板:
- ArrayList<T>
- ArrayList<String>
- ArrayList<Float>
- ArrayList<Perosn>
- ArrayList<任意Class>
public class ArrayList<T> {
private T[] array;
public void add(T e) {...}
public void remove(int index) {...}
public T get(int index) {...}
}
ArrayList<String> strList = new ArrayList<String>();
ArrayList<Float> floatList = new ArrayList<Float>();
ArrayList<Person> psList = new ArrayList<Person>();
范型就是定义一种模版,例如ArrayList
-
在代码中为用到的类创建对应的ArrayList<类型>
ArrayList<String> strList = new ArrayList<String>(); -
编译器针对类型做检查
strList.add("hello");
strList.add(new Integer(123));//compile error
2泛型的继承关系
ArrayList1<T>实现了List<T>接口:
- 可以向上转型: ArrayList<String>——> List<String>
List<String> list = new ArrayList<String>();
- 不能把ArrayList<Integer>向上转型为ArrayList<Numberr>或List<Number> 。ArrayList<Integer>和ArrayList<Number>两者没有继承关系。
ArrayList<Integer> integerList = new ArrayList<Integer>();
integerList.add(new Integer(123));
ArrayList<Number> numberList = integerList;
numberList.add(new Float(12.34));
Integer n = integerList.get(1);//ClassCastException!
3代码演示
public class Main {
public static void main(String[] args) {
ArrayList<String> strList = new ArrayList<String>();
strList.add("abc");
strList.add("xyz");
String first = strList.get(0);
System.out.println(first);
}
}
4总结
- 泛型就是编写模版代码来适应任意类型
- 不必对类型进行强制转换
- 编译器将对类型进行检查
- 注意泛型的继承关系:
可以把ArrayList<Integer> 向上转型为 List<Integer>(T不能变!)
不能把ArrayList<Integer>向上转型为ArrayList<Number>