死磕Java之Java数据类型的来龙去脉

一、数据类型分类

数据类型可以分为基本数据类型(8个)引用数据类型(3个)
具体可以参考如下图所示:
在这里插入图片描述

二、基本数据类型

基本数据类型就是咱们常说的8大基本数据类型:byte、short、int、long、float、double、char、boolean
在这里插入图片描述
整型:

名称 占用字节数 占用位数 数据表示范围
byte 1 1 * 8 = 8 -27 ~ 2 7- 1
short 2 2 * 8 = 16 -215 ~ 2 15 - 1
int 4 4 * 8 = 32 -231 ~ 2 31 - 1
long 8 8 * 8 = 64 -263 ~ 2 63 - 1

浮点型:

名称 占用字节数 占用位数 数据表示范围
float 4 4 * 8 = 32 -231 ~ 2 31- 1
double 8 8 * 8 = 64 -263 ~ 2 63 - 1

字符型:

名称 占用字节数 占用位数 数据表示范围
char 2 2 * 8 = 16 -215 ~ 2 15- 1

布尔型:

名称 占用字节数 占用位数 数据表示范围
boolean true和false

三、你真的了解包装类吗?

(一)面试题:Java已经有了int等基本类型了,为什么还需要包装类?

答:
Java是面向对象的语言,所有的类型都是引用类型
Object类是所有类的祖先,即Object类是所有类的父类。
但是基本数据类型如:int、double等并不是引用类型,也不是继承自Object,所以int、double等并不符合面向对象的特征。所以Java需要这样的包装类来使其具备面向对象的完整性。

(二)基本数据类型与包装类的对应关系

基本数据类型与包装类的对应关系表:

基本数据类型 包装类
byte Byte
boolean Boolean
short Short
char Character
int Integer
long Long
float Float
double Double

(三)包装类的自动拆箱与装箱

1、理解:(拿int和Integer来说)

  • 什么是拆箱:拆箱就是把Integer转换成int;
  • 什么是装箱:装箱就是把int转换成Integer;

2、自动装箱
例如:Integer a = 100;

相当于执行了:

Integer a = Integer.valueOf(100);

3、自动拆箱

Integer a = 100; //装箱,实际上执行了:Integer a = Integer.valueOf(100);
int b = a;//拆箱,实际上执行了:int b = a;
System.out.println(b+1);//自动拆箱,进行运算时也会自动拆箱

4、自动装箱有性能损耗,在循环中应避免

Integer sum = 0;
for(int i=0; i<100; i++){
sum+=i;
}

上面的代码 sum+=i 可以看成 sum = sum + i,但是这个操作会把 sum 先拆箱,然后相加后再装箱。等价于:Integer sum = new Integer(sum.intValue() + i;);

5、包装类的比较
==符号是进行引用的比较。这个比较不会引起自动拆箱。

Integer a=128;
Integer b=128;
System.out.println("a==b : " + (a == b)); //false,不会自动拆箱,比较的是引用,不是同一个地址引用
System.out.println("a>b : " + (a > b)); // false,会自动拆箱
System.out.println("a<b : " + (a < b)); // false,会自动拆箱

但是,由于 JVM 会缓存-128 到 127 的 Integer 对象,所以当包装类的值在-128 到 127 的范围内,判等比较的是同一个引用。

Integer a=127;
Integer b=127;
System.out.println("a==b : " + (a == b)); //true,不会自动拆箱,比较的是引用,不是同一个地址引用
System.out.println("a>b : " + (a > b)); // false,会自动拆箱
System.out.println("a<b : " + (a < b)); // false,会自动拆箱

那么对于 128 这样数字的包装类,判等该怎么做?很简单,手动拆箱,或者用 equals 方法。

equals 方法会拆箱后,根据基本类型比较,所以比较的是两者值的大小。

Integer a=128;
Integer b=128;
System.out.println("a.intValue()==b.intValue() : " +(a.intValue()==b.intValue())); //手动拆箱,true
System.out.println("a.equals(b) : " + (a.equals(b))); //true

6、包装类型和基本类型用==比较的时,会发生拆箱

Integer b=128;
int c=128;
long d=128;
System.out.println("b==c : " + (b == c)); //true ,b自动拆箱
System.out.println("b==d : " + (b == d));//true b自动拆箱,并且会自动提升类型

当包装类和基本类型用 equals 比较时,会出现问题了。

System.out.println("b.equals(c) : " + (b.equals(c))); //true
System.out.println("b.equals(d) : " + (b.equals(d))); //false

发生了什么?看一下 equals 方法源码就知道了

public boolean equals(Object obj) {
if (obj instanceof Integer) {
	return value == ((Integer)obj).intValue();
}
	return false;
}

基本类型会被自动装箱,放入 equals 方法,然后第一步会判等是否是 Integer 的类型,那么 long d 会被装箱成 Long,所以类型就不一致,直接不进行比较,返回 false。而 int c 会装箱成 Integer 而类型一致,可以继续比较下去。

(四)包装类总结

  • 包装类是一个对象,基本类型不是。
  • 包装类和基本类型可以互相转换,转换的过程称之为装箱拆箱,可以手动转换,也可自动转换。
  • 包装类比较大小的时候有很多坑,比如:
    1、==比较引用,Integer 类型只有在-128 到 127 的范围内,才会持有同一个引用。
    2、equals 方法会先比较类型是否一致,不一致直接 false。
  • 最佳的操作实践是,比较大小的时候,统一先手动拆箱,然后再比较值。

可以参考:Java 为什么需要包装类,如何使用包装类?

发布了145 篇原创文章 · 获赞 157 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_17623363/article/details/104914159
今日推荐