Java 容器 & 泛型:六、容器讲到为什么要使用泛型

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介:

ArrayList是集合类中无处不在的,泛型也是,泛型对集合类尤其有用。但是为啥要使用泛型?理解好了这个问题可以帮助理解相关的更多知识点。下面泥瓦匠以最简单的例子来验证这个问题。

一、泛型

泛型的目的是为了可以让更多不同类型的对象重用。没错,这样理解就太low。真正目的是为了在编译时找到bug,而不是在运行时。(编译时,指的是源代码翻译成机器识别的代码的时候。运行时,是指代码在机器中运行的时候。)泛型只存在编译时,理解这个可以帮助你更好的理解泛型。

这样,在编译时会比在运行时更容易地找到bug和修复。

二、实现没有泛型的简易版ArrayList

简易版的ArrList有个Obejct对象(因为是Object,我们可以add任意类型。)比如说,Integer 和 String的。代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package javaBasic.generic;
 
/**
  * 简易版ArrayList
  */
class ArrList
{
     private Object obj;
 
     public Object getObj()
     {
         return obj;
     }
 
     public void add(Object obj)
     {
         this.obj = obj;
     }
     
}
 
public class TestArrayList
{
     public static void main(String[] args)
     {
         ArrList arrList = new ArrList();
         arrList.add(1);
         arrList.add("1");
         
         Integer objInt = (Integer) arrList.getObj();
         System.out.println(objInt);
     }
}

运行可以看出会出现ClassCastException:

?
1
2
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
     at javaBasic.generic.TestArrayList.main(TestArrayList.java:30)

想问的问题是:”这Object对象属性,怎么不能强转呢?“

:编译时,代码没错的。运行main时,当set了String类型时,将结果强制转换为Integer就会报错这个错了。

泥瓦匠的记忆宫殿又来了:

1、使用泛型比那些杂乱的需要强制转换的Object代码具有更好的安全性和可读性。

2、使用泛型可以在编译时轻松找到和解决bugs

三、使用改写简易版ArrayList

使用泛型代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package javaBasic.generic;
 
/**
  * 简易版ArrayList
  */
class ArrList< T >
{
     private T obj;
 
     public T getObj()
     {
         return obj;
     }
 
     public void add(T obj)
     {
         this.obj = obj;
     }
     
}
 
public class TestArrayList
{
     public static void main(String[] args)
     {
         ArrList< Integer > arrList = new ArrList<>();
         arrList.add(1);
//      arrList.add("1");
         
         Integer objInt = arrList.getObj();
         System.out.println(objInt);
     }
}

这时候如果想用

?
1
arrList.add("1");

会发现:

image

这时候就是泛型大显身手的时候,也不用需要对属性 get 方法时的强制转换。其实,  Java 泛型只是编译时的概念,因为编译后类型会被擦除,还原本真。这里T就相当于Integer。

四、小结

泥瓦匠记忆宫殿

1、在编译时检查强类型

2、显示转换的消除(上面的Integer get省去)

3、更好地实现代码重用和泛型算法

4、使用泛型比那些杂乱的需要强制转换的Object代码具有更好的安全性和可读性。

相关文章
|
8天前
|
JavaScript Java 编译器
Java包装类和泛型的知识点详解
Java包装类和泛型的知识点的深度理解
|
29天前
|
Java
java中的泛型类型擦除
java中的泛型类型擦除
13 2
|
25天前
|
设计模式 程序员 C++
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
241 2
|
2天前
|
存储 安全 Java
Java中的容器,线程安全和线程不安全
Java中的容器,线程安全和线程不安全
10 1
|
7天前
|
存储 监控 安全
泛型魔法:解码Java中的类型参数
泛型魔法:解码Java中的类型参数
30 0
泛型魔法:解码Java中的类型参数
|
9天前
|
Java API
Java基础—笔记—内部类、枚举、泛型篇
本文介绍了Java编程中的内部类、枚举和泛型概念。匿名内部类用于简化类的创建,常作为方法参数,其原理是生成一个隐含的子类。枚举用于表示有限的固定数量的值,常用于系统配置或switch语句中。泛型则用来在编译时增强类型安全性,接收特定数据类型,包括泛型类、泛型接口和泛型方法。
9 0
|
25天前
|
存储 安全 编译器
【C++ 17 泛型容器对比】C++ 深度解析:std::any 与 std::variant 的细微差别
【C++ 17 泛型容器对比】C++ 深度解析:std::any 与 std::variant 的细微差别
47 1
|
25天前
|
存储 安全 算法
【C++ 17 包裹类 泛型容器 std::any】深入理解与应用C++ std::any:从泛型编程到多态设计
【C++ 17 包裹类 泛型容器 std::any】深入理解与应用C++ std::any:从泛型编程到多态设计
47 1
|
1月前
|
存储 安全 Java
JAVA泛型
JAVA泛型
11 0
|
3月前
|
存储 算法 安全
面霸篇:Java 核心集合容器全解(核心卷二)
面霸篇:Java 核心集合容器全解(核心卷二)
36 0