String字符串类型的数据结构
在 Java 中,String 除了是一个 引用数据类型 外,还是一个 用 final 关键字定义的 class 类
【final 关键字定义的类都是最终类,不能被继承】
String 类的部分代码如下:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; ……//类中定义很多,我们后面的先不看 }
因为 Jave 编译器对 String 有特殊处理,允许可以直接用 "…" 来表示一个字符串。通过这段代码,我们可以很清楚的看到 String 是一个 用 final 关键字定义的 class 类,而且还用关键字 private final 两个关键字定义了一个 char 类型的数组【final 关键字定义的 变量 都是 不能被改变的量,是为 常量】即 String 类型其实是一个个的 char 类型字符组成的,那么
import java.util.Arrays; public class Str { public static void main(String[] args) { // 定义一个String类型的值 String number = "abc"; String number1 = new String(new char[] { 'a', 'b', 'c' }); System.out.println("原数值number为:" + number); System.out.println("原数值number内存地址为:" + number.hashCode()); System.out.println("原数值number1为:" + number); System.out.println("原数值number1内存地址为:" + number.hashCode()); } }
运行结果 原数值number为:abc
原数值number内存地址为:96354
原数值number1为:abc
原数值number1内存地址为:96354
观察程序我们可以得到:String number = "abc";就相当于String number1 = new String(new char[] { 'a', 'b', 'c' });也清晰的理解了的“即 String 类型本质上是一个个的 char 类型字符组成的”这句话,也就是说实际上字符串在 String 内部是通过一个 char 类型的数组表示的
每次修改,都会产生一个新的字符串
由于 String 是一个 用 final 关键字定义的 class 类,而且还用关键字 private final 两个关键字定义了一个 char 类型的数组,“private final 两个关键字定义了一个 char 类型的数组”,而且没有任何修改char 类型的数组的方法实现 导致了字符串不可变,一旦对字符串进行修改,它就会指向一个新的地址,产生一个新的字符串
import java.util.Arrays; public class Str { public static void main(String[] args) { String s = "Hello";//定义一个字符串变量 System.out.println("s="+s); System.out.println("s的内存地址"+s.hashCode()); //s未指向新的字符串 //没有赋值给s,仅对s做大写字母转换,发现s并没有被改变,地址也未曾改变 s.toUpperCase(); System.out.println("s="+s); System.out.println("s的内存地址"+s.hashCode()); //s重新指向新的字符串 //对s做大写字母转换后赋值给s,发现s被改变,地址也改变 s = s.toUpperCase(); System.out.println("s="+s); System.out.println("s的内存地址"+s.hashCode()); } }
运行结果 s=Hello
s的内存地址69609650
s=Hello
s的内存地址69609650
s=HELLO
s的内存地址68624562对以上 s 的指向更直观的表示