a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 107|回复: 1

[专业语言] JAVA认证:小心使用boxing

[复制链接]
发表于 2012-8-4 12:44:44 | 显示全部楼层 |阅读模式
 自动装箱与拆箱的功能事实上是编译器来帮您的忙,编译器在编译时期依您所编写的语法,决定是否进行装箱或拆箱动作。例如:Integer i = 100;   相当于编译器自动为您作以下的语法编译:Integer i = new Integer(100);! L$ {: E6 V: q+ g
  所以自动装箱与拆箱的功能是所谓的“编译器蜜糖”(Compiler Sugar),虽然使用这个功能很方便,但在程序运行阶段您得了解Java的语义。例如下面的程序是可以通过编译的:
* y3 E+ M' |* d9 e# }% [  Integer i = null;
% y: O7 w% o4 E  z2 r6 s  int j = i;4 ]) u  G2 s* R3 s$ n8 r
  这样的语法在编译时期是合法的,但是在运行时期会有错误,因为这种写法相当于:  r& _# I% x/ P& ]
  Integer i = null;
$ a) E; s: O  \. `; @  int j = i.intValue();, C0 L+ Z! P0 O( U& H, D
  null表示i没有参考至任何的对象实体,它可以合法地指定给对象参考名称。由于实际上i并没有参考至任何的对象,所以也就不可能操作intValue()方法,这样上面的写法在运行时会出现NullPointerException错误。5 j+ Z* Z, v. p9 [, }( a
  自动装箱、拆箱的功能提供了方便性,但隐藏了一些细节,所以必须小心。再来看范例4.6,您认为结果是什么呢?8 t; t2 W" d+ H& U
  范例4.6 AutoBoxDemo2.java 8 f9 h' M% c2 l/ v* s' o
  public class AutoBoxDemo2 {
5 j3 H" d* k& h' e1 L  public static void main(String[] args) { 5 ~% b6 V$ L' u! ^% y
  Integer i1 = 100;
9 J+ X7 w$ Q, S: M  Integer i2 = 100;
- W+ E, @9 o; f9 C- b7 H# M0 J  if (i1 == i2) - B8 p0 m$ A7 H* U5 b; a2 d
  System.out.println("i1 == i2"); " k0 a) H' b- r9 [8 H
  else 4 p, F; d  Q/ u0 ^
  System.out.println("i1 != i2");
5 D& Q; y" J1 W% t+ e  } $ O$ `7 U2 e0 P5 V  P: v
9 O* z3 j3 ^% K. w' f0 k) r
  }
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:44:45 | 显示全部楼层

JAVA认证:小心使用boxing

</p>  从自动装箱与拆箱的机制来看,可能会觉得结果是显示i1 == i2,您是对的。那么范例4.7的这个程序,您觉得结果是什么?
4 [1 j; p* @0 l) R  范例4.7 AutoBoxDemo3.java * b& \9 g7 |) n0 p6 r7 V  O4 u6 G& q
' N, T2 e6 A+ _$ N0 G5 E/ h" `8 f! m
  public class AutoBoxDemo3 {
% i  i3 f& |" c* [: U* X, P5 U  public static void main(String[] args) { + e/ b: y2 b% c( N7 _7 q8 \' d
  Integer i1 = 200;
( B1 R+ ?' d2 u$ a  Integer i2 = 200; + J" x& Z$ @. a- r
  if (i1 == i2)
; _* V2 C2 l. \. A5 v) c  System.out.println("i1 == i2"); % p7 R/ h1 q/ g
  else
0 D0 E7 K9 t7 q0 x3 @; W* o% x; C* e6 }  System.out.println("i1 != i2"); : [+ S4 F$ U  n6 X- q; h5 W
  } + W4 N& }2 z( U* O8 J7 G
  }
9 |  C* z! [/ V! R( t  {' ^. l  结果是显示i1 != i2,这有些令人惊讶,两个范例语法完全一样,只不过改个数值而已,结果却相反。
) k1 W! c- H% C; g2 g! e  其实这与==运算符的比较有关,在第3章中介绍过==是用来比较两个基本数据类型的变量值是否相等,事实上==也用于判断两个对象引用名称是否参考至同一个对象。! U8 ~% ]7 n# \, _5 [9 N7 S( D
  在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,所以范例4.6中使用==进行比较时,i1 与 i2实际上参考至同一个对象。如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象,所以范例4.7使用==进行比较时,i1与i2参考的是不同的对象。
4 R) R5 V+ m, ^1 @  所以不要过分依赖自动装箱与拆箱,您还是必须知道基本数据类型与对象的差异。范例4.7最好还是依正规的方式来写,而不是依赖编译器蜜糖(Compiler Sugar)。例如范例4.7必须改写为范例4.8才是正确的。
3 L0 t# Y8 i) Z0 I: l# k3 m1 |  范例4.8 AutoBoxDemo4.java   N# U5 R" A) r% K
  public class AutoBoxDemo4 { 6 [7 R5 D( ]9 q
  public static void main(String[] args) {
0 \; j8 h9 \1 a6 I/ l  Integer i1 = 200; 4 J' c/ I$ x, k+ E
  Integer i2 = 200; 5 _  [5 A; V5 W. I
  if (i1.equals(i2)) ' J2 N  Y& d" M# b# D; \7 n, V  h
  System.out.println("i1 == i2"); 8 `0 b* K  x! b
  else
3 z. |9 L, i8 U  System.out.println("i1 != i2");
8 x3 k2 c+ ]3 _* Z- i  } 1 r$ D' @/ Q! }- y
  } 2 s$ {2 P: r2 M. m- h
  结果这次是显示i1 == i2。使用这样的写法,相信也会比较放心一些,对于这些方便但隐藏细节的功能到底要不要用呢?基本上只有一个原则:如果您不确定就不要用。 8 T: L) `: F( w. M
  建议新手不要使用自动装箱、拆箱的语法,在这里说明这个功能是为了要完整性介绍Java SE 6的特性,新手入门的话,最好在对对象有较深入了解之后,再来使用这个功能。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-6 20:44 , Processed in 0.293389 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表