建议29: 优先选择基本类型
包装类型是一个类,它提供了诸如构造方法、类型转换、比较等非常实用的功能,而且在Java 5之后又实现了与基本类型之间的自动转换,这使包装类型如虎添翼,更是应用广泛了,在开发中包装类型已经随处可见,但无论是从安全性、性能方面来说,还是从稳定性方面来说,基本类型都是首选方案。我们来看一段代码:
- public class Client {
- public static void main(String[] args) {
- Client cilent = new Client();
- int i=140;
- //分别传递int类型和Integer类型
- cilent.f(i);
- cilent.f(Integer.valueOf(i));
- }
- public void f(long a) {
- System.out.println("基本类型的方法被调用");
- }
- public void f(Long a) {
- System.out.println("包装类型的方法被调用");
- }
- }
在上面的程序中首先声明了一个int变量i,然后加宽转变成long型,再调用f()方法,分别传递int和long的基本类型和包装类型,诸位想想该程序是否能够编译?如果能编译输出结果又是什么呢?
首先,这段程序绝对是能够编译的。不过,说不能编译的同学还是很动了一番脑筋的,只是还欠缺点火候,你可能会猜测以下这些地方不能编译:
f()方法重载有问题。定义的两个f()方法实现了重载,一个形参是基本类型,一个形参是包装类型,这类重载很正常。虽然基本类型和包装类型有自动装箱、自动拆箱的功能,但并不影响它们的重载,自动拆箱(装箱)只有在赋值时才会发生,和重载没有关系。
cilent.f(i)报错。i是int类型,传递到fun(long l)是没有任何问题的,编译器会自动把i的类型加宽,并将其转变为long型,这是基本类型的转换规则,也没有任何问题。
cilent.f(Integer.valueOf(i)) 报错。代码中没有f(Integer i)方法,不可能接收一个Integer类型的参数,而且Integer和Long两个包装类型是兄弟关系,不是继承关系,那就是说肯定编译失败了?不,编译是成功的,稍后再解释为什么这里编译成功。
既然编译通过了,我们来看一下输出:
- 基本类型的方法被调用
- 基本类型的方法被调用
cilent.f(i)的输出是正常的,我们已经解释过了。那第二个输出就让人很困惑了,为什么会调用f(long a)方法呢?这是因为自动装箱有一个重要的原则:基本类型可以先加宽,再转变成宽类型的包装类型,但不能直接转变成宽类型的包装类型。这句话比较拗口,简单地说就是, int可以加宽转变成long,然后再转变成Long对象,但不能直接转变成包装类型,注意这里指的都是自动转换,不是通过构造函数生成。为了解释这个原则,我们再来看一个例子:
- public class Client {
- public static void main(String[] args) {
- int i=100;
- f(i);
- }
- public static void f(Long l){
- }
- }
这段程序编译是通不过的,因为i是一个int类型,不能自动转变为Long型。但是修改成以下代码就可以编译通过了:
- public static void main(String[] args) {
- int i=100;
- long l = (long)i;
- f(l);
- }
这就是int先加宽转变为long型,然后自动转换成Long型。规则说明白了,我们继续来看f(Integer.valueOf(i))是如何调用的,Integer.valueOf(i)返回的是一个Integer对象,这没错,但是Integer和int是可以互相转换的。没有f(Integer i)方法?没关系,编译器会尝试转换成int类型的实参调用,OK,这次成功了,与f(i)相同了,于是乎被加宽转变成long型—结果也很明显了。整个f(Integer.valueOf(i))的执行过程是这样的:
i通过valueOf方法包装成一个Integer对象。
由于没有f(Integer i)方法,编译器“聪明”地把Integer对象转换成int。
int自动拓宽为long,编译结束。
使用包装类型确实有方便的地方,但是也会引起一些不必要的困惑,比如我们这个例子,如果f()的两个重载方法使用的是基本类型,而且实参也是基本类型,就不会产生以上问题,而且程序的可读性更强。自动装箱(拆箱)虽然很方便,但引起的问题也非常严重—我们甚至都不知道执行的是哪个方法。
注意 重申,基本类型优先考虑。
相关推荐
基本类型转化时常见错误和问题 33 方法 33 简单的键盘输入和输出 33 本章思考作业 34 上机操作 34 第二章(2) 控制语句 35 顺序结构 35 选择结构 35 if单选择结构 35 if-else双选择结构 35 If-elseif-else多选择结构 ...
Java.Bug模式详解 第1章 混乱环境下的灵活方法 1.1 软件设计、实现和维护的趋势 1.1.1 对于稳定、安全 系统的需求增加 1.1.2 传统软件工程技 术的局限性 1.1.3 开放源代码的软 件项目的可利用性 1.1.4 对于...
(2)图的深度优先和广度优先遍历。 (3)无向图的连通性和最小生成树 (4)拓扑排序 (5)关键路径 (6)单源最短路径 5.散列表(哈希表) (1)散列表的概念 (2)散列表解决散列冲突的方法(开放地址法、链地址...
<br>(11) 第11章:运行期类型鉴定 若只有指向基础类的一个句柄,Java的运行期类型标鉴定(RTTI)使我们能获知一个对象的准确类型是什么。一般情况下,我们需要有意忽略一个对象的准确类型,让Java的动态绑定...
引论1.1 本书讨论的内容1.2 数学知识复习1.2.1 指数1.2.2 对数1.2.3 级数1.2.4 模运算1.2.5 证明的方法1.3 递归简论1.4 实现泛型特性构件pre-Java51.4.1 使用Object表示泛型1.4.2 基本类型的包装1.4.3 使用接口...
译者序前言第1章 引论1.1 本书讨论的内容1.2 数学知识复习1.2.1 指数1.2.2 对数1.2.3 级数1.2.4 模运算1.2.5 证明的方法1.3 递归简论1.4 实现泛型特性构件pre-Java51.4.1 使用Object表示泛型1.4.2 基本类型的包装...
10.11.1不能使用基本类型326 10.11.2不能使用泛型类异常326 10.11.3不能使用泛型数组327 10.11.4不能实例化参数类型对象..327 10.12本章小结328 第11章集合329 11.1集合接口与抽象类329 11.1.1Collection接口...
讲述了基本概念、递归和回溯、链表、栈、队列、树、优先队列和堆、并查集DAT、图算法、排序、查找、选择算法(中位数)、符号表、散列、字符串算法、算法设计技术、贪婪算法、分治算法、动态规划算法、复杂度类型等...
译者序前言第1章 引论1.1 本书讨论的内容1.2 数学知识复习1.2.1 指数1.2.2 对数1.2.3 级数1.2.4 模运算1.2.5 证明的方法1.3 递归简论1.4 实现泛型特性构件pre-Java51.4.1 使用Object表示泛型1.4.2 基本类型的包装...
1.4.2 基本类型的包装 1.4.3 使用接口类型表示泛型 1.4.4 数组类型的兼容性 1.5 利用Java5泛性实现泛型特性成分 1.5.1 简单的泛型类和接口 1.5.2 自动装箱/拆箱 1.5.3 带有限制的通配符 1.5.4 泛型static方法 ...
1.1.3 基本类型数组的初始化 1.1.4 引用类型数组的初始化 1.2 使用数组 1.2.1 数组元素就是变量 1.2.2 没有多维数组 1.3 小结 第2课 对象与内存控制 2.1 实例变量和类变量 2.1.1 实例变量和类变量的属性 ...
java5 1.4.1 使用object表示泛型 1.4.2 基本类型的包装 1.4.3 使用接口类型表示泛型 1.4.4 数组类型的兼容性 1.5 利用java5泛性实现泛型特性成分 1.5.1 简单的泛型类和接口 1.5.2 自动装箱/拆箱....
java5 1.4.1 使用object表示泛型 1.4.2 基本类型的包装 1.4.3 使用接口类型表示泛型 1.4.4 数组类型的兼容性 1.5 利用java5泛性实现泛型特性成分 1.5.1 简单的泛型类和接口 1.5.2 自动装箱/拆箱....
3.7 各类型数据间的优先关系和相互转换 第4章 运算符与表达式 4.1 算术运算符 4.2 关系运算符 4.3 布尔逻辑运算符 4.4 位运算符 4.5 赋值运算符 4.6 字符串运算符 4.7 扩展赋值运算符 4.8 条件运算符 ...
基本数据类型、算法和数据结构的介绍。 我们的重点是 Java 实现的应用程序和科学性能分析。 Part I 重点介绍基本data structures 、 sorting和searching 。 主题包括: 联合发现, 二分查找, 堆栈, 排队, 包, ...
小结 练习 参考文献 第6章 优先队列(堆) 6.1 模型 6.2 一些简单的实现 6.3 二叉堆 6.3.1 结构性质 6.3.2 堆序性质 6.3.3 基本的堆操作 6.3.4 其他的堆操作 6.4 优先队列的应用 6.4.1 选择问题 6.4.2...
1.1.1 Java程序的基本结构 4 1.1.2 原始数据类型与表达式 6 1.1.3 语句 8 1.1.4 简便记法 9 1.1.5 数组 10 1.1.6 静态方法 12 1.1.7 API 16 1.1.8 字符串 20 1.1.9 输入输出 21...