Java集合进阶——泛型

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> 和上述代码效果一样。

相关推荐
Solis程序员2 分钟前
缓存三剑客预防策略
java·spring·缓存
FlyWIHTSKY7 分钟前
React 19 + Next.js 16(App Router)项目中集成 MSW
开发语言·javascript·vue.js
Mr.Daozhi12 分钟前
跨境电商选品完整流水线:Google Trends筛词+Meta广告分析,CLI工具设计实战
开发语言·爬虫·python·跨境电商·工具链·选品
多彩电脑12 分钟前
Swift里字符串的索引
开发语言·swift
SoftLipaRZC12 分钟前
C语言预处理详解:从宏定义到条件编译
c语言·开发语言
会周易的程序员12 分钟前
C++ 对象池深度解析:架构设计与实现原理
开发语言·c++·物联网·iot·aiot
我登哥MVP14 分钟前
Spring Boot 从“会用”到“精通”:Model-Map原理
java·spring boot·后端·spring·servlet·maven·mybatis
L_090717 分钟前
【C++】智能指针
开发语言·c++·智能指针
程序猿乐锅18 分钟前
【苍穹外卖|Day02】后台接口自测闭环:Token、DTO 与 yml 配置
java·开发语言