如何理解String 代表不可变的字符序列,即String 字符串的不可变性
String 概述
String 字符串,使用一堆"" 引起来表示。
- 1.
String
类是final
的,表示不可被继承。 - 2.
String
实现了Serializable
接口,表示字符串是支持序列化的。
String
实现了Comparable
接口:表示String
是可以比大小的。 - 3.
String
内部定义了final char[] value
用于存储字符串数据,即String
底层都是以char[]
型数组存储的。
String 的不可变性理解
String 代表不可变的字符序列。简称:不可变性
体现1: 当对字符串重新复制时,需要重写指定内存区域赋值,不能使用原有的value 上赋值。
如下代码:
String s1 = "abc";//通过字面量方式定义字符串
String s2 = "abc";
s1 = "hello";
System.out.println(s1 == s2);//比较s1 和s2 的地址值
System.out.println(s1);//hello
System.out.println(s2);//abc
上述代码,给s1 重新赋值时,其实是在内存方法区的字符串常量池里,重新创建了一个名为hello
的字符串,将hello 的首地址,重新赋值给s1。
过程如下:
- 当先声明两个s1 和 s2 同时为"abc"时,内存示意图如下:
- 当给s1 重新赋值时,内存示意图如下:
体现2: 当对字符串进行连接操作时,也需要重新指定内存区域赋值,不能再原有value上赋值。
如下代码
声明了一个String 变量s3,此时给s3加上"def",其实是在内存中重新创建了如 "abcdef"的字符串常量,再将这个字符串常量的首地址关联到s3
String s3 = "abc";
s3 += "def";
System.out.println(s3);//abcdef
字符串对象是如何存储的
String s3 = new String("javaEE");
这种方式是如何存储的?
例如:String s1 = "javaEE";
和 String s3 = new String("javaEE");
有什么区别?
答:
String s1 = "javaEE";
//是通过字面量方式声明,字符串是存储在方法区中的字符串常量池中。String s3 = new String("javaEE");
// 这种方式,先是创建了一个对象,然后在对象中有一个value属性,这个属性关联到字符串常量池中的字符串(javaEE
)。
内存结构如图
例如: 如下代码演示字面量创建字符串和对象方式创建字符串的区别
//通过字面量方式声明字符串
String s1 = "javaEE";
String s2 = "javaEE";
//通过new对象方式声明
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
内存结构示意图
说明: 通过new 的方式创建字符串,实际上是创建了两个对象:
一个对象在堆中(new的对象),
另一个在字符串常量池中(真实字符串)。