Java中泛型擦除机制

1. 为什么擦除:向后兼容性

泛型擦除保证了 Java 向后兼容老版本的代码。如果没有擦除机制,Java 就无法兼容原来的非泛型代码。

示例:泛型擦除保持兼容性
import java.util.List;

public class GenericErasureExample {
    public static void main(String[] args) {
        // 使用泛型的List
        List<String> list = List.of("Hello", "World");
        System.out.println(list.getClass());  // 输出: class java.util.ArrayList
    }
}
解释:
  • 编译时,List<String> 允许存储 String 类型的元素。
  • 运行时,泛型类型 String 被擦除,list.getClass() 返回的是 java.util.ArrayList,没有泛型信息。
  • 这种机制保证了泛型引入后,原始的 List 类在运行时可以继续使用,而不破坏兼容性。

2. 作用:提供类型安全检查

泛型的作用是在编译时提供类型检查,这意味着可以避免错误的类型传入集合中。

示例:类型检查
import java.util.List;

public class TypeSafetyExample {
    public static void main(String[] args) {
        List<String> list = List.of("Apple", "Banana");
        // list.add(1);  // 编译时错误:无法添加非String类型的元素
        
        System.out.println(list);
    }
}
解释:
  • List<String> 在编译时只允许添加 String 类型的数据。
  • 如果尝试向 List<String> 添加非 String 类型的元素,编译器会报错。
  • 这是泛型提供的类型安全性,尽管运行时 String 类型的信息被擦除,但编译时会做类型检查。

3. 注意事项:无法获取运行时类型

由于泛型信息被擦除,运行时无法知道泛型的具体类型。

示例:运行时无法获取泛型类型
import java.util.List;

public class RuntimeTypeExample {
    public static void main(String[] args) {
        List<String> list = List.of("Hello", "World");

        // 尝试通过 instanceof 判断类型
        // if (list instanceof List<String>) {  // 编译错误: 泛型类型信息擦除
        //     System.out.println("It's a List<String>");
        // }
        
        // 运行时类型输出
        System.out.println(list.getClass());  // 输出: class java.util.ArrayList
    }
}
解释:
  • 编译时List<String> 只允许 String 类型的元素,但运行时,泛型类型 String 被擦除,只剩下 List
  • 运行时list.getClass() 输出的是 java.util.ArrayList,没有 String 的信息。你不能用 instanceof List<String> 来检查类型,因为编译时泛型信息已经被擦除。

4. 注意事项:无法创建泛型数组

由于泛型擦除,你不能创建具有泛型类型参数的数组。

示例:不能创建泛型数组
public class GenericArrayExample {
    public static void main(String[] args) {
        // 编译错误:无法创建带泛型的数组
        // List<String>[] array = new List<String>[10];
        
        // 正确做法:可以创建一个原始类型的数组
        List[] array = new List[10];  // 允许,但会有类型警告
    }
}
释:
  • 编译时,尝试创建 List<String>[] 数组会报错,因为泛型在运行时被擦除,无法创建带有具体泛型类型的数组。
  • 你只能创建原始类型的数组(List[]),但这会导致类型不安全,因此编译器会发出警告。

5. 泛型的上限:擦除为边界类型

如果泛型有上限(例如 T extends Number),在擦除时,T 会被替换为边界类型(Number)。

示例:泛型上限的擦除
import java.util.List;

public class BoundTypeExample {
    public static void main(String[] args) {
        // List<Integer> 是 List<Number> 的子类
        List<? extends Number> list = List.of(1, 2, 3);
        
        // 运行时擦除:<? extends Number> 会被擦除为 List
        System.out.println(list.getClass());  // 输出: class java.util.ArrayList
    }
}
解释:
  • 这里 List<? extends Number> 的泛型上限是 Number,在运行时,泛型信息被擦除,list.getClass() 输出的是 java.util.ArrayList,而不是 java.util.ArrayList<Number>
  • 这说明在擦除时,? extends Number 会变成原始的 List 类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值