Java基本数据类型和引用类型

       Java中一共有四类八种基本数据类型,如下所示:

类型 关键字
整型 byte short int long
浮点类型 float double
字符型 char
逻辑型 boolean

       除掉这四类八种基本类型,其它的都是对象,也就是引用类型,包括数组。来看一段示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(String[] args) {
int int1 = 100;
int int2 = int1;
int1 = 500;
System.out.println("打印int1的值:" + int1);
System.out.println("打印int2的值:" + int2);

int[] arr1 = new int[]{1, 2, 3, 4, 5};
int[] arr2 = arr1;
arr1[3] = 8;
System.out.println("打印arr1[3]的值:" + arr1[3]);
System.out.println("打印arr2[3]的值:" + arr2[3]);

Person per1 = new Person("张三", 21);
Person per2 = per1;
per1.setName("李四");
per1.setAge(35);

System.out.println("打印per1:" + per1.getName() + ";" + per1.getAge());
System.out.println("打印per2:" + per2.getName() + ";" + per2.getAge());
}

       先看第一句代码:

1
int int1 = 100;//声明了一个基本数据类型并赋值

       方法体里声明的基本数据类型在栈内存里,如下图:

基本数据类型和引用类型1

       继续执行以下代码:

1
int int2 = int1;//声明int2,并赋值为int1

       对于基本数据类型来说,赋值(=号)就相当于拷贝了一份值,把int1的值100,拷贝给int2,如下图:

基本数据类型和引用类型2

       int1=500,直接修改int1的值为500,表现如下图:

基本数据类型和引用类型3

       打印int1,int2的值,分别是500,100。

       再来看数组的初始化:

1
int[] arr1 = new int[]{1, 2, 3, 4, 5};//声明一个数组并赋值

       先初始化arr1,当执行到new这个关键字,会在堆内存分配内存空间,并把该内存空间的地址赋值给arr1。

基本数据类型和引用类型4

       继续执行以下代码:

1
int[] arr2 = arr1;//声明arr2,并赋值为arr1

       这儿arr2初始化时并没有new关键字,并不会在堆内存里新开辟一块空间,而是把arr1里存的堆内存地址直接赋值给了arr2,对于引用类型来说,赋值(=号)就相当于拷贝了一份内存地址,也就是说arr1,arr2现在指向了同一块堆内存,表现形式如下图:

基本数据类型和引用类型5

       这时候执行如下代码:

1
arr1[3] = 8;//修改数值下标位置为3的值

       虽然只是修改arr1数组下标位置为3的值,但由于数组arr1和数组arr2指向同一块堆内存,打印arr1[3]和arr2[3]的值,都是8。

基本数据类型和引用类型6

       再来看对象的初始化:

1
Person per1 = new Person("张三", 21);//声明一个对象并赋值

       当看到这个new,肯定在堆内存里开辟了一块内存空间,Person里有一个叫name的String对象,String这个对象有点特殊,虽然没有new这个关键字,但还是在堆内存中开辟了一块空间,String底层是数组实现的,数组也是引用类型,age为基本数据类型,表现如下图:

基本数据类型和引用类型7

       上图中大框里的内容就是整个Person对象在堆内存中的体现,继续执行以下代码:

1
Person per2 = per1;//声明per2,并赋值为per1

       没有new关键字,per2不会在堆内存中新开辟空间,和数组一样,也是把per1的内存地址直接赋值给了per2:

基本数据类型和引用类型8

       当我们修改per1的属性的时候:

1
2
per1.setName("李四");
per1.setAge(35);

       如下图两个红框里的内容,给对象(数组也是对象)赋值其实就是相当于引用重新指向一块堆内存,基本数据类型是直接修改值,表现如下图:

基本数据类型和引用类型9

       所以,不管打印per1还是per2的name、age,打印出来的结果都是“李四”、35。

       最开始的代码执行结果如下:

1
2
3
4
5
6
打印int1的值:500
打印int2的值:100
打印arr1[3]的值:8
打印arr2[3]的值:8
打印per1:李四;35
打印per2:李四;35

       所以当==两边是基本数据类型时,==比较的是两边的两个值是否相等,当==两边是引用类型时比较的是两个内存地址,也可以看成是看这两个引用是否指向堆内存里的同一块地址,如下图:

基本数据类型和引用类型10

参考资料:
清浅池塘 Java基本数据类型和引用类型

Fork me on GitHub