专栏首页Java 温故知新「JAVA」Java 一切皆对象,基本类型也没下,包装类自动拆装箱来相助

「JAVA」Java 一切皆对象,基本类型也没下,包装类自动拆装箱来相助

包装类,拆箱、装箱——一切皆对象

为何要包装类

  1. 在面向对象中,”一切皆对象”,但基本数据类型的特殊存在不太符合这一理念,面向对象面向得并不纯粹,因为基本类型变量并不是对象;
  2. 涉及进制间的转换的算法,数据类型间的基本操作;如果都要我们来实现,那工作量就太大了;
  3. Java的集合框架并不支持基本数据类型的存储,只支持对象存储;

故此,针对Java基本数据类型封装了包装类,每一个基本类型都有一个对应的包装类,以下是详情:

基本数据类型的包装类

八大基本数据类型的包装类都使用final修饰,都是最终类,都不能被继承。

// Byte
public final class Byte extends Number implements Comparable<Byte> {}

// Character
public final class Character implements java.io.Serializable,                       
                                         Comparable<Character> {}
                                         
// Short
public final class Short extends Number implements Comparable<Short> {}

// Integer
public final class Integer extends Number implements Comparable<Integer> {}

// Long
public final class Long extends Number implements Comparable<Long> {}

// Float
public final class Float extends Number implements Comparable<Float> {}

// Double 
public final class Double extends Number implements Comparable<Double> {}

// Boolean
public final class Boolean implements java.io.Serializable,                          
                                         Comparable<Boolean> {}

拆箱和装箱

装箱:把基本类型数据转成对应的包装类对象。

方式一:

Integer i = Integer.value(13);

方式二:

Integer i = new Integer(13);

拆箱:把包装类对象转成对应的基本数据类型数据。

int value = i.intValue();

自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)

在Java 5之前的版本中,基本数据类型和包装类之间的转换是需要手动进行的,但Sun公司从Java5开始提供了的自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)操作 ;

  • 自动装箱:可以把一个基本类型变量直接赋给对应的包装类型变量。
Integer i = 13;
  • 自动拆箱:允许把包装类对象直接赋给对应的基本数据类型变量。
Integer i = new Integer(13);
Int j = i;

自动装箱和自动拆箱,也是一个语法糖/编译器级别新特性,在底层依然是手动装箱、拆箱操作;但是在装箱操作中使用的是Integer.valueOf()方法,而不是直接new Integer();其他的几个包装类也是如此,装箱操作中使用的是各自的valueOf()方法。

自动装箱和自动拆箱的反编译效果

switch 对包装类的支持

switch支持的基本数据类型:byte,short,char,int;也支持对应的包装类。因为在底层,switch中会对包装类做手动拆箱操作。

switch 对包装类的支持

考虑下面的代码:

Object obj = 17;

在上述代码语句中有如下的操作:

  1. 自动装箱:Integer i = 17;
  2. 引用的自动类型转换,把子类对象赋给父类变量:Object obj = i; 因为Object类是所有Java类的父类;因此,Object可以接受一切数据类型的值;Object数组:Object[],该数组可以存储一切数据类型。
Object[] arr = {"A",12,3.14,true};// 这是完全可行的

包装类的常用操作方法(以Integer为例):

1. 包装类中的常量:

  • MAX_VALUE :最大值
  • MIN_VALUE :最小值
  • SIZE :变量在内存中存储数据占多少位
  • TYPE :对应的基本类型

2. 包装类的构造器:创建包装类对象,

/** Integer 构造器源码 **/
// 接收int类型数据构建Integer对象
public Integer(int value){    
    this.value = value;
}

// 接受字符串数据构建Integer对象
public Integer(String s) throws NumberFormatException {    
    this.value =parseInt(s,10);
}

其他的几个包装类型也是这样的规律,具体实现查看源码即可。

3. 基本类型和包装类型的转换(装箱和拆箱)

装箱:

Integer i1 =new Integer(13);      // 方式一,每次都会创建新对象,不推荐
Integer i2 = Integer.valueOf(13); // 方式二,推荐,底层使用了缓存。

拆箱:

int val = i1.intValue();

4.String和基本类型/包装类型之间的转换操作

把String转换为包装类类型:

// 方式1:包装类.valueOf(String str):
Integer i = Integer.valueOf(“13”);

// 方式2:new 包装类(String str):
Integer i= new Integer(“13”);

把包装类对象转换为String:

String str = 对象.toString(); 
// 不止包装类对象,其他任何对象都可以使用toString()转换;

把基本数据类型转换为String:

String str = 13 + "";

把String转换为基本数据类型:

// parseXxx(String s) : xxx表示8大基本数据类型,如:

String input = ”12345”;
int value = Integer.parseInt(input);

5. 对于Boolean来说,无论是使用new Boolean(“”); 还是Boolean.valueOf(“”), 只有使用true/TRUE会被认为是true,其他都是false。

Boolean b1 =newBoolean("true");// true
Boolean b1 =newBoolean("TRUE");// true
Boolean b1 =newBoolean("sjsj");// false

包装类中的缓存设计

在包装类中提供了缓存设计,会对一定范围内的数据作缓存,如果数据在范围内,会优先从缓存中取数据,超出范围才会创建新对象;

  • Byte、Short、Integer、Long:缓存[-128,127]区间的数据;
  • Character:缓存[0,127]区间的数据;

包装类中的缓存设计,也称为享元模式。缓存设计会在包装类中的valueOf()方法中实现,所以才会推荐使用valueOf()方法来实现拆箱操作,如下是Integer类的valueOf()源码:

valueOf()

再查看缓存实现细节:

IntegerCache 源码

通过查看源码可知,JVM会对-128 到 127之间的做缓存,如果你的变量值在这个范围内,就会优先从缓存中取数据,否则就会创建新对象。当然这个缓存区间也是可以设置的。

那么以下这个例子就可以解释了:

public static void main(String[] args){
    Integer i1 = Integer.valueOf(13);
    Integer i2 = Integer.valueOf(13);
    System.out.println(i1 == i2);
    // 输出为true。因为13在[-128, 127]之间,但是并没有创建新对象

    Integer i3 = Integer.valueOf(129);
    Integer i4 = Integer.valueOf(129);
    System.out.println(i3 == i4);  // 输出为false, 因为129不在[-128, 127]之间,  
    // 是使用new Integer()创建了新对象,故比较为false
    
    Integer i5 =129;
    Integer i6 =129;
    System.out.println(i5 == i6);// 输出为false
    System.out.println(i5.equals(i6));
    // 输出为true,建议:如果对象包装类对象的值作比较,  
    // 应选用包装类的equals方法。
}

我们再来看Integer的equals方法的实现源码:

Integer的equals方法

可以发现,包装类在比较时会将包装类型拆箱为基本数据类型,并使用==做比较。

包装类型和基本数据类型的区别

包装类型和基本数据类型的区别(以Integer与int的区别为例):

1. 默认值:

  • int的默认值是0。
  • Integer的默认值为null。Integer既可以表示null,又可以表示0。

2. 包装类中提供了该类型相关的很多算法操作方法:

static String toBinaryString(int i); // 把十进制转换为二进制
static String toOctalString(int i);  // 把十进制转换为八进制
static String toHexString(int i);    // 把十进制转换为十六进制

3. 在集合框架中,只能存储对象类型,不能存储基本数据类型值。

4. Integer和int并不是相同的数据类型,尽管值是相同的。Integer是一个类,可以实例化为对象,但int只是一个基本数据类型。

5.在JVM中,基本类型变量存储在栈中的,而包装类型对象存放于堆中。

其实,包装类就是把基本数据类对象化,包装类是基本数据类型的超集;在开发中,建议成员变量优先使用包装类型,局部变量优先考虑基本数据类型。

完结。老夫虽不正经,但老夫一身的才华

本文分享自微信公众号 - 老夫不正经(laofu_ss),作者:老夫不正经

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 「JAVA」Java面向对象之面向接口编程,细节都在这里了

    比如,显示器中封装了很多电子元器件,这些元器件连接在一起为显示器的正常共工作提供支持,那显示器如何与外界的其他设备(如电脑主机、外放音响、耳机等设备)通信交互呢...

    老夫编程说
  • 多态的灵魂,面向接口的程序设计,这才是你该懂得的接口

    比如,显示器中封装了很多电子元器件,这些元器件连接在一起为显示器的正常共工作提供支持,那显示器如何与外界的其他设备(如电脑主机、外放音响、耳机等设备)通信交互呢...

    老夫编程说
  • 「JAVA」变量、表达式、数据类型、数据类型转换详解

    变量: 表示存储空间,可用来存放某一类型(整数、小数...)的数据,没有固定值,变量值是可变的,可重复使用,也可以用来存储某种类型的未知数据。

    老夫编程说
  • 谈谈一些有趣的CSS题目(十七)-- 不可思议的颜色混合模式 mix-blend-mode

    Sb_Coco
  • WIN10系统Java环境变量设置(修正版)

    接下来,我们要先设置『JAVA_HOME』,当然了,没设置过的电脑是没有这个变量的,点击『新建』即可!

    BessCroft
  • 3个案例说决策树应用:提高数十倍效率,还能帮你精准找到另一半

    一个单身狗写下这个标题我是心虚!!! 很早就听说过决策树算法的威力,很早之前就做过决策树模型的分析和应用,这次就来看看决策树算法的操作和实际运用。 首先,要先理...

    沉默的白面书生
  • leetcode 907子数组的最小值之和题解

    思路分析:这里是求出子数组的最小值之和,其实并不需要知道这个子数组的除了最大值之外其它数值。通过对实例的分析,我们可以得出一个17运用公式如何算出来:(1+0-...

    flytam
  • 机器学习实战 - 读书笔记(03) - 决策树

    绿巨人
  • Multidex记录三:源码解析

    为什么要用记录呢,因为我从开始接触Android时我们的项目就在65535的边缘。不久Google就出了multidex的解决方案。我们也已经接入multide...

    静默加载
  • Java中Integer的详解

    在Java中有int和integer两种类型,简单的说Integer是int的引用类型,但是这个引用的类型比较特殊,下面看几个demo:

    付威

扫码关注云+社区

领取腾讯云代金券