本帖最后由 fantacyleo 于 2015-4-16 11:50 编辑
【审核老师您好,我是申请安卓66期的李灏。因为没有做实名认证,在此表明一下我的身份】
已看完老毕的基础视频,这两天正在攻坚张老师的高新视频。还没看高新时就目睹论坛上每天大量的帖子反映高新视频难,于是决定把学习过程中的心得体会拿出来跟大家分享,欢迎大家关注。
前两篇心得不涉及论坛上热门的反射、代理、泛型,而是J2SE 5.0引入的两个语法特性:自动装箱/拆箱和可变参数,因为这两个语法特性是前24个视频中唯一让我按暂停键去查资料的知识点。本篇先说说自动装箱/拆箱,下一篇说可变参数。
对于自动拆箱/装箱,我觉得要掌握三点:
1. 概念
基本类型 | boolean | byte | char | short | int | long | float | double | null | 引用类型 | Boolean | Byte | Character | Short | Integer | Long | Float | Double | NullType |
自动拆箱/装箱就是指由Java编译器自动完成上述前8种基本类型与其相对应的引用类型之间的【互相】转换,以及null-->引用类型的【单向】转换[1]。其中常见的是前八种,比如:
- // 自动装箱
- Integer i = 3;
- ArrayList<Integer> al = new ArrayList<Integer>();
- al.add(4);
- // 自动拆箱
- Integer j = new Integer(4);
- int k = j;
- System.out.print(3 + j);
复制代码
至于第9种null-->NullType的转换,是出于三目运算符? :赋值的语法需要[2],没必要深究。另外,不存在NullType-->null的拆箱转换,对null类型拆箱将抛出空指针异常(NullPointerException)
2. 享元设计模式
对于:
- true
- false
- byte类型
- 位于闭区间[0x0, 0x7f]中的char
- 位于闭区间[-128, 127]中的short或int
其装箱后的对象将被缓存起来,如果程序运行过程中再遇到相同的值要装箱为对象,则不再创建新对象,而是直接指向已缓存的对象,这就是享元设计模式。例如:
- Character c1 = 'a';
- Character c2 = 'a';
- System.out.println(c1 == c2); // true
- Character c3 = '\u107f';
- Character c4 = '\u107f';
- System.out.println(c3 == c4); // false
复制代码
要特别注意的是,享元特性【仅针对自动装箱】的情形,如果一个对象不是自动装箱生成的,就不具备享元特性,所以:
- Character c1 = 'a';
- Character c2 = new Character('a');
- System.out.println(c1 == c2); // false
复制代码
3. 自动拆箱/装箱的局限性,或者说它失效的情形:
- Integer i = 'a'; // 编译错误!!!
- ArrayList<Integer> al = new ArrayList<Integer>();
- al.add('a'); // 编译错误!!!
- short s = new Integer(1); // 编译错误!!!
- short s1 = 1; // 正确
复制代码
自动拆箱/装箱是不能和类型向上转换/向下转换共存的。也就是说,一条赋值语句中,执行了自动拆箱/装箱,就不会再进行类型向上转换/向下转换;执行了类型向上转换/向下转换,就不会再进行自动拆箱/装箱。
说到底,这个局限性来源于Java编译器进行赋值类型转换的规则(类型转换有一些特殊规则,参见我的另一篇帖子。):
Java编译器要求赋值语句=两边的类型必须相同,如果不同,则尝试进行如下【之一】的转换[3]:
- 基本类型向上转换,即byte-->short-->int-->long-->float-->double
- 引用类型基于继承体系的向上转换,比如任意对象-->Object Dog-->Animal
- 自动拆箱
- 自动装箱
注意关键词:之一。因此,想类型提升后再装箱,比如Integer i = 'a'; 是办不到的。只能拆成两步: int i = 'a'; Integer i1 = i; 搞清楚这个局限性非常重要,因为它可以帮助你避免可变参数函数重载时可能出现的错误,我将在下一篇说到这个问题。
[1] http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7
[2] http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25
[3] http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.2
|