【Java SE基础专题 三】装箱拆箱问题详解

简介: 【Java SE基础专题 三】装箱拆箱问题详解

本篇blog主要介绍装箱拆箱问题,怎么实现的,有什么问题?首先 通过一道例题分析看几个基本函数表示什么:

设有下面两个赋值语句:
a = Integer.parseInt("1024");
b = Integer.valueOf("1024").intValue();
下述说法正确的是()
A,  a是整数类型变量,b是整数类对象。
B,  a是整数类对象,b是整数类型变量。
C,  a和b都是整数类对象并且它们的值相等。
D,  a和b都是整数类型变量并且它们的值相等。

涉及的函数表示意义如下:

  • intValue()是把Integer对象类型变成int的基础数据类型
  • parseInt()是把String 变成int的基础数据类型
  • ValueOf()是把String 转化成Integer对象类型;(现在JDK版本支持自动装箱拆箱了。)

本题:parseInt得到的是基础数据类型int,valueof得到的是装箱数据类型Integer,然后再通过valueInt转换成int,所以选择D

基础类型和包装类型

每种基础类型都会对应一种包装类型,它们的对应关系如下:

类型转换

那么基础类型和包装类型是如何进行类型转换的呢?

下面赋值语句中正确的是()
A  double d=5.3e12; //科学计数表示方法,需要注意的是表示范围是否越界
B  float f=11.1;  //double-->float 精度丢失,需要强转
C  int i=0.0; //double-->int 精度丢失,需要强转
D  Double oD=3

在不加任何后缀情况下,整型默认为 int 浮点默认为 double,对于D选项,3是int类型,Double是包装器类型无法自动转型,所以应该表示为

double d= 3; 自动转型,int-->double
Double d = (double) 3; 强转+自动装箱

比较操作

通过一道例题来分析以下==equals的相关比较操作

Integer i = 42; //装箱
Long l = 42l;
Double d = 42.0;

下面为true的是

A   (i == l)
B   (i == d)
C   (l == d)
D   i.equals(d)
E   d.equals(l)
F   i.equals(l)
G  l.equals(42L)

依据三条原则来进行分析判断

  • 1,对于值类型来说比较大小就可以了,对于引用类型来说来说==比较的是地址,equals比较的是类型+值(重写过,否则引用地址不同也不能相等)
  • 2,包装类的“==”运算在遇到基本类型的情况下会自动拆箱
  • 3,包装类的equals()方法不处理数据转型

分析上题,ABC选项,都是包装类,引用类型,比较的是地址,地址不同,编译错误,DEF选项,因为equals方法不处理数据转型,所以还是比较类型,所以是错的,G是先对42L装箱,然后比较类型是否相同,如果相同,再比较值大小是否相同,显然都相同

==比较

基本型和基本型封装型进行“==”运算符的比较。

自动拆箱

基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;

int a = 220;
Integer b = 220;
System.out.println(a==b);//true

两个基本型的==操作就是比值(不管是不是同类型的基本型),但两个封装型的会先判断类型,类型不同报错,并且即使是同一类型也为false,因为引用指向的地址不同

Integer特殊的值范围

两个Integer类型(Integer.valueOf)进行“==”比较, 如果其值在**-128至127** ,那么返回true,否则返回false, 这跟Integer.valueOf()的缓冲对象有关。

Integer c=3;
Integer h=3;
Integer e=321;
Integer f=321;
System.out.println(c==h);//true
System.out.println(e==f);//false

这个方法就是返回一个 Integer 对象,只是在返回之前,看作了一个判断,判断当前 i 的值是否在 [-128,127] 区别,且 IntegerCache 中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新的对象。 创建新对象后当然就是不同的引用了。源代码如下:

public static Integer valueOf(inti) {
      assertIntegerCache.high>=127;
      if(i >= IntegerCache.low&& i <= IntegerCache.high)
             return  IntegerCache.cache[i+ (-IntegerCache.low)];
      return  new  Integer(i); }

Integer非特殊情况

但无论如何,Integer与new Integer不会相等。不会经历拆箱过程

package test;
/**
 * @author 田茂林
 * @data 2017年9月6日 下午9:46:42
 */
public class TestFinally {
      public static void main(String[] args) {
        Integer i= 57;
        Integer l = new Integer(57);
        if(i==l){
          System.out.println("true");
        }else{
          System.out.println("false");   //输出为false
        }
    }
  }

equals比较

两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true

Integer a=1;
Integer b=2;
Integer c=3;
System.out.println(c.equals(a+b));//true

自动装箱

基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行比较

int i=1;
int j = 2;
Integer c=3;
System.out.println(c.equals(i+j));//true
I==L

基本型不能调用equals()方法,否则编译会报错

综合举例

看下边这样一道题进行分析。

package test;
/**
 * @author 田茂林
 * @data 2017年9月6日 下午9:46:42
 */
public class TestFinally {
      public static  void add(Byte b)
      {
          b = b++;
      }
      public static void main(String[] args) {
          Byte a = 127;
          Byte b = 127;
          add(++a);  //自动拆箱
          System.out.print(a + " ");
          add(b);
          System.out.print(b + "");
    }
  }

运行结果

-128 127

public void add(Byte b){ b=b++; } 这里涉及java的自动装箱/自动拆箱(AutoBoxing/UnBoxing) Byte的首字母为大写,是类,看似是引用传递,但是在add函数内实现++操作,会自动拆箱成byte值传递类型,所以add函数还是不能实现自增功能。也就是说add函数只是个摆设,没有任何作用

  • add(++a);,Byte类型值大小为-128~127之间。 add(++a);这里++a会越界,a的值变为-128
  • add(b),没有变化,还是127

以上就是装箱拆箱的全部内容理解,可以看的出Java对equals有了重写,对于操作符==没有重写

  • ==:它的作⽤是判断两个对象的地址是不是相等。即,判断两个对象是不是同⼀个对象(基本数据类型⽐较的是值,引⽤数据类型⽐较的是内存地址
  • equals(): 它的作⽤也是判断两个对象是否相等。但它⼀般有两种使⽤情况:
  • 类没有覆盖 equals() ⽅法。则通过 equals() ⽐较该类的两个对象时,等价于通过“==”⽐较这两个对象。
  • 类覆盖了 equals() ⽅法。⼀般,我们都覆盖 equals() ⽅法来⽐较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)

结合装箱拆箱以及比较的实现来理解更加深刻

相关文章
|
7月前
|
存储 Java 编译器
【Java SE语法篇】7.面向对象——类和对象
【Java SE语法篇】7.面向对象——类和对象
【Java SE语法篇】7.面向对象——类和对象
|
7月前
|
存储 Java
【Java SE语法篇】3.运算符
【Java SE语法篇】3.运算符
|
7月前
|
存储 Oracle Java
【Java SE语法篇】2.数据类型和变量
【Java SE语法篇】2.数据类型和变量
|
7月前
|
Java API
Java基础知识:什么是Java平台,包括Java SE,Java EE和Java ME?
Java基础知识:什么是Java平台,包括Java SE,Java EE和Java ME?
176 2
|
3月前
|
Oracle Java 关系型数据库
Java(TM) Platform SE binary 已停止工作”的解决方法
Java(TM) Platform SE binary 已停止工作”的解决方法
274 2
|
7月前
|
Java
<Java SE> 5道递归计算,创建数组,数组遍历,JVM内存分配...
<Java SE> 5道递归计算,创建数组,数组遍历,JVM内存分配
73 2
|
7月前
|
Java
<Java SE> 数组详解大全(附带练习题).一维数组、二维数组、数组拷贝、数组遍历...
<Java SE> 数组详解大全(附带练习题).一维数组、二维数组、数组拷贝、数组遍历
64 0
|
7月前
|
Java 开发框架 XML
JDK、JRE、Java SE、Java EE和Java ME有什么区别?
JDK、JRE、Java SE、Java EE和Java ME有什么区别?
|
7月前
|
Java 索引
Java SE ____二维数组
Java SE ____二维数组
|
7月前
|
分布式计算 安全 Java
Java的三大体系架构:深入剖析Java的三大体系架构,包括Java SE、Java ME和Java EE等
Java的三大体系架构:深入剖析Java的三大体系架构,包括Java SE、Java ME和Java EE等
164 1