概述

  1. String:字符串,使用一对””引起来表示。
  2. String声明为final的,不可被继承
  3. String实现了Serializable接口:表示字符串是支持序列化的。

    实现了Comparable接口:表示String可以比较大小

  4. String内部定义了final char[] value用于存储字符串数据

  5. 通过字面量的方式(区别于new给一个字符串赋值,此时的字符串值声明在字符串常量池中)。
  6. 字符串常量池中是不会存储相同内容(使用String类的equals()比较,返回true)的字符串的。

String的不可变性

说明

  1. 当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
  2. 当对现的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
  3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
  1. String s1 = "abc";//字面量的定义方式
  2. String s2 = "abc";
  3. System.out.println(s1 == s2);//比较s1和s2的地址值----->true
  4. s1 = "hello";
  5. System.out.println(s1 == s2);//比较s1和s2的地址值----->flase
  6. String s3 = "abc";
  7. s3 += "def";
  8. System.out.println(s3);//abcdef
  9. System.out.println(s2);
  10. String s4 = "abc";
  11. String s5 = s4.replace('a', 'm');
  12. System.out.println(s4);//abc
  13. System.out.println(s5);//mbc

String实例化的不同方式

方式说明

方式一:通过字面量定义的方式
方式二:通过new + 构造器的方式

代码举例

  1. //通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
  2. String s1 = "javaEE";
  3. String s2 = "javaEE";
  4. //通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
  5. String s3 = new String("javaEE");
  6. String s4 = new String("javaEE");
  7. System.out.println(s1 == s2);//true
  8. System.out.println(s1 == s3);//false
  9. System.out.println(s1 == s4);//false
  10. System.out.println(s3 == s4);//false

图示

image.pngimage.png

面试题

String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?
两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:”abc”


字符串拼接方式赋值的对比

说明

1.常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
2.只要其中一个是变量,结果就在堆中。
3.如果拼接的结果调用intern()方法,返回值就在常量池中

代码举例

  1. String s1 = "javaEE";
  2. String s2 = "hadoop";
  3. String s3 = "javaEEhadoop";
  4. String s4 = "javaEE" + "hadoop";
  5. String s5 = s1 + "hadoop";//堆中
  6. String s6 = "javaEE" + s2;//堆中
  7. String s7 = s1 + s2;//堆中
  8. System.out.println(s3 == s4);//true
  9. System.out.println(s3 == s5);//false
  10. System.out.println(s3 == s6);//false
  11. System.out.println(s3 == s7);//false
  12. System.out.println(s5 == s6);//false
  13. System.out.println(s5 == s7);//false
  14. System.out.println(s6 == s7);//false
  15. String s8 = s6.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop”
  16. System.out.println(s3 == s8);//true
  17. String s1 = "javaEEhadoop";
  18. String s2 = "javaEE";
  19. String s3 = s2 + "hadoop";
  20. System.out.println(s1 == s3);//false
  21. final String s4 = "javaEE";//s4:常量
  22. String s5 = s4 + "hadoop";
  23. System.out.println(s1 == s5);//true

JVM中字符串常量池存放位置说明

jdk 1.6 (jdk 6.0 ,java 6.0):字符串常量池存储在方法区(永久区)
jdk 1.7:字符串常量池存储在堆空间
jdk 1.8:字符串常量池存储在方法区(元空间)