一 泛型
泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
泛型格式:<引用数据类型>
ArrayList<Integer> list = new ArrayList<>();
在JDK5以前,没有泛型的时候,集合存储数据的方式:如果没有给集合指定类型,那么集合可以添加任意类型的元素并且将这些元素的数据类型转换为Object类。这样的话,虽然能够存储,但是由于父类无法访问子类的特有方法,通过强制转换将父类转化为子类也不方便。
泛型的好处:
(1)统一了数据类型
(2)把运行时期的问题提前到编译时期,避免了强制转换可能出现的异常,因为在编译阶段类型就能确定下来。
注意
(1)在java中,所谓的泛型实际是伪泛型,即java只是在元素传入时限制了数据类型(编译阶段),而数据传进来后仍然是将其数据类型提升为Object类;
(2)泛型中不能写基本数据类型,因为基本数据类型无法提升为Object类;
(3)指定泛型的数据类型后,传递数据时,可以传递该数据类型或者它的子类类型;
(4)如果不写泛型,默认是Object类。
二 泛型类
使用场景:当一个类中,某一个变量的数据类型不确定时,就可以定义带有泛型的类。
import java.util.Arrays;
public class MyArrayList<E> {
private Object[] list = new Object[10];
private int size;
public MyArrayList() {}
public boolean add(E e){
list[size] = e;
size++;
return true;
}
public E get(int index){
return (E)list[index];
}
@Override
public String toString() {
return Arrays.toString(list);
}
}
public class GenericsDemo {
public static void main(String[] args) {
MyArrayList<String> list = new MyArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
String str = list.get(1);
System.out.println(list);//[aaa, bbb, ccc, null, null, null, null, null, null, null]
System.out.println(str);//bbb
}
}
三 泛型方法
方法中形参类型不确定时,可以使用类名后面定义的泛型(如上面的add方法),或者在方法申明上定义自己的泛型(只有本方法能用)
格式: 修饰符 <类型> 返回值类型 方法名(类型 变量名){}
import java.util.ArrayList;
import java.util.Arrays;
public class MyListUtil {
private MyListUtil(){}
public static<E> void addAll(ArrayList<E> list,E...e){
for(E element:e){
list.add(element);
}
}
}
public class MyListUtilDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
MyListUtil.addAll(list,1,2,3);
System.out.println(list);
}
}
四 泛型接口
格式:修饰符 interface 接口名<类型>{ }
使用方式:
(1)实现类给出具体类型;
public class MyClass implement List<String>{}
(2)实现类延续泛型,创建对象时再确定。
public class MyClass<E> implement List<E>{}
五 泛型的通配符
泛型不具备继承性
虽然使用泛型会接受各种不确定的数据类型,但是,没有任何的限制;
如果我们想只接受某一个继承体系的数据类型,可以使用通配符:
? extends E;//可以接收类型E及其所有子类
? super E;//可以接收所有E及其父类