Java基本数据的包装类以及自动装箱时遇到的问题(从源码角度上来看)

概念

Java语言是一门面向对象的编程语言,但是在Java当中的基本数据类型却是不面对象的,在这个实际的使用的时候是很不方便的,为了解决这个不足,所以在设计类的时候为了每个基本数据类型都设计了一个对应的类进行代表,这样八个和基本数据类型对应的类就通常为包装类。

包装类:(如: Integer、Double等)这些封装类了一个相应的基本数据类型数值,并为其提供了一系列的操作方法。
在这里插入图片描述

在图片中明显的可以看出在当a != null的时候,编译器就给我吗报了错误。

下面来认识一下基本数据类型和包装类之间的对应关系

基本数据类型包装类
byteByte
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean

在这里插入图片描述

对于包装类来讲,这些类的用途主要包含两种:

  1. 作为和基本数据类型对应的类类型存在。
  2. 包含每种基本数据类型的相关属性如最大值、最小值等,以及相关的操作方法等。

经过封装后就可以调用响应的方法来对其进行实现。
在这里插入图片描述

包装类常用的属性方法

以java.lang.Integer为列:

public static final int MAX_VALUE ; 返回int类型的最大值
public static final int MIN_VALUE ; 返回int类型的最小值

构造方法:

Integer(int a);
Integer(String a); 会将String类型转换为int型的
在这里插入图片描述

比较方法:

static int compareTo(Integer a); 返回两个数大小,小了-1 等于0 大于1
boolean equals(Object); 因为是对象的形式,直接==根据存放数据的地址肯定不相等,所以要用equals来调用判断对象内的数据是否相等
int max(int a ,int b); 返回大值
int min(int a , int b); 返回小值

代码演示:

public class Demo01 {
    public static void main(String[] args) {
        Integer a = new Integer(128);
        System.out.println("Integer中最大是: " + a.MAX_VALUE);
        System.out.println("Integer中最小是: " + a.MIN_VALUE);

        // 构造方法
        Integer b = new Integer("10");
        System.out.println("String类型的输出为Integer: " + b);

        //比较方法
        Integer one = new Integer(8);
        Integer two = new Integer(10);
        Integer three = new Integer(10);
        System.out.println("通过compareTo比较8和10的大小结果: " + one.compareTo(two)); // 前<后 --->  -1
        System.out.println("通过compareTo比较10和10的大小结果: " + two.compareTo(three)); // 前=后  --->  0
        System.out.println("通过compareTo比较10和8的大小结果: " + two.compareTo(one));  // 前>后  ---> 1

        System.out.println("通过==来判断10和10是否相等: " + (two == three));
        System.out.println("通过equals来判断10和10是否想等: " + two.equals(three));

        System.out.println("返回8和10的最大值: " + Integer.max(one, two));
        System.out.println("返回8和10的最小值: " + Integer.min(one, two));
    }
}

在这里插入图片描述

static String toBinaryString(int i); 将数字转换为二进制
static String toHexString(int i); 将数字转换为十六进制
static String toOctalString(int i) 将数字转换为八进制

int intValue(); 将Integer类型转换为int型
在这里插入图片描述

static int parseInt(String s); 将String类型转换为int型
在这里插入图片描述

String toString(); 将Integer转换为String类型
在这里插入图片描述

static Integer valueOf(int i); 将int类型转换为Integer类型
在这里插入图片描述

static Integer valueOf(String s); 将String类型装换为Integer类型
在这里插入图片描述

public class Demo02 {
    public static void main(String[] args) {
        System.out.println("30转二进制: " + Integer.toBinaryString(30));
        System.out.println("30转十六进制: " + Integer.toHexString(30));
        System.out.println("30转八进制: " + Integer.toOctalString(30));
        Integer a = new Integer(10);
        int b = a.intValue();  //接受int类型的Integer
        System.out.println("通过intValue将引用类型的 a 数字转为基本数据类型: " + b);

        String st = "10";
        int s = Integer.parseInt(st);
        System.out.println("通过parseInt将String类型的转换为int类型: " + s);

        String y = a.toString();
        System.out.println("通过toString将Integer类型转换为String类型: " + y);


        Integer x = Integer.valueOf(s);
        System.out.println("通过valueOf(int i)将int类型转换为Integer类型: " + x);
        Integer z = Integer.valueOf(st);
        System.out.println("通过valueOf(String s)将String类型转换为Integer类型: " + z);
    }
}

在这里插入图片描述

自动装箱/拆箱

装箱和拆箱 Auto-boxing/unboxing

装箱
自动将基本数据类型转换为包装器类型
装箱的时候自动调用的是Integer的valueOf(int)方法

拆箱
自动将包装类型转换为基本数据类型
拆箱的时候自动调用的是Integer的intValue方法。

在这里插入图片描述

自动装箱遇到的大问题:

运行下面的代码:

public class Demo3 {
    public static void main(String[] args) {
        //因为自动装箱的问题,所以Integer x = 127 ==>Integer x = Integer.valueOf(127)
        Integer x = Integer.valueOf(127);
        Integer y = 127;
        System.out.println(x == y);

        Integer m = new Integer(127);
        Integer n = new Integer(127);
        System.out.println(m == n);

        Integer x1 = 128;
        Integer y1 = 128;
        System.out.println(x1 == y1);

        Integer m1 = new Integer(128);
        Integer n1 = new Integer(128);
        System.out.println(m1 == n1);
    }
}

会遇到这样的问题:
在这里插入图片描述

ou?这是为什么呢?
这。。。都是有原因的。且看我分析一波……

从上面的代码,我们是否可以做出一个大胆的猜想,是不是当自动装箱的时候数的绝对值小于128,就会为true呢?

先了解一个感念:
==这个符号判断的是基本类型的时候比较的就是值,当比较的是引用类型的时候,比较的是地址是否相等

来,让我们看源代码:

先看直接使用构造方法的:
在这里插入图片描述

这个很直接,最后包装成了一个对象,那使用 == 显然两个对象的地址怎么可能相等,那么它的结果必然是false。

来再看自动装箱时调用的方法:
在自动装箱时调用的就是这个valueOf 方法
在这里插入图片描述

为什么会有不同的输入结果,就是这两行代码造成的结果。

点开看这个IntegerCacher方法查看:
在这里插入图片描述

可以看到low值为-127,high值为127
cache值在一开始就创建好了,为常量,保存在缓存当中。

所以在调用valueOf方法的时候,当传入的值大于-127小于127的话,return返回的值是加载好的常量值,当不在这个范围了,才创建Integer对象。

再根据==符号的定义,就能一下子就像明白了。

最后我在用debug方法,验证一下数据创建过程当中对内存的占用:
在这里插入图片描述

我说的就这么多啦,大家有什么分析和交流或建议什么的,欢迎大家评论区讨论。

这是我重读javase基础的一个系列,比起当时初学的时候,现在看问题多个高度,理解什么也相对轻松一点。比较学过时间也比较长了,有什么不对,希望大家指出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值