Java 溯本求源之基础(三十一)——泛型

目录

[1. 泛型的定义与基本概念](#1. 泛型的定义与基本概念)

[2. 泛型的优势](#2. 泛型的优势)

[3. 泛型的基本语法](#3. 泛型的基本语法)

[3.1 泛型类](#3.1 泛型类)

[3.2 泛型方法](#3.2 泛型方法)

[3.3 泛型接口](#3.3 泛型接口)

[4. 泛型的边界](#4. 泛型的边界)

[4.1 上限通配符(? extends T)](#4.1 上限通配符(? extends T))

[4.2 下限通配符(? super T)](#4.2 下限通配符(? super T))

[5. 泛型的类型擦除](#5. 泛型的类型擦除)

[6. 泛型的使用场景](#6. 泛型的使用场景)

[7. 结语](#7. 结语)


1. 泛型的定义与基本概念

在 Java 中,泛型(Generics)是一种强大的特性,它允许在类、接口和方法中使用类型参数。通过泛型,我们可以在编译时指定类、接口和方法的操作对象的类型,从而提高代码的安全性和复用性。

简单来说,泛型就是类型参数化。通过泛型,开发者可以编写通用的类、接口和方法,而无需在使用时指定具体的类型,直到编译时才决定具体类型,从而实现代码的类型安全和灵活性。

2. 泛型的优势
  • 类型安全 :在没有泛型的情况下,集合类(如 ListMap 等)通常只能存储 Object 类型的元素,这就意味着你在提取元素时需要进行类型转换,且可能会导致 ClassCastException 异常。泛型则通过参数化类型来避免这种情况,确保了类型安全。

  • 代码复用:通过泛型,类、方法和接口可以处理不同类型的数据,避免了重复编写相似代码的需要。

  • 提高可读性:使用泛型后,代码会更具可读性,避免了过多的强制类型转换,代码的意图更加明确。

3. 泛型的基本语法
3.1 泛型类

一个泛型类的定义格式如下:

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

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

在上面的例子中,T 是类型参数,代表某个具体的类型。在创建对象时,我们可以指定类型:

java 复制代码
Box<Integer> integerBox = new Box<>();
integerBox.setValue(10);
System.out.println(integerBox.getValue()); // 输出:10

Box<String> stringBox = new Box<>();
stringBox.setValue("Hello");
System.out.println(stringBox.getValue()); // 输出:Hello
3.2 泛型方法

除了泛型类外,泛型还可以应用于方法中。泛型方法的定义格式如下:

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

这里的 <T> 是方法级别的泛型,它表示方法的返回类型和参数类型是可以自定义的。例如:

java 复制代码
public class Test {
    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3};
        String[] stringArray = {"Hello", "World"};

        printArray(intArray);  // 输出:1 2 3
        printArray(stringArray);  // 输出:Hello World
    }
}
3.3 泛型接口

泛型还可以应用于接口。下面是一个泛型接口的例子:

java 复制代码
interface Pair<K, V> {
    K getKey();
    V getValue();
}

class SimplePair<K, V> implements Pair<K, V> {
    private K key;
    private V value;

    public SimplePair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}
4. 泛型的边界

在泛型中,除了可以指定类型,还可以使用边界来限制泛型的类型范围。常见的有上限通配符和下限通配符。

4.1 上限通配符(? extends T

上限通配符用于指定某个泛型类型是指定类型或其子类。例如:

java 复制代码
public static void printList(List<? extends Number> list) {
    for (Number num : list) {
        System.out.println(num);
    }
}
4.2 下限通配符(? super T

下限通配符用于指定某个泛型类型是指定类型或其父类。例如

java 复制代码
public static void addNumbers(List<? super Integer> list) {
    list.add(10);
    list.add(20);
}

? super Integer 表示这个 list 的类型参数可以是 Integer 类型或其父类(如 NumberObject)。

5. 泛型的类型擦除

Java 泛型是通过类型擦除 来实现的。这意味着在编译时,Java 会将泛型的实际类型替换为原始类型(通常是 Object),因此,在运行时,无法直接获取泛型的类型信息。

例如:

java 复制代码
public class Test {
    public static void main(String[] args) {
        Box<Integer> intBox = new Box<>();
        Box<String> strBox = new Box<>();

        System.out.println(intBox.getClass() == strBox.getClass());  // 输出:true
    }
}

尽管 intBoxstrBox 是不同类型的泛型对象,但它们的类类型在运行时是一样的。

6. 泛型的使用场景

泛型在实际开发中应用广泛,以下是一些典型的使用场景:

  1. 集合类 :Java 集合框架中的大多数类(如 List, Map, Set 等)都支持泛型,用于存储指定类型的对象。

  2. 通用工具类:泛型可以帮助开发者编写通用的方法和类,提高代码复用性。

  3. 设计模式 :泛型在很多设计模式中也有广泛应用,如工厂模式策略模式等,能够增强系统的灵活性和可扩展性。

  4. 封装返回值:一些业务属性如果存在很多通用的返回值那么可以进行封装,如web接口返回值中可以设置一些响应信息,以及一些状态码的响应

7. 结语

Java 中的泛型是一个非常强大的特性,它能够帮助我们提高代码的复用性和类型安全性,同时使得代码更加简洁和易读。通过理解泛型的基本概念和应用场景,开发者可以在实际项目中更加高效地进行开发,减少冗余代码,并增强系统的可扩展性。

掌握泛型的使用,可以让你在开发过程中更加灵活、简洁,并能编写出更具通用性和可维护性的代码。因此,对于每一位 Java 开发者来说,深入理解泛型的特性和应用非常重要。

相关推荐
独好紫罗兰1 分钟前
洛谷题单3-P1980 [NOIP 2013 普及组] 计数问题-python-流程图重构
开发语言·python·算法
可爱的霸王龙4 分钟前
JVM——模型分析、回收机制
java·jvm
神秘的t5 分钟前
javaSE————网络原理
java·网络
独好紫罗兰6 分钟前
洛谷题单3-P1009 [NOIP 1998 普及组] 阶乘之和-python-流程图重构
开发语言·python·算法
Taichi呀6 分钟前
PHP语言基础
android·开发语言·php
hongweihao7 分钟前
啥?有分布式锁都还能被突破
java·后端
BeerBear8 分钟前
记一次Kill <Pid> Java进程无法退出的问题处理
java·后端·spring
Aerkui27 分钟前
Python数据类型-int
开发语言·python
莲动渔舟31 分钟前
Nyquist插件基础:LISP语法-自定义函数
服务器·开发语言·lisp·音频处理·audacity
莲动渔舟37 分钟前
Nyquist插件基础:LISP语法-运算符
开发语言·lisp·音频处理·audacity