包装类与自动拆箱与装箱

这一生的挚爱 提交于 2019-12-09 13:12:42
Java是面向对象的语言,但并不是“纯面向对象”的,因为我们经常用到的基本数据类型就不是对象。但是我们在实际应用中经常需要将基本数据转化为对象,以便于操作。比如:将基本数据类型存储到Object[]数组或集合操作中等等。
Object o = {1024,"张三"};
其中的1024在我们现在看来是一个基本数据类型int,但是数组是Object类型的,int不是一个Object的子类,它是基本数据类型的,其实这中间有个装箱的过程,将int包装成一个对象
 
基本数据类型
包装类
byte
Byte
boolean
Boolean
short
Short
char
Character
int
Integer
long
Long
float
Float
double
Double
 
包装类Integer、Byte、Double等都继承了一个类Number,里面提供了各种方法,例如ValueOf等等 
 1 package com.testwrappedclass;
 2 public class TestWrappedClass {
 3        public static void main(String[] args) {
 4              //基本类型转为包装类
 5              int a =3;
 6 //           Integer a_integer = new Integer(a);//在version9是官方不再建议这样书写
 7              Integer a_integer = Integer.valueOf(a);
 8              double b = 4.0;
 9              Double b_double = Double.valueOf(b);
10              
11              //包装类转成基本类型
12              int a_int = a_integer.intValue();
13              double b_doub = b_double.doubleValue();
14              
15              //字符串转为包装类
16              String s="2315";
17              Integer s2int = Integer.valueOf(s);//其实是调用了parseInt(String  s)方法
18              
19              //包装类转为字符串
20              String string = s2int.toString();
21        }
22 }
也就是说,转为包装类(Integer/Double/....)都用.valueOf()方法,转为基本类型(int/double/...)用int/double/xxxValue(),转为字符串类型用toString()
 
 
自动拆箱与装箱
自动拆箱与装箱是由编译器compiler完成的,自动拆箱即由包装类"直接"转为基本类型;自动装箱即由基本类型"直接"转为包装类。如:
//自动拆箱
Integer w = Integer.valueOf(3);
int a =w;//实际上,编译器会自动加上w.intValue()方法
//自动装箱
Integer r = a;//实际上,编译器会自动加上r.valueOf(a)方法
再看下面的这个例子:
Integer p =null;
int c =p;
若运行,编译器会报
        Exception in thread "main" java.lang.NullPointerException
NullPointerException 错误是说企图调用一个空对象中的方法。但是我们没看到有调用p的方法啊?其实是有的,自动拆箱调用了Integer的intValue()方法。
 
包装类的缓冲池问题
//包装类中的缓冲池的问题
             Integer int3 = Integer.valueOf(1234);
             Integer int4 = Integer.valueOf(1234);
             😀System.out.println(int3==int4);
             🐶System.out.println(int3.equals(int4));
             
             Integer int1 = Integer.valueOf(-128);
             Integer int2 = Integer.valueOf(-128);
             😘System.out.println(int1==int2);
             🐷System.out.println(int1.equals(int2));
 
##########输出结果#################
false
true
true
true
在😀处:因为int3和int4是两个不同的对象,所以输出为false
在🐶处:因为int3和int4中的内容相等,所以输出为true
在😘处:为啥int1和int2是不同的对象,但是输出为true呢??原来在包装类中的valueOf方法有这样一个机制,先看下它的源代码:
@HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)//IntegerCache.low=-128,IntegerCache.high=127
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
而IntegerCache是这样的:
private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];
        static {
            // high value may be configured by property
            int h = 127;
。。。。。
原来,我们在使用valueOf方法时,会自动创建一个Integer类型的数组cache,cache数组中的每个对象是-128~127各个数形成的包装类。如果我们的整型包装类对象的值在-128~127之间,则不再创建新的对象,而是直接到cache数组找这个对象。如上例int1和int2都是-128值,那它们对应的对象就是cache数组中值为-128的对象,所以为true
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!