是的,泛型(Generics)的核心目的之一就是提供类型安全(Type Safety)。
简单来说,泛型允许你在编译时(compile-time)就检查出类型错误,而不是等到运行时(runtime)才暴露出来(比如抛出 ClassCastException)。
下面通过对比 没有泛型 和 有泛型 的情况来详细解释:
在 Java 引入泛型之前(Java 1.4 及以前),集合类(如 ArrayList)内部存储的是 Object 类型。这意味着你可以往里面放任何东西,但是取出来的时候,你必须手动强制转换(Cast),这就埋下了隐患。
// 旧版本代码(没有泛型)
List list = new ArrayList();
list.add("Hello");
list.add(123); // 编译不会报错,因为 123 被自动装箱为 Integer,也是 Object
list.add(new Date());
// 取出数据
String s = (String) list.get(0); // 正常
String s2 = (String) list.get(1); // 编译通过,但运行时报错:ClassCastException
问题: 编译器无法知道 list 里到底应该放什么类型。你以为里面全是字符串,但实际上混进了一个整数。程序在编译时毫无波澜,但在运行时直接崩溃。
引入泛型后,你可以在定义集合时指定“只能装某种特定类型”。
// 使用泛型
List<String> list = new ArrayList<String>();
list.add("Hello");
// list.add(123); // 编译错误!编译器直接阻止你添加非 String 类型的数据
// list.add(new Date()); // 编译错误!
// 取出数据
String s = list.get(0); // 不需要强制转换,因为编译器知道里面肯定是 String
优势:
Integer 到 String 列表,编译器会直接报错,阻止代码编译通过。String 类型,不再需要 (String) 强转,代码更简洁,也避免了遗漏强转导致的错误。这里有一个重要的概念叫 类型擦除(Type Erasure)。
List<String> 变成 List(实际上是 List<Object> 或上限类型)。正因为要保证类型安全,泛型也有一些限制:
T obj = new T(); // 错误,因为运行时 T 被擦除了,不知道 new 什么
List<int> list = new ArrayList<>(); // 错误
List<Integer> list = new ArrayList<>(); // 正确(使用包装类)
T[] array = new T[10]; // 错误
泛型绝对是类型安全的。
它通过允许开发者在代码中声明“这个容器只能装这种类型”,让编译器在编译阶段就拦截掉非法的类型插入,从而避免了运行时出现 ClassCastException,极大地提高了代码的健壮性和可读性。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。