1.泛型
介绍:
泛型可以在编译阶段约束操作的数据类型,并进行检查。
应用场景:
如果在定义类、方法、接口的时候,如果类型不确定,就可以使用泛型。
格式:
<数据类型>
注意:
泛型只支持引用数据类型
如下图中<String>,就是泛型
细节:
1.指定泛型的具体类型后,传递数据时,可以传入该类型或者其子类类型
2.如果不写泛型,类型默认为Object
好处:
1.统一数据类型
2.把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来
扩展:
Java中的泛型为伪泛型,即若使用泛型确定类型后,元素若要存入集合,泛型就会检查是否为规定的类,存入集合中时,元素为Object类,但是获取元素时代码底层会将Object类强转成泛型规定的类。
且编译时会擦除泛型,在class文件中,集合中的元素仍为Object类。
2.泛型类
泛型类即在类名后面添加泛型约束的类。
下面创建一个泛型类
代码演示:
泛型类MyArratList:
public class MyArrayList <E> {Object[] obj = new Object[10];int size;public boolean add(E e) {obj[size] = e;size++;return true;}public E get(int index) {return (E) obj[index];}@Overridepublic String toString() {return Arrays.toString(obj);}
}
测试类GenericsDemo:
public class GenericsDemo {public static void main(String[] args) {MyArrayList<Integer> list = new MyArrayList<>();list.add(111);list.add(222);list.add(333);System.out.println(list);System.out.println(list.get(1));}
}
运行结果:
3.泛型方法
介绍:
泛型方法有两种形式,一种是泛型类中的方法都可以使用类名后定义的泛型,第二种是在方法申明上定义自己的泛型(只有本方法能用)下面详细介绍第二种形式。
格式:
修饰符 <类型> 返回值类型 方法名(类型 变量名){
}
小练习:
定义一个工具类ListUtil,类中定义一个静态方法addAll,用来添加多个集合元素
代码:
ListUtil类:
public class ListUtil {//因为是工具类,不需要构造方法private ListUtil(){}public static <E> void addAll(ArrayList<E> list,E...e) {for (E element : e) {list.add(element);}}
}
测试类Test:
public class Test {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();ListUtil.addAll(list,"aaa", "bbb", "ccc");System.out.println(list);}
}
运行结果:
4.泛型接口
当借口中类型不确定时,就可以使用泛型接口
格式:
修饰符 interface 接口名<类型>{
}
使用方法:
方法一.实现类给出具体类型
代码演示:
演示代码具体类型为String
List<String>即为泛型接口,重写List中的方法后,其中的泛型方法类型也被指定为String
public class MyArrayList2 implements List<String> {@Overridepublic int size() {return 0;}@Overridepublic boolean isEmpty() {return false;}@Overridepublic boolean contains(Object o) {return false;}@Overridepublic Iterator<String> iterator() {return null;}@Overridepublic Object[] toArray() {return new Object[0];}@Overridepublic <T> T[] toArray(T[] a) {return null;}@Overridepublic boolean add(String s) {return false;}@Overridepublic boolean remove(Object o) {return false;}@Overridepublic boolean containsAll(Collection<?> c) {return false;}@Overridepublic boolean addAll(Collection<? extends String> c) {return false;}@Overridepublic boolean addAll(int index, Collection<? extends String> c) {return false;}@Overridepublic boolean removeAll(Collection<?> c) {return false;}@Overridepublic boolean retainAll(Collection<?> c) {return false;}@Overridepublic void clear() {}@Overridepublic String get(int index) {return null;}@Overridepublic String set(int index, String element) {return null;}@Overridepublic void add(int index, String element) {}@Overridepublic String remove(int index) {return null;}@Overridepublic int indexOf(Object o) {return 0;}@Overridepublic int lastIndexOf(Object o) {return 0;}@Overridepublic ListIterator<String> listIterator() {return null;}@Overridepublic ListIterator<String> listIterator(int index) {return null;}@Overridepublic List<String> subList(int fromIndex, int toIndex) {return null;}
}
方法二.实现类延续泛型,创建对象时再确定
代码演示:
这种情况下重写的List方法中使用泛型的继续使用类名后定义的泛型
public class MyArrayList3<E> implements List<E> {@Overridepublic int size() {return 0;}@Overridepublic boolean isEmpty() {return false;}@Overridepublic boolean contains(Object o) {return false;}@Overridepublic Iterator<E> iterator() {return null;}@Overridepublic Object[] toArray() {return new Object[0];}@Overridepublic <T> T[] toArray(T[] a) {return null;}@Overridepublic boolean add(E e) {return false;}@Overridepublic boolean remove(Object o) {return false;}@Overridepublic boolean containsAll(Collection<?> c) {return false;}@Overridepublic boolean addAll(Collection<? extends E> c) {return false;}@Overridepublic boolean addAll(int index, Collection<? extends E> c) {return false;}@Overridepublic boolean removeAll(Collection<?> c) {return false;}@Overridepublic boolean retainAll(Collection<?> c) {return false;}@Overridepublic void clear() {}@Overridepublic E get(int index) {return null;}@Overridepublic E set(int index, E element) {return null;}@Overridepublic void add(int index, E element) {}@Overridepublic E remove(int index) {return null;}@Overridepublic int indexOf(Object o) {return 0;}@Overridepublic int lastIndexOf(Object o) {return 0;}@Overridepublic ListIterator<E> listIterator() {return null;}@Overridepublic ListIterator<E> listIterator(int index) {return null;}@Overridepublic List<E> subList(int fromIndex, int toIndex) {return null;}
}
5.泛型通配符
作用:
可以限制类型的范围
应用场景:
如果类型不确定,但是知道传递的都是哪个继承体系中的,就可以使用泛型的通配符
格式:
? extend E 表示可以传递E和E的所有子类类型
? super E 表示可以传递E和E的所有父类类型
代码演示:
public class GenericsDemo2 {public static void main(String[] args) {//创建Ye Fu Zi的集合ArrayList<Ye> list1 = new ArrayList<>();ArrayList<Fu> list2 = new ArrayList<>();ArrayList<Zi> list3 = new ArrayList<>();//调用方法method(list1);method(list2);method(list3);}//定义方法在集合中调用对象public static void method(ArrayList<? extends Ye> list){System.out.println(list);}//创建最高父类爷class Ye{}//创建父继承爷class Fu extends Ye{}//创建子继承父class Zi extends Fu{}
}
运行结果:
也可以把上述method方法中的泛型通配符改成<? super Zi> 和上述代码效果一样。