【笔记】Java 赋值与内存地址的关系
本文最后更新于 798 天前,其中的信息可能已经有所发展或是发生改变。

首先明确一点,就是 == 运算符的作用就是比较两边变量所指向内存地址是否相同。

基本类型的赋值与内存地址

首先来看这个例子:

int i1 = 123;
int i2 = 123;
int i3 = i1;

System.out.println(i1 == i2);   // true
System.out.println(i1 == i3);   // true

i3 = 321;
System.out.println(i1 == i3);   // true

可以得出几个结论:

  • 对于基本类型,值相等的变量,它们指向的内存地址也是相同的;
  • 对于基本类型,将一个变量赋予另一变量,两者指向的内存地址也是相同的;
  • 对于基本变量,如果两个变量先前指向的内存地址是相同的,但是后来有一个变量修改了值,那么修改值后两个变量的内存地址就不再相同。

总结一下,就是值相同,地址就相同

数组类型的赋值与内存地址

来看 Java 数组的例子:

int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
int[] array3 = array1;
int[] array4 = new int[] {1, 2, 3};

System.out.println(array1 == array2);   // false
System.out.println(array1 == array3);   // true
System.out.println(array1 == array4);   // false

array3[0] = 10;

System.out.println(array1 == array3);   // true
// array1 = {10, 2, 3}
// array3 = {10, 2, 3}

可以得出几个结论:

  • 对于数组类型,两个数组变量哪怕内容相同,它们指向的地址也是不同的;
  • 对于数组类型,一旦将一个变量赋值给另一个变量,那么这两个数组变量都将指向同一个内存中的数组数据。修改一个变量,另一个变量也会随之修改;
  • 对于数组类型,不管用不用 new,都会创建一个新的数组。

总结来说,只有将一个变量赋值给另一个变量,两者地址才相同

对象类型的赋值与内存地址

来看这样的例子:

var t1 = new TodolistItem("Todolist title");
var t2 = new TodolistItem("Todolist title");
var t3 = t1;

System.out.println(t1 == t2);       // false
System.out.println(t1 == t3);       // true

t3.setTodolistTitle("new title");
System.out.println(t1.getTitle());  // "new title"
System.out.println(t3.getTitle());  // "new title"

TodolistItem 是一个 JavaBean 类,根据上面的例子可知:

  • 对于对象类型,不管对象内的字段是否相同,它们指向的地址也是不同的;
  • 对于对象类型,一旦将一个变量赋值给另一个变量,那么这两个对象变量都将指向同一个内存中的对象数据。修改一个变量,另一个变量也会随之修改。

和数组类型差不多,只有将一个变量赋值给另一个变量,两者地址才相同

String 类型的赋值与内存地址

String 类型对象有两种创建方式:

String s1 = "String Content";
String s2 = new String("String Content");

这两种创建 String 对象的方式要分开来进行分析。

直接创建字符串方式

首先是直接创建字符串的方式:

String s1 = "String Content";
String s2 = "String Content";
String s3 = s1;

System.out.println(s1 == s2);   // true
System.out.println(s1 == s3);   // true

s3 = "new Content";
System.out.println(s1);         // "String Content"
System.out.println(s3);         // "new Content"
System.out.println(s1 == s3);   // false

根据上面的例子可知:

  • 直接定义的字符串,如果字符串内容相同,则地址相同;
  • 将直接定义的字符串变量直接赋值给另一个变量,那么两个变量指向的地址是相同的;
  • 如果两个指向相同内存地址的变量中的一个字符串变量发生变化,另一个变量不会随之变化,两者指向的地址也不再相同。

简单来说,就是和基本类型的情况差不多。

通过 new 创建字符串方式

另一种是通过 new 来创建的字符串:

String s1 = new String("String Content");
String s2 = new String("String Content");
String s3 = s1;

System.out.println(s1 == s2);   // false
System.out.println(s1 == s3);   // true

s3 = "new Content";
System.out.println(s1);         // "String Content"
System.out.println(s3);         // "new Content"
System.out.println(s1 == s3);   // false

根据上面的例子可知:

  • new 创建的字符串,即便内容相同,地址也不相同;
  • 如果将 new 创建的字符串变量直接赋值给另一个变量,那么两个变量指向的地址是相同的;
  • 如果两个指向相同内存地址的变量中的一个字符串变量发生变化,另一个变量不会随之发生变化,两者指向的地址也不再相同。

顺便说一句,例子中用的是 s3 = "new Content";,用 s3 = new String("new Content"); 效果也是一样的。

String 类型的赋值总结

可以看到,String 类型虽然也是对象类型,但是和其他对象类型还是不太一样的。

String 类型有两种创建的方式,其中直接用双引号来创建字符串对象的方式和基本类型没什么区别;但另一种通过 new 创建字符串对象的方式,它和基本类型或者对象类型都是不相同的。所以 String 类型的赋值与地址之间的关系要单独理解记忆。

总结

总结得到下表所示的规律:

类型值相同时地址是否相同a==b 时修改 a,此时 b 是否会发生变化
基本类型相同不会改变,一旦 a 发生变化,ab 的地址就不再相同
数组类型不相同会发生改变,ab 的地址始终是相同的
对象类型不相同会发生改变,ab 的地址始终是相同的
直接定义的字符串对象相同不会改变,一旦 a 发生变化,ab 的地址就不再相同
new 创建的字符串对象不相同不会改变,一旦 a 发生变化,ab 的地址就不再相同
赋值与内存地址的关系总结
暂无评论

发送评论 编辑评论

上一篇
下一篇