1.泛型
介绍:
泛型可以在编译阶段约束操作的数据类型,并进行检查。
应用场景:
如果在定义类、方法、接口的时候,如果类型不确定,就可以使用泛型。
格式:
<数据类型>
注意:
泛型只支持引用数据类型
如下图中<String>,就是泛型
细节:
1.指定泛型的具体类型后,传递数据时,可以传入该类型或者其子类类型
2.如果不写泛型,类型默认为Object
好处:
1.统一数据类型
2.把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为在编译阶段类型就能确定下来
扩展:
Java中的泛型为伪泛型,即若使用泛型确定类型后,元素若要存入集合,泛型就会检查是否为规定的类,存入集合中时,元素为Object类,但是获取元素时代码底层会将Object类强转成泛型规定的类。
且编译时会擦除泛型,在class文件中,集合中的元素仍为Object类。
2.泛型类
泛型类即在类名后面添加泛型约束的类。
下面创建一个泛型类
代码演示:
泛型类MyArratList:
java
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];
}
@Override
public String toString() {
return Arrays.toString(obj);
}
}
测试类GenericsDemo:
java
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类:
java
public class ListUtil {
//因为是工具类,不需要构造方法
private ListUtil(){}
public static <E> void addAll(ArrayList<E> list,E...e) {
for (E element : e) {
list.add(element);
}
}
}
测试类Test:
java
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
java
public class MyArrayList2 implements List<String> {
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public Iterator<String> iterator() {
return null;
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public <T> T[] toArray(T[] a) {
return null;
}
@Override
public boolean add(String s) {
return false;
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean containsAll(Collection<?> c) {
return false;
}
@Override
public boolean addAll(Collection<? extends String> c) {
return false;
}
@Override
public boolean addAll(int index, Collection<? extends String> c) {
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return false;
}
@Override
public boolean retainAll(Collection<?> c) {
return false;
}
@Override
public void clear() {
}
@Override
public String get(int index) {
return null;
}
@Override
public String set(int index, String element) {
return null;
}
@Override
public void add(int index, String element) {
}
@Override
public String remove(int index) {
return null;
}
@Override
public int indexOf(Object o) {
return 0;
}
@Override
public int lastIndexOf(Object o) {
return 0;
}
@Override
public ListIterator<String> listIterator() {
return null;
}
@Override
public ListIterator<String> listIterator(int index) {
return null;
}
@Override
public List<String> subList(int fromIndex, int toIndex) {
return null;
}
}
方法二.实现类延续泛型,创建对象时再确定
代码演示:
这种情况下重写的List方法中使用泛型的继续使用类名后定义的泛型
java
public class MyArrayList3<E> implements List<E> {
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public Iterator<E> iterator() {
return null;
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public <T> T[] toArray(T[] a) {
return null;
}
@Override
public boolean add(E e) {
return false;
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean containsAll(Collection<?> c) {
return false;
}
@Override
public boolean addAll(Collection<? extends E> c) {
return false;
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return false;
}
@Override
public boolean retainAll(Collection<?> c) {
return false;
}
@Override
public void clear() {
}
@Override
public E get(int index) {
return null;
}
@Override
public E set(int index, E element) {
return null;
}
@Override
public void add(int index, E element) {
}
@Override
public E remove(int index) {
return null;
}
@Override
public int indexOf(Object o) {
return 0;
}
@Override
public int lastIndexOf(Object o) {
return 0;
}
@Override
public ListIterator<E> listIterator() {
return null;
}
@Override
public ListIterator<E> listIterator(int index) {
return null;
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return null;
}
}
5.泛型通配符
作用:
可以限制类型的范围
应用场景:
如果类型不确定,但是知道传递的都是哪个继承体系中的,就可以使用泛型的通配符
格式:
? extend E 表示可以传递E和E的所有子类类型
? super E 表示可以传递E和E的所有父类类型
代码演示:
java
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> 和上述代码效果一样。