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

相关推荐
阿猿收手吧!3 分钟前
【C++】string_view:高效字符串处理指南
开发语言·c++
风生u29 分钟前
activiti7 详解
java
玄同76533 分钟前
我的 Trae Skill 实践|使用 UV 工具一键搭建 Python 项目开发环境
开发语言·人工智能·python·langchain·uv·trae·vibe coding
岁岁种桃花儿38 分钟前
SpringCloud从入门到上天:Nacos做微服务注册中心(二)
java·spring cloud·微服务
Word码41 分钟前
[C++语法] 继承 (用法详解)
java·jvm·c++
Yorlen_Zhang43 分钟前
Python Tkinter Text 控件完全指南:从基础编辑器到富文本应用
开发语言·python·c#
lxl130744 分钟前
C++算法(1)双指针
开发语言·c++
TT哇1 小时前
【实习 】银行经理端两个核心功能的开发与修复(银行经理绑定逻辑修复和线下领取扫码功能开发)
java·vue.js
逝水如流年轻往返染尘1 小时前
Java中的数组
java
不绝1911 小时前
C#进阶:预处理指令/反射,Gettype,Typeof/关键类
开发语言·c#