A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 fantacyleo 于 2015-4-16 11:50 编辑

【审核老师您好,我是申请安卓66期的李灏。因为没有做实名认证,在此表明一下我的身份】

已看完老毕的基础视频,这两天正在攻坚张老师的高新视频。还没看高新时就目睹论坛上每天大量的帖子反映高新视频难,于是决定把学习过程中的心得体会拿出来跟大家分享,欢迎大家关注。
前两篇心得不涉及论坛上热门的反射、代理、泛型,而是J2SE 5.0引入的两个语法特性:自动装箱/拆箱和可变参数,因为这两个语法特性是前24个视频中唯一让我按暂停键去查资料的知识点。本篇先说说自动装箱/拆箱,下一篇说可变参数。

对于自动拆箱/装箱,我觉得要掌握三点:
1. 概念
基本类型 boolean byte charshort int long float double null
引用类型 Boolean Byte Character Short Integer Long Float Double NullType

自动拆箱/装箱就是指由Java编译器自动完成上述前8种基本类型与其相对应的引用类型之间的【互相】转换,以及null-->引用类型的【单向】转换[1]。其中常见的是前八种,比如:
  1. // 自动装箱
  2. Integer i = 3;
  3. ArrayList<Integer> al = new ArrayList<Integer>();
  4. al.add(4);
  5. // 自动拆箱
  6. Integer j = new Integer(4);
  7. int k = j;
  8. System.out.print(3 + j);
复制代码

至于第9种null-->NullType的转换,是出于三目运算符? :赋值的语法需要[2],没必要深究。另外,不存在NullType-->null的拆箱转换,对null类型拆箱将抛出空指针异常(NullPointerException)

2. 享元设计模式
对于:
  • true
  • false
  • byte类型
  • 位于闭区间[0x0, 0x7f]中的char
  • 位于闭区间[-128, 127]中的short或int

其装箱后的对象将被缓存起来,如果程序运行过程中再遇到相同的值要装箱为对象,则不再创建新对象,而是直接指向已缓存的对象,这就是享元设计模式。例如:
  1. Character c1 = 'a';
  2. Character c2 = 'a';
  3. System.out.println(c1 == c2); // true

  4. Character c3 = '\u107f';
  5. Character c4 = '\u107f';
  6. System.out.println(c3 == c4); // false
复制代码


要特别注意的是,享元特性【仅针对自动装箱】的情形,如果一个对象不是自动装箱生成的,就不具备享元特性,所以:
  1. Character c1 = 'a';
  2. Character c2 = new Character('a');
  3. System.out.println(c1 == c2); // false
复制代码


3. 自动拆箱/装箱的局限性,或者说它失效的情形:
  1. Integer i = 'a'; // 编译错误!!!
  2. ArrayList<Integer> al = new ArrayList<Integer>();
  3. al.add('a'); //  编译错误!!!
  4. short s = new Integer(1); // 编译错误!!!
  5. 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

评分

参与人数 1技术分 +1 收起 理由
格子、 + 1 总结的不错

查看全部评分

11 个回复

倒序浏览
总结的不错                                                                                    
回复 使用道具 举报
哥们 感觉你的基础好扎实啊。怎么现在还没面试吗?
回复 使用道具 举报
恩,总结的不错,谢谢分享!
回复 使用道具 举报
学习了..
回复 使用道具 举报
谢谢楼主的分享!
回复 使用道具 举报
总结的很好~!
回复 使用道具 举报
可以可以 ,挺好的。
回复 使用道具 举报
总结的不错,楼主很细心学习啊,赞一个
回复 使用道具 举报
还好啊,只是还没有看到这里来的。
回复 使用道具 举报
总结的太好了!
回复 使用道具 举报
哇.这总结 .留个印
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马