19.包装类

一.概述:

  • 包装类就是把基本数据类型转换为对象(引用数据类型)


二.理解包装类:

  • 对于基本数据类型,在变量中记录的是真实的数据值,例如上述图片中定义了一个基本数据类型的整型变量i为10,那么变量i真实的数据值就是10,内存中变量记录的也是10

  • 以int为例,int对应的包装类为Integer类,可以认为在Java中是用Integer类来描述整数,在Integer类里有一个属性值value,value用来记录整数的数据值

  • 创建包装类的对象也是用new关键字去创建,比如此时创建了一个Integer类对象即Integer n=new Integer(10);->该对象名为n,类型为Integer类,传入的属性值为10,这是时会在栈里创建一个变量n,类型是Integer类,由于此时是new的对象,所以就会在堆里再开辟一个小空间记录成员变量value,成员变量value就记录n的属性值10,而栈里的n记录的是成员变量value在堆内的地址值

  • 包装类的本质就是创建了一个对象,对象中记录对应的数据值->包装类:用一个对象,把基本数据类型给包起来


三.为什么要学习包装类:

在Java中,万物皆对象,由于多态的存在,所有的对象都是Object类的子类,意味着所有对象都可以被Object类接收,

对于基本数据类型,如果没有包装类,假设此时传递了一个整数,就会导致Object类无法接收,程序就会有局限性,

而且在集合中,是不能存储基本数据类型的,只能存储对象即引用数据类型,所以要想往集合中存储基本数据类型,就必须用基本数据类型的包装类。


四.基本数据类型对应的包装类:


五.以int型的包装类Integer为例:其他类似

1.获取Integer对象的方式(了解):

在JDK5以前,如果要获取包装类的对象,需要通过new一个构造方法,或者通过静态方法valueOf来获取:

对于valueOf方法:

1.形参包括字符串的:

2.形参为整数的:

上述图片中第1069行代码里的[]是数组的含义,所以cache表示一个数组,而且是Integer型。

形参为整型的valueOf方法:首先会对参数i进行判断,

如果参数i在if里的范围,就会执行if语句从cache数组中获取已经创建好的Integer对象并返回,

如果参数i不在if里的范围时才会new一个对象。

由此可以得出,如果传入的参数i符合if语句里的范围中,就不会自己new一个对象,而是从cache数组中获取一个Integer对象并返回。

对于if语句里的范围i >= IntegerCache.low && i <= IntegerCache.high,i是参数,IntegerCache是方法,low和high是IntegerCache里的变量,

if语句中的IntegerCache方法,包含变量low(值为-128)、变量high以及数组cache

->对于变量high,第1014行代码中有一块静态代码块,首先定义了一个变量h,值为127,然后在第1028行中把h的值即127赋值给了high,所以if语句里的范围是[-128,127]即byte类型的取值范围,

->因此传入的参数i如果在[-128,127]这个范围内,就会执行第1035行代码,其中首先会创建一个Integer类型的数组c,该数组的长度是size,size的值为 (high - low) + 1(在第1032行代码),加1是因为在[-128,127]之间还有一个0,加1是为了把0也计入,(high - low) + 1=(127-(-128))+1=(127+128)+1=255+1=256,所以有256个数据,数组c的长度也是256

->在第1038行还有一个遍历c数组for循环,循环体即第1039行代码中继续操作数组c,给数组c里的每一个值进行赋值,通过创建Integer对象赋值,传入j++,j的初始值是low即-128(第1037行代码)

->所以就是会把low创建一个Integer对象,放到数组c中(一开始j为-128,放到c数组的0索引,j++是先赋值再++,因此就是先把j的值赋给数组,再++进行下一轮的操作,所以一开始j以-128的值赋值给c数组的0索引,再++进行第二轮操作。所以-127给c数组的1索引,以此类推)

->综上所述,Integer类在底层首先会把[-128,127]之间的所有数据都创建好Integer对象 ,然后全部放到cache数组中,当使用参数为整型的valueOf方法获取到对象时,首先会判断参数是否在[-128,127]范围内,如果在,不会创建新的Integer对象,而是从cache数组中获取已经创建好的Integer对象并返回,只有不在[-128,127]范围内,才会new一个Integer对象。

代码演示:
package com.itheima.a03integerdemo;
​
public class A01_IntegerDemo1 {
    public static void main(String[] args) {
        //1.利用构造方法获取Integer的对象(JDK5以前的方式)
        Integer i1=new Integer(1);
        Integer i2=new Integer("1");
        System.out.println(i1); //运行结果为1,i1就是整数对应的包装类
        System.out.println(i2); //运行结果为1,i2就是整数对应的包装类
        /*虽然利用构造方法获取Integer的对象在JDK5以及JDK5之后的版本中已废弃,
          但是依旧能够在JDK5以及JDK5之后的版本中利用构造方法获取Integer的对象,
          尽管此时idea会报编译时异常,但代码可以运行*/
​
        /* -------------------------------------------------------------------------------------------------------------------------------------------------*/
​
        //2.利用静态方法获取Integer的对象(JDK5以前的方式)
        Integer i3 = Integer.valueOf(123); //表示此时获取的是一个包装类,包装类里记录的数据是整数123
        Integer i4 = Integer.valueOf("123"); //表示此时获取的是一个包装类,包装类里记录的数据是字符串123
        Integer i5 = Integer.valueOf("123",8); //表示此时获取的是一个包装类,包装类里记录的数据是字符串123,8代表前面的字符串123是8进制下的
        System.out.println(i3); //运行结果为123
        System.out.println(i4); //运行结果为123
        System.out.println(i5); //运行结果为83,这里不是123,是因为i5已经指定了字符串123是在8进制下的数据,那么在打印时就会把123转化为8进制,再把结果以10进制输出打印,所以结果为83
​
        /* -------------------------------------------------------------------------------------------------------------------------------------------------*/
​
        //3.上述获取Integer对象的两种方式的区别(需要掌握)->以下的==号比的是地址值,如果结果为true,表示前后是同一个对象,如果结果为false,表示前后不是同一个对象
        /*底层原理:
           在实际开发中,-128到127之间的整数数据用的比较多,
           如果每次使用-128到127之间的整数数据都是new一个对象,那么会浪费很多内存,
           所以,Java会提前把-128到127之间的每一个整数数据都创建好对象,
           如果要用到-128到127之间的整数数据就不会创建新的对象了,而是返回已经创建好的对象 */
        Integer i6=Integer.valueOf(127);
        Integer i7=Integer.valueOf(127);
        System.out.println(i6==i7); //运行结果为true
        /* 对于参数为整型的valueOf方法,
           如果传入的参数范围在[-128,127]内,那么最终创建的对象就是同一个对象,地址值也就一样,
           所以本例中传入127,最终表示同一个对象,地址值也就一样,因此运行结果为true */
​
        Integer i8=Integer.valueOf(128);
        Integer i9=Integer.valueOf(128);
        System.out.println(i8==i9); //运行结果为false
        /* 对于参数为整型的valueOf方法,
           如果传入的参数范围在[-128,127]内,那么最终创建的对象就是同一个对象,地址值也就一样,
           但本例中传入的是128,超出了[-128,127],因此最终表示不同的对象,地址值也就不一样,因此运行结果为false */
​
        //new关键字:
        Integer i10=new Integer(127);
        Integer i11=new Integer(127);
        System.out.println(i10==i11);
        /* 运行结果为false,
           原因:对于i10和i11,都使用了关键字new,
                在Java中,每一次new都是创建了一个新的对象,所以i10和i11的地址值不一样,
                又因为此时i10和i11都表示地址值,因此结果为false */
​
        Integer i12=new Integer(128);
        Integer i13=new Integer(128);
        System.out.println(i12==i13);
        /* 运行结果为false,
           原因:对于i12和i13,都使用了关键字new,
                在Java中,每一次new都是创建了一个新的对象,所以i12和i13的地址值不一样,
                又因为此时i12和i13都表示地址值,因此结果为false */
    }
}
​

2.Integer对象的计算:

代码演示:

package com.itheima.a03integerdemo;
​
public class A02_IntegerDemo2 {
    public static void main(String[] args) {
        //在以前包装类如何进行计算
        Integer i1=new Integer(1);
        Integer i2=new Integer(2);
​
        //需求:需要把i1和i2两个数据进行相加得到结果3
        /* 注:i1和i2此时都是包装类对象即引用数据类型,包装类对象之间是不能直接进行计算的,
           如果想要进行计算,步骤如下:
            1.把包装类对象进行拆箱,也就是把包装类对象变为基本数据类型
            2.变为基本数据类型后就可以相加了
            3.把得到的结果再次进行装箱(装箱的目的就是变回包装类对象)  */
        //intValue方法可以把Integer包装类对象进行拆箱为int型
        int result = i1.intValue() + i2.intValue();
        //把result进行装箱:new一个Integer对象,参数传入result,就可以把int型的result装箱为Integer包装类
        Integer i3=new Integer(result);
        System.out.println(i3); //运行结果为3
    }
}

3.自动装箱和自动拆箱:

代码演示:

package com.itheima.a03integerdemo;
​
public class A03_IntegerDemo3 {
    public static void main(String[] args) {
        //在JDK5的时候提出了一个机制:自动装箱和自动拆箱
        /* 自动装箱:把基本数据类型自动地变成其对应的包装类对象
           自动拆箱:把包装类对象自动地变成其对象的基本数据类型  */
​
        //在底层,int型还是会去自动调用静态方法valueOf进行自动装箱得到一个Integer对象,只不过这个操作不需要我们自己去实现了
        //10是基本数据类型,但最终是Integer类,说明进行了自动装箱
        Integer i1 = 10;
​
        Integer i2 = new Integer(10);
        //把i2进行自动拆箱,最终为int型
        int i=i2;
​
        //在JDK5以后,int和Integer可以看作是同一个东西,因为在底层可以自动转化。
​
        /*---------------------------------------计算---------------------------------------*/
        /* 有了自动装箱和自动拆箱的机制,
           Integer类可以直接赋值整数(把int型整数自动装箱为Integer类),
           然后可以直接计算(计算时会把Integer类自动拆箱为int型整数),
           最终得出结果(得出的结果是把int型整数自动装箱得来的Integer类)*/
        Integer a=1;
        Integer b=2;
        Integer c=a+b;
        System.out.println(c); //运行结果为3
    }
}

4.总结:

5.Integer类的成员方法:

  • 上述图片中前三个得到进制的方法的返回值都是String型,而不是整型,原因:1.比如二进制可能有01010101,但如果是整型,整数中0是不能做开头的,这就出现了局限性;2.整型中long型和int型是有长度限制的,以int型为例,int型最多只能取到21个亿,也就是int类型最多只能有10位,而二进制可能有30多位、40多位和50多位,所以int型可能装不下,long型同理,只有String型可以,这也就是为什么返回String型

  • 上述图片的四个方法都是静态的,因此都可以用类名.方法名进行调用

  • 上述图片中前三个得到进制的方法常出现在源码中,如Object类里的toString方法,就用到了toHexString方法:意思是把对象的地址值转成十六进制的形式后进行返回

代码演示:

package com.itheima.a03integerdemo;
​
public class A04_IntegerDemo4 {
    public static void main(String[] args) {
        //1.把整数转成二进制
        String str1 = Integer.toBinaryString(100);
        System.out.println(str1); //运行结果为1100100
​
        //2.把整数转成八进制
        String str2 = Integer.toOctalString(100);
        System.out.println(str2); //运行结果为144
​
        //3.把整数转成十六进制
        String str3 = Integer.toHexString(100);
        System.out.println(str3); //运行结果为64
​
        //4.将字符串类型的整数转成int类型的整数
        /* Java是一种强类型语言:强类型语言指的是每种数据在Java中都有各自的数据类型,
           在计算的时候,如果不是同一种数据类型,是无法直接计算的。
           只有数据的类型相同时,才可以进行计算。
           比如想让字符串"123"和整数123相加,此时想要得到的结果是246,
           但字符串和数字进行计算时,是把数字拼接到字符串上,此时的结果为123123,
           要想达到目的,就需要把字符串"123"变为整数才能和后面的数字123相加,
           因此就需要把字符串"123"变为整数 */
        int i = Integer.parseInt("123");
        System.out.println(i); //运行结果为123
        System.out.println(i+123); //运行结果为246
    }
}
​

parseInt方法的细节演示:

public class Main2 {
    public static void main(String[] args) {
        //细节1:在类型转换的时候,括号中的参数只能是数字,不能是其他,否则代码会报错
        //细节2:在8种包装类中,除了Character类外都有对应的parseXxx的方法,进行类型转换,转换为对应的基本数据类型
        String str="true";
​
        /*需求:把str的值的类型变为布尔类型*/
        boolean b = Boolean.parseBoolean(str); //如果str是"true",结果为true,除此之外都是false
        System.out.println(b); //运行结果为true
    }
}

6.键盘录入改进:

package com.itheima.a03integerdemo;
​
import java.util.Scanner;
​
public class A05_IntegerDemo5 {
    public static void main(String[] args) {
        //键盘录入
        Scanner sc=new Scanner(System.in);
        /*弊端:
          当我们在使用next、nextInt、nextDouble等接收数据的时候,如果遇到空格、回车、制表符的时候就会停止接收,
          如果此时想要录入的是123 123,由于有一个空格,那么此时只能接收到空格前面的数据即123,显然少接收一部分。
          平时写代码时,想要接收的是一整行的数据
            ->约定:以后想要键盘录入,无论什么类型,统一使用nextLine,nextLine方法会接收一整行的数据,把空格、制表符全部会接收,
                   nextLine方法遇到回车才停止,nextLine方法返回的是String型,
                   但如果要多次使用键盘录入,就不要使用nextLine方法了 */
        System.out.println("请输入一个字符串");
        String s = sc.nextLine(); //录入123 123
        System.out.println(s); //运行结果为123 123
​
    }
}
package com.itheima.a03integerdemo;
​
import java.util.Scanner;
​
public class A05_IntegerDemo5 {
    public static void main(String[] args) {
        //键盘录入
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入一个字符串");
        String line = sc.next();//录入123 123
        System.out.println(line); //运行结果为123,因为next在接收时遇到空格、回车、制表符会停止接收,所以只接收到空格前的123
​
        /*
        //如果此时要求录入的结果是整型,只需要类型转换即可
        int i = Integer.parseInt(line);
        */
​
        //如果此时要求录入的结果是小数即浮点型,只需要类型转换即可
        double v = Double.parseDouble(line);
        System.out.println(v); //运行结果为123.0
        System.out.println(v+1); //运行结果为124.0
    }
}
​

六.Integer类概述以及Integer类里的所有方法概述:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值