String

  • 一、字符串常量池
  • 二、String对象的创建方式
  • 三、 String比较
  • 四、字符串拼接"+"的影响


一、字符串常量池

字符串常量池用于存放字符串常量。
在jdk1.7之前,其存放在永久代中;jdk1.7之后移至java堆中。

二、String对象的创建方式

java中String对象一共有两种创建方式

  • 字面量形式
    用字面量形式进行String对象创建时,会首先在常量池中查找是否有该字面量,若有该字面量,则直接返回该字面量的引用地址;若不存在该字面量,则先将该字面量加入常量池中再返回引用。
String s1="abc";//先将字面量加入常量池再返回引用
 String s2="abc";//直接返回引用
  • String()构造函数形式
    用构造函数形式(如下例)进行String对象创建时,首先会在常量池中查找是否有字面量"abc",如果有该字面量,则会直接在堆内存中创建一个字符串对象并返回堆上的引用地址,否则会先将该字面量加入常量池中,再在堆内存中创建一个字符串对象并返回堆上的引用地址。
String s3=new String("abc");//因为s1的创建,s3直接在堆内存中创建

三、 String比较

  • “a==b”
String s1="abc";
   String s2="abc";
   String s3=new String("abc");
   System.out.println(s1==s2);//true
   System.out.println(s1==s3);//false

上述两个输出结果之所以一个为true,一个为false是因为"a==b"的比较,不仅仅是比较两者的值是否相等,并且会比较两者的地址是否相等。s1和s2的地址都是常量池中“abc”对应的地址,因此输出为true;而s3的地址是堆中的地址,与常量池中地址不一样,因此返回false。

  • “a.equals(b)”
String s1="abc";
   String s2="abc";
   String s3=new String("abc");
   System.out.println(s1.equals(s2));//true
   System.out.println(s1.equals(s3));//true

上述两个输出结果之所以都为true,是因为"a.equals(b)"的比较,只比较两者值是否相等,因此比较结果显而易见。
注意: 在需要判断两个字符串是否相等时,一般情况下需求都是判断值是否相等,因此推荐使用"a.equals(b)"形式。

四、字符串拼接"+"的影响

String test="helloworld";
String s1="hello";
String s2="world";
System.out.println(test=="hello"+"world");//true
System.out.println(test ==s1 + s2);//false

第一个比较为true这是因为字符串字面量拼接操作是在Java编译器编译期间就执行了,也就是说编译器编译时,直接把"hello"和"world"这两个字面量进行"+“操作得到一个"helloworld” 字面量,而该字面量在test创建时就加入常量池中,因此"hello"+"world"的地址就是常量池中的地址。
第二个比较为false这是因为字符串引用的"+"运算是在Java运行期间执行的,即s1 + s2 在程序执行期间才会进行计算,它会在堆内存中重新创建一个拼接后的字符串对象,因此其地址是堆中的地址。