Java拆装箱问题

自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值自动地转换成对应的对象类型。

什么是自动装箱和拆箱

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型byte,short,char,int,long,float,double和boolean对应的封装类为Byte,Short,Character,Integer,Long,Float,Double,Boolean。

自动装箱拆箱要点

  • 自动装箱时编译器调用valueOf将原始类型值转换成对象,同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成原始类型值

自动装箱的弊端

自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

1
2
3
4
Integer sum = 0;
 for(int i=1000; i<5000; i++){
   sum+=i;
}

上面的代码sum+=i可以看成sum = sum + i,但是+这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其内部变化如下

1
2
int result = sum.intValue() + i;
Integer sum = new Integer(result);

由于我们这里声明的sum为Integer类型,在上面的循环中会创建将近4000个无用的Integer对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。

问题一:装箱拆箱举例

  1. public class Demo{  
  2.     public static void main(String[] args) {  
  3.         Integer i = 10;  
  4.         int n =i;  
  5.     }  
  6. }  
装箱通过:

Integer localInteger = Integer.valueOf(10); 


拆箱通过:

  1. int i = localInteger.intValue();  

问题二、八种基本类型的包装类中的常量池与否


[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class Main {  
  2.     public static void main(String[] args) {  
  3.            
  4.         Integer i1 = 100;  
  5.         Integer i2 = 100;  
  6.         Integer i3 = 200;  
  7.         Integer i4 = 200;  
  8.            
  9.         System.out.println(i1==i2);  
  10.         System.out.println(i3==i4);  
  11.     }  
  12. }  
答案是:true,false。

原因:

看看valueOf的源码:-128到128之外,则新建对象。(注释:java1.7源码)

假如面试官只是为了考点是否深入其实到这儿就结束了。碰到一个较真的面试官,可能会一并问这个问题。

示例二:

  1. public class Demo{  
  2.     public static void main(String[] args) {  
  3.            
  4.         Double i1 = 100.0;  
  5.         Double i2 = 100.0;  
  6.         Double i3 = 200.0;  
  7.         Double i4 = 200.0;  
  8.            
  9.         System.out.println(i1==i2);  
  10.         System.out.println(i3==i4);  
  11.     }  
  12. }  

答案:false,false。

长得几乎一摸一样,只是类型由Integer变成了Double。

是不是想问为什么设计者这么变态?因为常量数量有限,可以通过常量数组去处理加快速度,而类似double,float也用-127到128范围枚举的话就太多了。

总结记住以下:(记少不记多,记住第二句!)

Integer、Short、Byte、Character、Long、Boolean有常量池。

double,float没有常量池。

问题三、衍生的String的问题:

ava中的数据类型,可分为两类: 
1.基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean 
  他们之间的比较,应用双等号(==),比较的是他们的值。 
2.复合数据类型(类) 
  当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
  对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。


  1. public class Demo{  
  2.     public static void main(String[] args) {  
  3.   
  4.         String s1 = new String("hello");  
  5.         String s2 = new String("hello");  
  6.         System.out.println(s1 == s2);//输出false  
  7.         System.out.println(s1.equals(s2));//输出true  
  8.         String s3 = "hello";  
  9.         String s4 = "hello";  
  10.         System.out.println(s3 == s4);//输出true  
  11.         System.out.println(s3.equals(s4));//输出true  
  12.     }  
  13. }  
   
   
1 public class TestString { 2   public static void main(String[] args) { 3 String s1 = " Monday " ; 4 String s2 = " Monday " ; 5 if (s1 == s2)  6 { 7 System.out.println( " s1 == s2 " );} 8 else { 9 System.out.println( " s1 != s2 " );} 10 } 11 }
复制代码
编译并运行程序,输出:s1 == s2:说明:s1 与 s2 引用同一个 String 对象 -- "Monday"!






























  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值