语法:
interface 接口<T>{}
class 类<K,V>{};
其中,T,K,V不代值,而是表示类型。
任意字母都可以,常用T 表示Type;
注意事项:
泛型<E> 这个E表示泛型指定的数据类型:
1.必须是引用数据类型,不能是基本数据类型。
List<Integer> = new ArrayList<Integer>();
List<int> = new ArrayList<int>();
2.可以传入T指定类型的本类型/子类型,或者是可以满足自动类型转换的数据类型
既:不能传入超过E类型实现范围的类型。
3.实际开发中我们一般推荐简写
原因是编译器会进行类型推断。
但是注意如果前后都写,要注意前后一致。
List<Integer> list = new ArrayList<Integer>();
List<Integer> list = new ArrayList<>();
List<Object> list = new ArrayList<Integer>();
4.在不规定泛型得时候,默认是Object类型
List = new ArrayList();
以ArrayList为例,源码中说到:E是列表中元素的类型。
Type parameters:
<E> – the type of elements in this list
而这个E在源码中写到:
type parameter E extends Object
由上可知,当你不进行规定类型时,E的类型是Object。
但是注意 这个并不是代表ArrayList底层中维护的Object[]变成了你指定类型的数组,底层仍然维护的是一个Object[],只是里面存放的数据类型是你使用E指定的数据类型。
参考ArrayList的add()方法在添加数据时如果我们指定了数据类型,那么这个被添加的数据,因为泛型的存在,传入Object[]中类型就已经不再是Object类型。这也是为什么迭代时候不需要再进行向下转型的原因。因为在添加时,数据类型已经是我们使用泛型指定的类型了。反之,E默认为Object类型,迭代需要转型。
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}