字符串(修正版)

前面说到引用数据类型的存储方式与基本数据类型不一致,这里做进一步更规范的说明。

 


先看代码:

 1 public class String01 {
 2     public static void main(String[] args)
 3     {
 4         String str1 = "yyds";
 5         String str2 = "yyds";
 6         String str3 = new String("yyds");
 7         System.out.println(str1==str2);
 8         System.out.println(str1==str3);
 9     }
10 }

 

 为何会出现这样的情况?

内存可以分为栈、堆、方法区。而方法区里面又有一块地方称之为运行常量区。而像上面的"yyds",是保存在方法区的运行常量区的。上面第4、5行代码都是相当于在栈里声明了变量。若仅声明而不赋值,其地址为空。当初始化为"yyds"之后,"yyds"便存储在方法区的运行常量区,同时其地址会赋值给str1.假设其为089.再来看str2.因为str2也是赋值为"yyds",首先计算机会检测运行常量区是否有这个常量。已经有了的话,就不会再新开辟一块内存区域了,没有才会。因为在运行常量区已经有一个"yyds"了,所以它们会使用相同的内存区域。因此str2里面保存的也是089,与str1指向同一块内存区域。而str3就不一样了。所有new出来的对象都是存储在堆里面的(类的对象都是需要new的)。堆里面的对象就保存了一个地址,同样也是089,指向运行常量区的"yyds".堆里面这个对象保存的是地址,值是089,这个对象同样也是有地址的,假设其为045.我们是把new出来的对象赋值给了str3,所以str3指向堆里面的这个对象,而堆里面的对象又指向了运行常量区的字符串

因此,上面比较str1和str2,其实比较的是引用。由于其指向的都是同一块引用,地址是一样的,所以输出true.而str3指向的是堆里面的一块内存区域,str2指向的是运行常量区里面的一块内存区域,所以比较这两个字符串的话,肯定是不相等的,于是输出false.

注意equals这个方法比较的是字符串里面的字符,没有上面那么复杂。

 


示意图如下:


 插入:对于数组的一点说明:

首先看代码:

 1 public class ArrayDemo {
 2     public static void main(String[] args)
 3     {
 4         int[] a = {1,2,3};
 5         int[] b = null;
 6         b = a;
 7         b[1] = 80;
 8         System.out.println(a[1]+" "+b[1]);
 9     }
10 }

运行效果如下:

 

 出现这种情况的原因是因为,数组是属于引用数据类型,第6行代码的b = a这个操作相当于把a的地址赋给了b,所以它俩就指向了堆里面的同一块内存区域,当修改b[1]的值时,是把这块内存区域里面索引为1的那个值修改了。所以输出a[1]和b[1]时,它们都变为了80.


 

 

 总结:

基本数据变量声明出来不管是否赋值,都已经分配了内存;

引用数据变量的创建分为两步:声明和初始化。其中声明只在栈内分配内存(存储引用,或者说,存储内存地址),而初始化在堆或者方法区分配内存(存储实际的数据),new出来的东西放在堆里面,程序运行常量放在方法区。

 

posted @ 2021-01-25 16:22  EvanTheBoy  阅读(78)  评论(0)    收藏  举报