什么是泛型
JDK5引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
泛型的作用
如果没有给集合数据类型,那么会默认所有的数据类型都是object
此时可以向集合中添加任意的数据类型
带来一个问题 ,我们无法使用这个数据类型的特有行为
此时推出了泛型,它就像一个保安一样,限制了集合内可存储元素的类型,我们在添加数据的时候就把数据类型进行统一
我们在获取数据的时候,也不用进行强制转换很方便
泛型的好处
1、统一数据类型
2、运行时期的问题提前到了编译时期,避免了强制类型转换时可能出现的异常。
拓展:JAVA泛型是一种伪泛型
实际上存入的数据类型仍然是Object,仅仅在编译过程中做限制作用,在字节码文件中泛型会消失,学名:泛型擦除
泛型的细节
1、泛型中不能写基本数据类型,这是因为基本数据类型不继承于Object类
2、指定泛型的具体类型后,传递数据时,可以传入其子类类型。
3、如果不写泛型,默认为Object类
public static void main(String[] args) {
//没有泛型的时候,集合如何存储数据
//1、创建集合的对象
ArrayList list=new ArrayList();
//2、添加数据
list.add(123);
list.add("aaa");
list.add(new Student("zhangsan",12));
//3、遍历集合里的每一个元素
Iterator it=list.iterator();
while (it.hasNext()){
//多态的弊端是不能调用子类的功能
Object obj=it.next();
//当我们输出一个引用数据类型时,会自动调用toString方法,如果我们不主动去重写他,默认会输出地址值
System.out.println(obj);
}
}
泛型可以作用于那些地方?
泛型类、泛型方法、泛型接口
泛型类
使用场景:当一个类中,某个变量的数据类型不确定时,就可以定义带有泛型的类。
下面代码中E可以理解为一个变量,但并非记录数据,而是记录数据的数据类型。
public class A1<E> {
/*
当我们编写一个类的时候,如果不知道类型,就可以定义成泛型类
*/
Object[] obj=new Object[10];
int size=0;
//E是不确定的类型,该类型已经在类名后面定义过了
//e是形参的名字,变量名
public boolean add(E e){
obj[size]=e;
size++;
return true;
}
public E getSize(int index) {
return (E)obj[index];
}
@Override
public String toString() {
return Arrays.toString(obj);
}
}
public class A1Test {
public static void main(String[] args) {
A1<String> list=new A1<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
System.out.println(list);
}
}
泛型方法
当方法内的参数类型不确定时
方案1:使用类名后面的泛型
方案2:在方法声明上定义自己的泛型
格式:
修饰符<类型> 返回值类型 方法名(类型 变量名){ }
public class A3 {
private A3(){}
//类中定义一个静态方法addAll,用来添加多个集合的元素
/*
参数1 集合
参数2到最后 需要添加的元素
*/
public static<E> void addALL(ArrayList<E> list,E e1,E e2){
list.add(e1);
list.add(e2);
}
}
public class A3Test {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>();
A3.addALL(list,"aaa","ccc");
System.out.println(list);
}
}
泛型接口
格式:
修饰符 interface 接口名<类型>{ }
如何使用一个带泛型的接口?
1、实现类给出具体的类型
2、实现类继续延续泛型,创建实现类对象的时候再确定类型