Java 泛型详解

🌟 什么是泛型?

泛型(Generics) 是 JDK 5 引入的一项重要特性,旨在增强代码的可读性、类型安全性和复用性。

使用泛型后,编译器可以在编译阶段对传入的参数进行类型检查,避免运行时因类型不匹配导致的错误。例如:

ArrayList<Person> persons = new ArrayList<>();
persons.add(new Person()); // ✅ 合法
persons.add("Hello");      // ❌ 编译错误!

📌 关键点

  • 泛型确保了集合只能存储指定类型的对象

  • 如果试图添加不符合泛型类型的对象,编译器会直接报错

  • 这不是运行时报错,而是编译期就能发现的错误


🔁 泛型的三大使用方式

1️⃣ 泛型类(Generic Class)

通过在类名后加上 <T>,声明一个泛型类,使类具有通用性。

// T 可以是任意标识符,常见如 T、E、K、V 等
public class Generic<T> {
​
    private T key;
​
    public Generic(T key) {
        this.key = key;
    }
​
    public T getKey() {
        return key;
    }
}

📌 使用示例:

Generic<String> stringGeneric = new Generic<>("Hello");
System.out.println(stringGeneric.getKey()); // 输出: Hello
​
Generic<Integer> integerGeneric = new Generic<>(123);
System.out.println(integerGeneric.getKey()); // 输出: 123

2️⃣ 泛型接口(Generic Interface)

接口也可以定义为泛型形式,允许实现类根据需要指定具体类型。

public interface Generator<T> {
    T method();
}

📌 实现示例:

public class StringGenerator implements Generator<String> {
    @Override
    public String method() {
        return "Generated String";
    }
}

3️⃣ 泛型方法(Generic Method)

即使类本身不是泛型类,也可以单独定义泛型方法。

public static <E> void printArray(E[] inputArray) {
    for (E element : inputArray) {
        System.out.printf("%s ", element);
    }
    System.out.println();
}

📌 特别注意:

  • 静态方法要使用泛型,必须在方法前显式声明 <E>

  • 普通方法如果在泛型类中,可以直接使用类上的泛型参数(如 T

  • 如果普通方法不在泛型类中,也必须自己声明泛型参数

📌 使用示例:

Integer[] intArray = {1, 2, 3};
String[] strArray = {"Java", "泛型", "真香"};
​
printArray(intArray);   // 输出: 1 2 3 
printArray(strArray);   // 输出: Java 泛型 真香 

⚠️ 类型擦除(Type Erasure)

Java 的泛型是编译期特性,在运行时会被“擦除”,即所谓的 类型擦除(Type Erasure)

这意味着:

  • 在 JVM 层面,ArrayList<Person>ArrayList<String> 被视为相同的类型

  • 所有泛型信息在编译后都会被替换为原始类型(raw type),比如 ArrayList

  • 编译器会在必要处插入类型检查和强制转换,以保证类型安全

💡 那为什么还能保证类型安全?

因为编译器做了严格的检查,并且在必要时插入了隐式类型转换

举个例子:

Person p = list.get(0); // ✅ 安全,编译器自动插入 (Person)

编译器确保你取出来的对象一定是 Person 类型,不需要你自己再强转。

📌 示例:

ArrayList<Integer> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
​
System.out.println(list1.getClass() == list2.getClass()); // true


💡 小贴士

问题回答
泛型类可以继承吗?✅ 可以,但子类必须明确泛型类型或继续使用泛型
接口和类能同时使用泛型吗?✅ 可以,泛型接口可以由泛型类或普通类实现
如何限制泛型类型?✅ 使用通配符,如 <T extends Number>
静态方法能否使用类级别的泛型?❌ 不行,必须自己声明泛型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值