深入理解Java泛型

Java泛型是在JDK 5中引入的一个强大的特性,它允许开发者在编译时提供类型安全的集合操作。泛型的本质是参数化类型,即在类或方法中使用一个或多个类型形参来定义,然后在创建类实例或调用方法时传入具体的类型参数。

泛型的基本使用

泛型的基本语法如下:

java 复制代码
_genericClass<T>_ 或 _genericInterface<T>_

这里的T是一个类型参数,可以是任何有效的类型名称。在类的内部,你可以把T当作一个普通的类型来使用。

类型参数的类

java 复制代码
public class Box<T> {
    private T t;

    public Box(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }
}

类型参数的方法

java 复制代码
public class Utils {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
}

泛型的类型推断

Java 7开始支持"钻石"语法,允许开发者在声明泛型实例时不必重复其类型参数,编译器能够根据上下文推断出具体的类型。

java 复制代码
Box<String> box = new Box<>("Hello World");
// 钻石语法
Box<String> boxDiamond = new Box<>("Hello Diamond");

通配符

在某些情况下,你可能需要定义一个可以操作多种类型元素的泛型类或方法。这时可以使用通配符?来表示一个未知的类型参数。

无限制通配符

java 复制代码
public void processAny(List<?> list) {
    for (Object obj : list) {
        // 只能读取数据,不能修改
        System.out.println(obj);
    }
}

上界限定通配符

java 复制代码
public void processNumbers(List<? extends Number> list) {
    for (Number num : list) {
        // 只能读取数据,不能修改,且只能取Number及其子类的实例
        System.out.println(num.intValue());
    }
}

下界限定通配符

java 复制代码
public void processSuper(List<? super Employee> list) {
    list.add(new Employee()); // 只能添加Employee及其父类的对象
}

类型擦除

由于Java在运行时不存在泛型的类型信息,所以泛型在编译时会被擦除,类型参数将被替换为限定的最高位的类型,通常是Object或限定的类型。

java 复制代码
List<String> list = new ArrayList<String>();
// 编译后变为:
List list = new ArrayList();

泛型的局限性

泛型虽然强大,但也有其局限性:

  1. 不能实例化泛型数组:因为数组是具体类型的,而泛型是不确定的。
  2. 不能抛出或捕获泛型类型的异常:因为异常也是具体类型的。
  3. 不能使用instanceof操作泛型类型:因为泛型类型在运行时被擦除。

泛型的高级应用

泛型不仅限于集合类,它还可以用于自定义类和方法,提高代码的复用性和可读性。

自定义泛型类

java 复制代码
public class Stack<T> {
    private T[] elements;
    private int size = 0;
    private int capacity;

    public Stack(int capacity) {
        this.capacity = capacity;
        this.elements = (T[]) new Object[capacity];
    }

    public void push(T element) {
        elements[size++] = element;
    }

    public T pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        return elements[--size];
    }
}

自定义泛型方法

java 复制代码
public static <E extends Comparable<E>> E max(Collection<E> coll) {
    if (coll == null || coll.isEmpty()) {
        throw new IllegalArgumentException();
    }
    E max = null;
    for (E e : coll) {
        if (max == null || e.compareTo(max) > 0) {
            max = e;
        }
    }
    return max;
}

结语

泛型为Java语言提供了强大的类型安全支持,使得集合操作更加安全和灵活。理解泛型的使用和原理,对于编写高质量的Java代码至关重要。


这篇文章深入探讨了Java泛型的使用、类型推断、通配符、类型擦除、局限性和高级应用,适合那些希望提高自己泛型使用技巧的Java开发者。

相关推荐
皮皮林5511 小时前
IDEA 源码阅读利器,你居然还不会?
java·intellij idea
databook4 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar5 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
卡尔特斯5 小时前
Android Kotlin 项目代理配置【详细步骤(可选)】
android·java·kotlin
集成显卡5 小时前
windows 下使用 bat 批处理运行 Chrome 无头模式刷一波访问量
windows·程序员
白鲸开源5 小时前
Ubuntu 22 下 DolphinScheduler 3.x 伪集群部署实录
java·ubuntu·开源
用户8356290780515 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_5 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
ytadpole5 小时前
Java 25 新特性 更简洁、更高效、更现代
java·后端
纪莫6 小时前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股