【Java 数据结构】包装类 (通俗易懂)

🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!

欢迎志同道合的朋友一起加油喔🦾🦾🦾


目录

一、包装类分类

二、使用包装类的原因

三、包装类的自动拆装箱机制

三、包装类中的缓存机制

(方法区) 整数型常量池

equals方法

四. Integer方法

五. Character方法 



一、包装类分类

基本数据类型包装类型
bytejava.lang.Byte(父类Number)
shortjava.lang.Short(父类Number)
intjava.lang.Integer(父类Number)
longjava.lang.Long(父类Number)
floatjava.lang.Float(父类Number)
doublejava.lang.Double(父类Number)
booleanjava.lang.Boolean(父类Object)
charjava.lang.Character(父类Object)

注意: 8种包装类属于 引用数据类型 

二、使用包装类的原因

Java语言是面向对象的编程语言,而基本数据类型声明的变量并不是对象,为其提供包装类,增强了Java面向对象的性质。

而且,如果只有基本数据类型,使用时是很不方便的,比如,在集合类中,无法将int 、double等类型放进去的,因为集合的容器要求元素是Object类型。

此外,包装类还为基本类型添加了属性和方法,丰富了基本类型的操作。如当我们想知道int取值范围的最小值,我们需要通过运算,如下面所示,但是有了包装类,我们可以直接使用Integer.MAX_VALUE即可。

//求int的最大值
int max = 0;
int flag = 1;
for (int i=0; i<31; i++) {
	max += flag;
	flag = flag << 1;
}
System.out.println(max +"	"+ Integer.MAX_VALUE); //2147483647      2147483647

为什么要保留基本数据类型?

因为Java种创建的对象都是存储在堆里的,使用的时候需要通过栈中的引用,所以常用的基本数据类型,不需要使用new在堆上创建,而是直接在栈内存中存储不创建对象,就会比较高效。

三、包装类的自动拆装箱机制

进行基本类型数据和包装类对象之间的互转时:

使用new关键字或者使用Integer类的valueOf()可以手动转换成包装类。这两个方式是有所区别的,我们下面会说到。 

//创建包装类对象有两种方式:new关键字、valueOf()方法。
Integer num1 = new Integer(1);	//基本数据类型转为包装类
Integer integer = Integer.valueOf(10);//基本数据类型转为包装类
int num2 = num1.intValue();		//包装类型转为基本数据类型
System.out.println(num1 +"	"+ num2);

为了方便使用和性能优化,提供了自动装箱和拆装箱机制(不需要手动转换了)

  • 自动装箱:基本数据类型自动转换成包装类
  • 自动拆箱:包装类自动转换成基本数据类型
//1、包装类中的自动装箱拆箱机制
Integer  num1 = 1;		//自动装箱
int num2 = num1;		//自动拆箱
System.out.println(num1 +"	"+ num2);

当使用jad工具对上面的代码进行反编译时,结果如下:

Integer integer = Integer.valueOf(1);
int i = integer.intValue();
System.out.println((new StringBuilder()).append(integer).append("\t").append(i).toString());

 从反编译可以看出,底层也是调用ValueOf方法帮我们完成的自动装箱!

三、包装类中的缓存机制

前面说到创建包装类对象有两种方式:new关键字、valueOf()方法。我们来看一段代码感受一下它们的区别。

//包装类中的缓存机制
Integer num3 = 10;
Integer num4 = 10;
Integer num5 = new Integer(20);
Integer num6 = new Integer(20);
Integer num7 = 128;
Integer num8 = 128;
System.out.println((num3==num4) +"	"+ num3.equals(num4));
System.out.println((num5==num6) +"	"+ num5.equals(num6));
System.out.println((num7==num8) +"	"+ num7.equals(num8));

运行结果为

为什么会得到这样的运行结果呢?

首先,我们查看Integer的valueOf()方法的源码

在Java中,Integer类使用了一个静态内部类(Static Nested Class),它在首次使用Integer类时被加载。该内部类预先创建了一个包含-128到127之间的所有Integer对象的缓存数组(cache),以优化性能。

当使用Integer.valueOf()方法创建Integer对象时,如果数值在-128到127范围内,方法会直接返回缓存数组中的对应对象,而不会新建对象。这种方法称为“享元模式”,可以节省内存,提高性能。

当使用new关键字创建Integer对象或使用Integer.valueOf()方法创建小于-128或大于127的值时,Java会创建一个新的Integer对象。注意,直接使用new关键字创建对象时,无论数值是否在-128到127范围内,都会新建一个对象,而不是使用缓存中的对象

(方法区) 整数型常量池

java中为了提高程序的执行效率,将 [-128 ~ 127] 之间所有的包装对象提前创建好, 放到了一个方法区的“整数型常量池”当中了。

目的是:只要用这个区间的数据不需要再new了,直接从整数型常量池当中取出来。

//包装类中的缓存机制
Integer num3 = 10;
Integer num4 = 10;
Integer num5 = new Integer(20);
Integer num6 = new Integer(20);
Integer num7 = 128;
Integer num8 = 128;
System.out.println((num3==num4) +"	"+ num3.equals(num4));
System.out.println((num5==num6) +"	"+ num5.equals(num6));
System.out.println((num7==num8) +"	"+ num7.equals(num8));

 由于num3、num4都小于等于127,它们指向的是同一个缓存的Integer对象,所以用==进行比较的结果是true;num5、num6由于使用new关键字指向的是两个不同的新对象,结果为false;num7、num8虽然是采用自动装箱的方式,但执行valueOf()方法的时候,由于不满足条件i >= IntegerCache.low && i <= IntegerCache.high,而同样新建了两个不同的新对象,结果同样是false。

接着,我们再来看看源码中Integer的equals()方法的实现

equals方法

可见equals()方法比较的是Integer对象的值,而不是像==一样比较的是对象是否是同一个对象。所以,当需要比较两个Integer对象的值是否相等时,记住要用equals()方法。用==比较的话由于缓存机制的存在,可能产生一些让人困扰的结果。

此外,在8种包装类型中,有缓存区的有Character、Byte、Short、Integer、Long,而且它们的实现方式基本一样,都是-128到127的缓存范围。Boolean虽然没有缓存区,但是因为只有两个值true、false,所以Boolean在成员变量中就创建了两个相应的对象。没有缓存区的只有Float、Double,之所以没有原因很简单,即便是0到1这么小的范围,浮点数也有无数个,因此,在实际应用中,为这些值创建缓存区不具备现实意义和实用性。

缓存区的存在使得常用的包装类对象可以得到复用,这有利于提升性能。当我们需要创建新对象的时候再new一个,增加了灵活性。

四. Integer方法

方法名作用
static Integer decode(String nm)将String转成Integer
static int compare(int x, int y)比较两个数是否相等;相等返回0;前大后小返回1;后大前小返回-1
static int signum(int i)符号函数;负数返回-1;正数返回1;0返回0
static String toBinaryString(int i)将i转成二进制
static String toHexString(int i)将i转成十六进制
static String toOctalString(int i )将i转成八进制
常用方法
static int parseInt(String s)字符串转int
static Integer valueOf(String s)字符串转Integer
String toString()Integer转String
boolean equals(Object obj)判断两个Integer是否相等
  注意:   Byte、Short、Long、Float、Double、Boolean照葫芦画瓢,方法差不多相同。

代码演示: 

class IntegerTest{
    public static void main(String[] args) {
        Integer d = Integer.decode("123");
        System.out.println(d);//自动拆箱 123

        Integer a = 100;
        Integer b = 100;

        int res1 = Integer.compare(a, b);
        System.out.println(res1);//0
        res1 = Integer.compare(-a, b);
        System.out.println(res1);//-1
        res1 = Integer.compare(a, -b);
        System.out.println(res1);//1

        System.out.println(a.equals(b));//true

        int i = Integer.parseInt("123");
        System.out.println(i);//123

        System.out.println(Integer.signum(-123));//-1
        System.out.println(Integer.signum(123));//1
        System.out.println(Integer.signum(0));//0

        System.out.println(Integer.toBinaryString(10));//1010
        System.out.println(Integer.toOctalString(10));//12
        System.out.println(Integer.toHexString(10));//a

        String s = Integer.toString(123);
        System.out.println(s);//123

        Integer int1 = Integer.valueOf("123");
        System.out.println(int1);//123
    }
}

五. Character方法 

方法名作用
char charValue()将Character转成char
int compareTo(Character anotherCharacter)判断两个Character是否相等;相等返回0;前大后小返回1;后大前小返回-1
常用方法
boolean equals(Object obj)判断两个Character是否相等
String toString()将Character转成String
static boolean isDigit(char ch)判断ch是不是数字
static boolean isLetter(char ch)判断ch是不是字母
static boolean isLetterOrDigit(char ch)判断ch是不是字母或数字
static boolean isLowerCase(char ch)判断ch是不是小写字母
static boolean isUpperCase(char ch)判断ch是不是大写字母
static boolean isSpaceChar(char ch)判断ch是不是空格
static Character valueOf(char c)将char转成Character

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书生-w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值