数据类型
1.基本数据类型、引用数据类型
在java中数据类型主要可以分成基本数据类型和引用数据类型。
(1)八大基本数据类型:(‘|’后面是每种数据类型占的bit位数,也就是二进制位数)
- 整数型:byte short int long | 8 16 32 64
- 浮点型:float double | 32 64
- 字符型:char | 16
- 布尔型:boolean | 8
每个基本数据类型都有一个对应的包装类。
其中,布尔型理论只需要1个bit即可满足条件,但我们可以操作的最小单元是1个byte,所以布尔型是8个bit。
(2)引用数据类型:所有的类(包括上面的包装类),数组,接口。(3种)
例如:String、int[]
2.二者区别
- 存储机制:
基本数据类型存储在栈区里面,直接存储值的二进制数。
引用数据类型,比如说类A创建了一个对象a,这个对象a的信息、数据、方法等都会在堆区申请一块区域来存储;这个a其实是引用名,存储在栈区里,它只存储这个对象的引用地址,也就是指向堆中的存储位置。
- 比较:
如果是用等号比较的话,基本数据类型比较栈中的值,引用数据类型比较存的引用地址。例:
int a = 100;
int b = 100;
System.out.println(a==b);
Integer ia = 100;
Integer ib = 100;
System.out.println(ia==ib);
第一个a == b,a和b都是基本数据类型,所以直接比较的是a和b的值,输出true。第二个ia==ib,ia和ib都是引用数据类型,比较的是他们的引用地址,因为有常量池的原因(在后面会讲),ia和ib的引用地址是一样的,所以也是输出true。
3.几个问题
- 问题一:
int a=100;
double b=100.0;
System.out.println(a==b);//true
这是两个基本数据类型,比较存在栈里的值,所以相等,输出true。
- 问题二:
(1)首先解释一下装箱和拆箱。对于基本类型的包装类,例如int的包装类Integer,类里面有个属性int value,也就是存储整型类对象的值,装箱操作如下:
//装箱
Integer ia = 200;
Integer ia = new Integer(200);
//这两句话是等价的,都是让对象ia的value = 200
//而且如果用第二个语句,编译器会给一个警告“不必要的装箱 'new Integer(200)'”
下面是拆箱,也就是可以直接取出value:
// 拆箱
int ina = ia;
int ina = ia.intValue();
//两句话等价,第二句会给警告
//编译器同样会给一个警告“不必要的拆箱 'ia.intValue()'”
(2)问题:
Integer ia = 100;
Integer ib = 100;
System.out.println(ia==ib);//比较地址
Integer ic = 200;
Integer id = 200;
System.out.println(ic==id);//比较地址
System.out.println(ic.equals(id));//比较value
第一个输出true,第二个输出false,第三个输出true。这是四个引用数据类型,是比较他们的引用地址,但为什么第一个和第二个有区别呢? 这里就要说到前面说的常量池了。Integer 在内存的堆区中拥有一个常量池,是一个byte大小,8位二进制,所以常量池可以存的数的范围是 -128 – 127。如果创建的Integer对象,它们的value值在这个范围内,那么它们引用地址都是相同的,所以也就出现了第一个输出是true的情况。
- 问题三:
// 字符串常量池
String str1 ="ABC"; // 第一次定义的字符串对象会在常量池中创建一个
String str2 ="ABC";// 后来同内容字符串延用这个地址
System.out.println(str1==str2);//输出true
String str3 =new String("ABC");
System.out.println(str1==str3);//输出false
两次输出结果分别是true,false。字符串同样也是如此,同样拥有一个常量池,这个常量池会存第一次创建的字符串,如果后来创建新的字符串对象的内容和常量池的一样,那么他们的引用地址就相同。但如果像str3这样用new 已经重新在堆区申请了一片区域,那么引用地址就会不同。
本文到这里就结束了,我学习了数据类型之后,通过了几个典型的例子,加深了对数据类型的理解,也是有所收获。