概念
允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)
从JDK1.5以后,Java引入了参数化类型(Parameterized type)的概念,允许我们在创建集合时再指定集合元素的类型,正如:List
JDK1.5改写了集合框架中的全部接口和类,为这些接口、类增加了泛型支持, 从而可以在声明集合变量、创建集合对象时传入类型实参。
Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生 ClassCastException异常。同时,代码更加简洁、健壮。
泛型类
interface List
常用T表示,是Type的缩写。
修饰符 class 类名称<泛型标识> {
修饰符 泛型标识 // 成员变量类型
修饰符 构造函数(泛型标识 参数)
}
- 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如:
泛型类的构造器如下
public GenericClass(){}
而下面是错误的:
public GenericClass<E>(){}
实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致。
- 泛型不同的引用不能相互赋值。 >尽管在编译时ArrayList
和ArrayList 是两种类型,但是,在运行时只有 一个ArrayList被加载到JVM中。 - 泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价 于Object。经验:泛型要使用一路都用。要不用,一路都不要用。
- 如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。
- jdk1.7,泛型的简化操作:ArrayList
flist = new ArrayList<>(); - 泛型的指定中不能使用基本数据类型,可以使用包装类替换
- 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态 属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法 中不能使用类的泛型。
- 异常类不能是泛型的
- 不能使用new E[]。但是可以:E[] elements = (E[])new Object[capacity]; 参考:ArrayList源码中声明:Object[] elementData,而非泛型参数类型数组。
12.父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型。
按照约定,类型参数名称命名为单个大写字母,以便可以在使用普通类或接口名称时能够容易地区分类型参数。以下是常用的类型参数名称列表 -
- E - ELement(元素),主要由Java集合(Collections)框架使用。
- K - Key(键),主要用于表示映射中的键的参数类型。
- V - Value(值),主要用于表示映射中的值的参数类型。
- N - Number(数字),主要用于表示数字。
- T - Type(类型),主要用于表示第一类通用型参数。
- S - 类型,主要用于表示第二类通用类型参数。
- U - 类型,主要用于表示第三类通用类型参数。
- V - 类型,主要用于表示第四个通用类型参数。
集合
只有指定类型才可以添加到集合中:类型安全 读取出来的对象不需要强转:便捷。
class ArrayList<E>{
public boolean add(E e){ }
public E get(int index){ }
....
}
ArrayList集合:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(3);
list.add(5);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
HashMap
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("one",1);
map.put("two",2);
map.put("three",3);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> next = iterator.next();
System.out.println(next.getKey()+":"+next.getValue());
}
泛型方法
定义
修饰符 <泛型标识> 返回值类型 方法名(参数列表(使用泛型)) {
方法体
}
eg
public class GenericsFunc {
public static <T> String foo(T t) {
return "hello "+t;
}
public static void main(String[] args) {
System.out.println(foo("world"));
System.out.println(foo(123));
System.out.println(foo(false));
}
}
这里
泛型接口
与泛型类的用法基本相同,常用于数据类型的生产工厂接口中
定义泛型接口
继承泛型接口
创建测试函数
通配符
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用问号?,?表示未知通配符,即表示任意的数据类型
注意:此时只能接受数据,不能往该集合中存储数据。
1.:List<?> ,Map<?,?> List<?>是List