在逛 Stack Overflow 的时候,发现了一些访问量像熊耳山一样高的问题,比如说这个:为什么不应该使用Java的原始类型?访问量足足有 205K+,这不得了啊!说明有很多很多的程序员被这个问题困扰过。实话实说吧,本文之前的我就是其中之一。

来回顾一下提问者的问题吧:

Java 的原始类型是什么?为什么不要使用原始类型?如果不能使用原始类型,有什么更好的选择呢?

如果大家也被这个问题困扰过,或者正在被困扰,就请随我来,咱们肩并肩手拉手一起梳理一下这个问题,并找出最佳答案。Duang、Duang、Duang,打怪进阶喽!

01、Java 的原始类型是什么?

要理解 Java 的原始类型是什么,可以先看一下什么是泛型。

List<String> list = null;

其中 list 就是一个泛型,我们通常称之为字符串(String)列表(List),也就是说 list 中只能放字符串类型的元素。

如果我们按照下面这种方式声明 list 的话,它就是一个原始类型。

List list = null;

从 list 的声明当中我们可以对比发现,原始类型没有为容器指定明确的元素类型,所以我们可以在容器中放入一个 String,也可以放入一个 Integer,甚至任意的类型,就像下面这样。

public class RawType {public static void main(String[] args) {List list = new ArrayList();list.add("沉默王二");list.add(18);list.add(new RawType());}
}

注意哦,编译器没有任何提醒!这预示着 Java 这门强类型的语言竟然有点弱类型的影子了。

PS:关于 Java 中的类型术语,大家可以参照下表。

术语 含义 举例
Parameterized type 参数化类型 List<String>
Actual type parameter 实际类型参数 String
Generic type 泛型类型 List<E>
Formal type parameter 形式类型参数 E
Unbounded wildcard type 无限制通配符类型 List<?>
Raw type 原始类型 List
Bounded type parameter 限制类型参数 <E extends Number>
Bounded wildcard type 限制通配符类型 List<? extends Number>

02、为什么不要使用原始类型?

大家可能会有一个疑惑,原始类型用起来很爽啊!因为不用关心放入 List 的元素到底是什么类型,想放什么就可以放什么,不要太爽啊!

可当我们想要从 List 中把元素取出来使用的时候,可就遇到大麻烦了。

List list = new ArrayList();
list.add("沉默王二");
list.add(18);
list.add(new RawType());for (Object o : list ) {String s = (String) o;System.out.println(s);
}

上面这段代码编译的时候没有任何问题,但输出的时候就会抛出 ClassCastException

沉默王二
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stringat com.cmower.java_demo.programcreek.RawType.main(RawType.java:14)

除非我们使用 instanceof 关键字进行类型判断,就像下面这样。

List list = new ArrayList();
list.add("沉默王二");
list.add(18);
list.add(new RawType());for (Object o : list ) {if (o instanceof String) {String s = (String) o;System.out.println(s);} else if (o instanceof Integer) {Integer i = (Integer) o;System.out.println(i);} else if (o instanceof RawType) {RawType raw = (RawType) o;System.out.println(raw);}
}

可假如代码写成这样,可真真算得上是糟糕的代码了。

通常来说,为了代码的安全性起见,我们希望代码的错误发生得越早越好,能在编译时就不要在运行时。可使用原始类型的时候,我们发现错误一直到运行时才可能会被检出。

还记得《扁鹊见蔡桓公》的故事吗?

扁鹊见蔡桓公,立有间。扁鹊曰:“君有疾在腠理,不治将恐深。”桓侯曰:“寡人无疾。”扁鹊出,桓侯曰:“医之好治不病以为功。”…居十日,扁鹊望桓侯而还走。桓侯故使人问之,扁鹊曰:“疾在腠理,汤熨之所及也;在肌肤,针石之所及也;在肠胃,火齐之所及也;在骨髓,司命之所属,无奈何也。今在骨髓,臣是以无请也。”居五日,桓侯体痛,使人索扁鹊,已逃秦矣。桓侯遂死。

病情发现得越早,治疗的可能性就越大。同理,代码隐藏的问题发现的越晚,找出根源花费的精力就越大、时间就越多。

03、有什么更好的选择呢?

如果不能使用原始类型,有什么更好的选择呢?

为了让 List 能够容纳任意类型的元素,我们可以使用 List<Object>,尽管这并不是一个最优的选择。

List<Object> list = new ArrayList<>();
list.add("沉默王二");
list.add(18);
list.add(new RawType());

鹅鹅鹅,这样的参数化类型 List<Object> 和原始类型 List 之间有区别吗?

当然有了!

List<Object> 至少明确地告诉编译器,该容器可以存放任意类型的对象,没有丢失类型的安全性。

可能我这样的解释会遭到某些抨击:“这不五十步笑百步吗?呵呵。”但我要想表达的是登月男神阿姆斯特朗的那句话:“这是我个人的一小步,却是人类的一大步。”能向前迈一步是一步啊。

那最优的选择是什么呢?

从一开始就为 List 声明具体的类型,比如说 List<String> list,当我们尝试放入一个 int 值的时候就会编译出错。

从另一种层面上来说,这样做削弱了程序的灵活性,但保证了程序的绝对安全性,以及在表达上的明确性。

04、为什么 Java 允许使用原始类型?

既然原始类型是不安全的,那为什么 Java 一直允许使用原始类型呢?并且泛型擦除后仍然是个原始类型呢?

答案很简单、很无厘头、很苍白——为了版本兼容!

引入泛型的时候,Java 已经进入到第二个十年(年纪大了),市面上存在大量没有使用 Java 泛型的代码。如果因为版本升级导致它们不能使用,恐怕 Java 也活不到现在,毕竟对用户友好才是一个软件存在的硬道理。

当然了,Java 已经对开发者做出了警示:强烈建议不要在 Java 代码中使用原始类型,未来的版本中可以会禁止使用原始类型,请小心点。

05、鸣谢

好了各位读者朋友们,以上就是本文的全部内容了。能看到这里的都是最优秀的程序员,升职加薪就是你了

五分钟学Java:为什么不应该使用Java的原始类型?相关推荐

  1. 语言叮叮消息接口_五分钟学后端技术:如何学习Java工程师必知必会的消息队列...

    原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 什么是消息队列 "RabbitMQ?""Kafka?""RocketMQ?" ...

  2. 五分钟学会python_关于五分钟学Python系列视频

    Up主记得我们父母辈考大学的时候,外语,尤其是英语,是一个非常火爆的专业.那个时候会英语的人相对比较少,因此能掌握流利的英文听说读写的学生可以算是稀缺人才.现在虽然英语专业人才仍然有很大市场,但是整体 ...

  3. 五分钟学GIS | BIM与三维GIS的融合

    今天五分钟学GIS的时间我们来学习BIM与三维GIS的融合. 什么是BIM? BIM:建筑信息模型(Building Information Modeling)或者建筑信息管理(Building In ...

  4. 五分钟学GIS | GIS服务器集群技术

    今天五分钟学GIS的时间我们来学习GIS集群技术. 什么是GIS服务器集群 GIS服务器集群,是指将多个GIS服务器成群组,当有用户请求到达集群服务器时,集群服务器的父节点统一对GIS服务进行调配,使 ...

  5. 五分钟学GIS | 倾斜摄影单体化技术

    第二期的"五分钟学GIS | 倾斜摄影技术"专题之后,相信大家对倾斜摄影技术已经有了一个初步的认识,本期我们将深入讲解倾斜摄影单体化技术. 单体化技术的来源 在第二期专题中我们了解 ...

  6. 为什么虚拟机上一运行就显示程序停止_五分钟学Java:如何学习Java面试必考的JVM虚拟机...

    原创声明 本文首发于微信公众号[程序员黄小斜] 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 为什么要学习JVM虚拟机 最近的你有没有参加Java面试呢?你有没有发现,Java ...

  7. 为什么虚拟机上一运行就显示程序停止_五分钟学Java:如何学习Java面试必考的JVM虚拟机||CSDN博文精选...

    作者:黄小斜 原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 为什么要学习JVM虚拟机 最近的你有没有参加Java面试呢?你有没有发现,Java面试中总是爱考一类问题, ...

  8. 五分钟看懂python函数(同Java方法作比较)

    今天来学习python函数,对于有java基础的我来说那岂不是手到擒来 既然已经有java基础了,那么首先我想到的就是两个问题 python如何定义函数 python如何调用函数 python中如何定 ...

  9. 【Java 泛型】泛型(泛型类型、原始类型、泛型方法)、通配符(上界、下界、无限制、继承)

    泛型(Generics) 泛型(Generics) 泛型类型(Generic Type) 多个类型参数 泛型类型的继承 原始类型(Raw Type) 泛型方法(Generic Method) 泛型方法 ...

最新文章

  1. 防止程序重复执行的单元
  2. Entityframework:“System.Data.Entity.Internal.AppConfig”的类型初始值设定项引发异常。
  3. python 文件 IO 操作
  4. 效率提升一倍,成本下降 80%,阿里云落地全球最大规模云原生实践
  5. DES和RSA算法的java实现
  6. linux boot命令用法,Linux基础命令介绍 - 2
  7. CDOJ 483 Data Structure Problem DFS
  8. 2015-11-23 12:50:55
  9. 【环境搭建】在Ubuntu16.04上搭建Nginx-rtmp流媒体服务器
  10. ie7/8卸载工具 降级到IE6
  11. java gzip rest_使用restclient或postman发送gzip数据
  12. C++11 forward完美转发
  13. hoolilaw解读:在美国如何应对交通罚单
  14. 如何实现一个漂亮的微信小程序朋友圈、表白墙、校内圈(后台篇)
  15. 【Spring Data ElasticSearch】高级查询,聚合
  16. 供应链安全这件事,早就被朱元璋玩明白了
  17. Kotlin-Android世界的一股清流-委托
  18. com.google.android.material.tabs.TabLayout 选择tab 加粗字体加大
  19. ubuntu快捷复制粘贴
  20. domyPP:回归经典表格管理,以可协作表格管理项目

热门文章

  1. [代码解读]独立按键控制LED位移c51单片机
  2. [国产PLC]耐特来源PLC在锅具旋压机中怎样运用
  3. 关于网上商城开发的随笔记录4
  4. 今天下载并安装了Rss阅读器Awasu,还是很爽的。
  5. CSV 格式数据清洗 Python123
  6. Manjaro 输入法配置
  7. OGame的建筑说明
  8. 1.2软件工程是不是教会不怎么会写程序的人开发软件?
  9. 【华为ICT备赛】华为VRP系统
  10. 架构设计文档模板参考