java实型_深入理解java基本数据类型

深入理解java数据类型

java是一种强类型语言,这就意味着必须为每一个声明变量声明一种类型。在java中,一共有8种数据类型,其中4种整型,2种浮点类型,1种字符类型和一种表示真值的boolean类型。

1. 整型

整型用于表示没有小数部分的整数部分,java提供了4中整型,如下表所示:

类 型

存储大小

取值范围

int

4字节

-2^31 ~ 2^31 - 1

short

2字节

-2^15 ~ 2^15 - 1

long

8字节

-2^63 ~ 2^63 - 1

byte

1字节

-2^7 ~ 2^7 - 1

但是java是一门面向对象的语言,所以对于基本类型java也有其包装类型:Integer,Short,Long,Byte.

自动装箱与自动拆箱

为了使基本数据类型灵活转变,java采用了自动装箱与自动拆箱。如下所示:

Integer i = 9; // 装箱

int a = i; // 拆箱

装箱就是自动把基本类型转化为包装器类型,拆箱就是自动把包装器类型转化为基本数据类型。

那么java是怎么实现自动装箱和自动拆箱的呢?我们反编译一下:

public static void main(java.lang.String[]);

Code:

0: bipush 9

2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

5: astore_1

6: aload_1

7: invokevirtual #3 // Method java/lang/Integer.intValue:()I

10: istore_2

11: return

从反编译的指令中可以看出自动装箱是调用了valueof方法,而拆箱是调用了intValue方法,本着探究的精神再来看看源码:

public static Integer valueOf(int i) {

if (i >= IntegerCache.low && i <= IntegerCache.high) // 判断是否在Integer缓存区内

return IntegerCache.cache[i + (-IntegerCache.low)];

return new Integer(i);

}

显然这里返回了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

// 翻译一下,就是high的值可以由属性或者参数配置

int h = 127; // 默认是 127

// 下面就是检测是否修改了high的配置

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.

}

}

// 如果未修改,直接赋值

high = h;

// 将区间[-128,127]的数值存入缓存数据

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

int j = low;

for(int k = 0; k < cache.length; k++)

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

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

assert IntegerCache.high >= 127;

}

看过源码我们知道装箱的原理,也了解到Integer里的缓存机制,所以推出一个常见的题目,那就是Integer大小的比较:

for (int i = -200; i <= 200; i++){

Integer a = i;

Integer b = i;

System.out.println("a = " + a + ", b = " + b + ", a == b: " + (a == b));

}

答案也很显然了,相信你早就知道了,就是在区间[-128, 127]的值比较都为true,其他都为false。当然只有在装箱情况下的比较才会这样,其他的如:

int a = 1, int b = 1或者Integer a = new Integer(1), Integer b = new Integer(1)都遵循一般情况分别为true和false;所以,由此可以推出Long,

Character等也同理,但是这缓存机制对浮点类型并不适用,你想想从1.0缓存到2.0有多少个小数?无数个!那么为什么要采用缓存机制呢?既然是缓存,那大概是为了避免每次取数都要new一个对象,减少损耗。而且确实int类型使用最多,这样每次在使用时都是重复使用同一个对象。

java整型对java跨平台的支持:

为了实现“一次编译,到处运行”的理想,java整型的范围与运行java的机器是无关的,这就解决了软件从一个平台移植到另一个平台的诸多问题。不会出现软件在32位机器运行良好,而在16位机器运行就出现问题,所以每一种类型的取值范围都是固定的。

2.浮点类型

浮点类型表示有小数部分的数值,java有两种浮点类型,如下所示:

类 型

存储大小

取值范围

float

4字节

大约±3.40282346638528860e+38(有效数7位)

double

8字节

大约 ±1.79769313486231570e+308 (有效数15位)

(注:取值范围依据根据 IEEE 754 浮点“双精度格式”位布局,返回指定浮点值的表示形式,并保留 NaN 值。 第 63 位(掩码 0x8000000000000000L 选定的位)表示浮点数的符号。第 62-52 位(掩码 0x7ff0000000000000L 选定的位)表示指数。第 51-0 位(掩码 0x000fffffffffffffL 选定的位)表示浮点数的有效数字(有时也称为尾数))

浮点数值不适用于有舍入误差的金融计算中,例如:

···

System.out.println(2.0 - 1.1);

···

结果会是

0.8999999999999999

那么为什么不是0.9呢?那是因为浮点数值用二进制表示,而二进制系统无法精确表示1/10。所以要进行精确运算时,最好使用BigDecimal类

public static void main(String[] args) {

BigDecimal a = new BigDecimal("2.0");

BigDecimal b = new BigDecimal("1.1");

System.out.println(a.subtract(b));

}

结果

0.9

3.总结

装箱是自动把基本数据类型转化为包装器类型,拆箱是自动把包装器类型转化为基本数据类型。

整型以及char类型在自动装箱且数值在[-128, 127] 时,会返回缓存数组中相应的值而不是new一个对象

在进行精确运算时不要使用浮点类型,而要使用BigDecimal类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值