为什么long,int和Integer,Long不能直接转换?

今天测试遇到一个异常,检查半天没有找到问题所在,最后将IOException改为Exception终于把异常捕捉到了,问题就是:

无法将long转化为Integer

看起来只是一个不起眼的问题,但是真正检查却花了半小时,尴尬

(1)首先基本数据类型之间可以强转,如long,int

(2)对象类数据类型,如Integer,String, Long,这个时候基本数据类型和对象数据类型之间的转换就涉及到装箱/拆箱。

如int 和Integer转换,

int a = Integer.parseInt("12"); 

int a = Integer.valueOf("12");

double a = Double.valueOf("12.2");

double a = Double.parseDouble("12.2");

String a = String.valueOf("1234");//这里括号中几乎可以是任何类型

String b= String.valueOf(true);

String c = new Integer(12).toString();//通过包装类的toString()也可以

String d = new Double(2.3).toString();

(3)int和Integer类型转换源码:

从源码可以看出, 当大于intercache缓存中的最小值,同时小于最大值时候,从缓存中取值,否则int转换为Integer类型new 一个Integer对象。

基本数据类型和对象类数据类型转换涉及到拆箱封箱的过程,为什么要用对象数据类型呢?

基本数据类型不支持面向对象编程机制,而对象包装类则符合面向对象编程,如LIst<Integer>,而List<Int>非法的。

 

举例:

1.下面这段代码的输出结果是什么?

答案是

i1=i2  true;

i3=i4 false;

为什么会出现这样的结果?输出结果表明i1和i2指向的是同一个对象,而i3和i4指向的是不同的对象.

只需一看源码便知究竟,下面这段代码是Integer的valueOf方法的具体实现.

在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。

上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。

2.下面这段代码的输出结果是什么?

false
false

 

至于具体为什么,读者可以去查看Double类的valueOf的实现。

  在这里只解释一下为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。

  注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。

     Double、Float的valueOf方法的实现是类似的。

Boolean i11 = false;
Boolean i21 = false;
Boolean i31 = true;
Boolean i41 = true;

System.out.println(i11==i21);
System.out.println(i31==i41);
true
true

3.谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。

  当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:

  1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;

  2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。

Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;

System.out.println(c==d);
System.out.println(e==f);
System.out.println(c==(a+b));
System.out.println(c.equals(a+b));
System.out.println(g==(a+b));
System.out.println(g.equals(a+b));
System.out.println(g.equals(a+h));

true
false
true
true
true
false
true

这里面需要注意的是:当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。明白了这2点之后,上面的输出结果便一目了然。

第一个和第二个输出结果没有什么疑问。第三句由于  a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。而对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较。同理对于后面的也是这样,不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。

 

 

 

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值