Java中字符串对象的声明区别

在Java中字符串对象的声明有两种方式,一种是直接赋值(字面量创建字符串),另一种是通过new关键字调用构造函数创建对象。

代码如下:

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

这个String实例内容是一样的,但是地址是不一样的。

为什么?解释这个之前需要了解一下常量池的相关概念。参考:https://www.cnblogs.com/ysocean/p/8571426.html#_label0

常量池:Java运行时会维护一个String Pool(String池), 也叫“字符串缓冲区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。

在jdk1.7之前常量池和堆内存是分开存放的(常量池存在方法区中),但是在1.7以后方法区中的常量池被放到了堆中了。如下:

字面量创建字符串(直接赋值)或者纯字符串(常量)拼接字符串时,会首先在常量池中查找,看是否有相等的对象。没有的话就在常量池中创建该对象;有的话则直接用常量池中的引用,避免重复创建对象。

String s1 = "abc";
String s2 = "abc";
String s3 = "a"+"bc";//编译器确定为常量,直接到常量池中引用
System.out.println(s1==s2);//true
System.out.println(s1==s3);//true

使用new关键字创建时,直接在堆中创建一个新对象,变量所引用的都是这个新对象的地址。使用包含变量表达式来创建String对象,则不仅会检查维护常量池,还会在堆区创建这个对象,最后是指向堆内存的对象。

String s1="ab";
String s2="abc";
String s3=s1+"c";//编译器不能确定s1为常量(会在堆区创建一个String对象)
System.out.println(s3==s2);         // false

所以对于上面提到的问题,是不是现在已经明白了?直接赋值的相关操作是在常量池中进行的,而通过new关键字的相关操作则是在堆中。

猜你喜欢

转载自blog.csdn.net/yong_zi/article/details/81297404
今日推荐