java装箱内存分配_深入理解Java之装箱与拆箱

本文详细介绍了Java中的数据类型,包括值类型与引用类型的区别,并深入探讨了自动转换和强制转换。接着,文章重点讲解了Java的装箱与拆箱概念,包括装箱的实现方式(通过valueOf方法),拆箱的实现(通过xxxValue方法)。同时提醒注意点,如大量使用自动拆装箱可能影响性能,重载方法中可能导致的问题,以及缓存值问题。最后,文章提到了包装类的常量池,不同包装类的常量池范围也有所不同。
摘要由CSDN通过智能技术生成

一、Java数据类型

1、在说装箱与拆箱之前,先说一下Java的基本数据类型,Java从数据类型上可以划分为值类型与引用类型,值类型是四类八种,分别是:

整数型:byte̵,short̵,int̵,long

浮点型:float,double

字符型:char

布尔型:boolean

数据类型

内存

默认值

包装类

byte

8位

0

Byte

short

16位

0

short

int

32位

0

Integer

long

64位

0L或0l

Long

float

32位

0.0F或0.0f

Float

double

64位

0.0D或0.0d

Double

char

16位

\u0000

Character

boolean

8位

flase

Boolean

2、引用类型:

数组

类(class)

接口(Interface)

枚举(enum)

2fcb2ce32cd2ff0727ba62a8ecd02858.png

3、值类型与引用类型的区别

1.  从概念方面上来说:

值类型:变量名指向具体的值

引用类型:变量名指向数据对象的内存地址

2.  从内存构建方面上来说:

值类型:变量在声明之后,Java就会立刻分配给它内存空间

引用类型:它以特殊的方式(类似C指针)指向对象实体,这类变量声明时不会分配内存,只是存储

3.  从使用方面上来说:

值类型:使用时需要赋具体值,判断时用 ” == “号

引用类型:使用时可以赋null,判断时使用 equals 方法

二、Java数据类型转换

1、自动转换

定义:程序在执行过程中“悄然”进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换

优先关系:按从低到高的顺序转换。不同类型数据间的优先   关系如下:

低--------------------------------------------->高

byte,short,char-> int -> long -> float -> double

转换规则:

运算中,不同类型的数据先转化为同一类型,然后进行运算

操作数1类型

操作数2类型

转换后的类型

byte、short、char

int

int

byte、short、char、int

long

long

byte、short、char、int、long

float

float

byte、short、char、int、long、float

double

double

2、强制转换

定义:强制类型转换则必须在代码中声明,转换顺序不受限制

格式:在需要转型的数据前加上“( )”,然后在括号内加入需要转化的数据类型

结果:精度可能会丢失,也可能更加精确

int x;

double y;

x= (int)3.14 + (int)5.20  //精度丢失

y= (double)x + (double)8  //精度提升

输出:x=8;y=16.0

三、Java之装箱与拆箱

1、包装类

Java是面向对象语言,号称万事万物皆对象,因此,8种基本数据类型有了对应的类,这就是包装类

2、什么是装箱与拆箱

装箱:将值类型装换成引用类型的过程

拆箱:将引用类型转换成值类型的过程

自动装箱:

intx=3;

Integer y=x;  //int -->Integer,Integery=x<==>Integery=Integer.valueOf(x)

自动拆箱:

Integerx=newInteger(5);

int y=x;  //Integer -->int,inty=x<==>inty=x.intValue()

3、装箱和拆箱是如何实现的

装箱过程是通过调用包装器的valueOf方法实现的

拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)

4、注意点:

大量使用自动拆装箱会使性能降低,还会造成大量的内存消耗

在重载方法中,可能出现问题

Listlist=newArrayList<>();

Integer x,y,z;

x=1;y=2;z=4;

list.add(x);list.add(y);list.add(z);

list.remove(2);

b4aa6cd41e2c2978ba9ea2983f44fd56.png

在上面这段代码中ArrayList.remove方法有两个重载方法,那么list.remove(2)是调用了哪个方法,remove掉的是值为2的对象,还是remove了index为2,值为4的那个对象呢?

在这种情况下,编译器不会进行自动拆装箱,所以调用的是remove(int index),index为2值为4的这个Integer对象会被remove.

如果要调用 remove(Object o)的方法,应该这么写 list.remove(y)

3.  缓存值问题

案例解析:

Integeri1=100;

Integer i2=100;

Integer i3=200;

Integer i4=200;

System.out.println(i1==i2);

System.out.println(i3==i4);

Output: true false

观察源码:

Intteger.valueOf方法

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i<= IntegerCache.high)

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;

String integerCacheHighPropValue=

sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");

if (integerCacheHighPropValue != null) {

try {

int i=parseInt(integerCacheHighPropValue);

i=Math.max(i, 127);

// Maximum array size is Integer.MAX_VALUE

h=Math.min(i, Integer.MAX_VALUE - (-low) -1);

} catch( NumberFormatException nfe) {

// If the property cannot be parsed into an int, ignore it.

}

}

hhigh= h;

cache=newInteger[(high - low) + 1];

int j=low;

for(int k=0; k

cache[k] = new Integer(j++);

// range [-128, 127] must be interned (JLS7 5.1.7)

assert IntegerCache.high >= 127;

}

private IntegerCache() {}

}

从源码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象

Byte、Short、Integer、Long四种包装类默认创建了数值为[-128,127]的相应类型的缓存数据,但是超出此范围仍会创建新的对象。

Character默认会创建[0,127]的响应类型的缓存数据

两种浮点型没有实现常量池技术,在某个范围内的整型数值的个数是有限的,而浮点数却不是

包装类

常量池

常量池范围

Byte

存在

[-128,127]

Short

存在

[-128,127]

Integer

存在

[-128,127]

Long

存在

[-128,127]

Character

存在

[0,127]

Float

不存在

Double

不存在

注意点:

当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)

对于包装器类型,equals方法并不会进行类型转换

算术运算会触发装箱与拆箱过程

【责任编辑:庞桂玉 TEL:(010)68476606】

点赞 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值