String类分析(JDK1.8)
1、源码
String 对象是对 char 数组进行了封装实现的对象, 主要有 2 个成员变量: char 数组, hash 值。
2、String对象的不可变性
String类被final关键字修饰了,变量char 数组也是final修饰了。不可继承修改。
3、优点
- 保证 String 对象的安全性。假设 String 对象是可变的,那么 String 对象将可能被恶意修改。
b、保证 hash 属性值不会频繁变更,确保了唯一性, 使得类似 HashMap 容器才能实现相应的 key-value 缓存功能。
c、可以实现字符串常量池。在Java 中通常有两种创建字符串对象的方式,一种是通过字符串常量的方式创建,如 String str=“abc”; 另一种是字符串变量通过 new 形式的创建,如 String str = new String(“abc” )。
4、String 的创建方式及内存分配的方式
a、String str=“abc”
当代码中使用这种方式创建字符串对象时, JVM 首先会检查该对象是否在字符串常量池中, 如果在, 就返回该对象引用,否则新的字符串将在常量池中被创建。 这种方式可以减少同一个值的字符串对象的重复创建,节约内存。(str 只是一个引用)。
b、String str = new String(“abc”)
首先在编译类文件时, "abc"常量字符串将会放入到常量结构中,在类加载时,“abc"将会在常量池中创建;其次,在调用 new 时,JVM 命令将会调用 String的构造函数,同时引用常量池中的"abc” 字符串,在堆内存中创建一个 String 对象;最后,str将引用String对象。
- 使用 new, 对象会创建在堆中, 同时赋值的话, 会在常量池中创建一个字符串对象, 复制到堆中。具体的复制过程是先将常量池中的字符串压入栈中, 在使用 String 的构造方法是, 会拿到栈中的字符串作为构方法的参数。这个构造函数是一个 char 数组的赋值过程, 而不是 new 出来的, 所以是引用了常量池中的字符串对象。 存在引用关系。
编程过程中, 字符串的拼接很常见。 前面我讲过 String 对象是不可变的, 如果我们使用 String 对象相加, 拼接我们想要的字符串, 是不是就会产生多个
对象呢? 例如以下代码:
分析代码可知: 首先会生成 ab 对象, 再生成 abcd 对象, 最后生成 abcdef 对象, 从理论上来说, 这段代码是低效的。
编译器自动优化了这行代码, 编译后的代码, 你会发现编译器自动优化了这行代码, 如下
String str= "abcdef";
5、Intern()
String 的 intern 方法, 如果常量池中有相同值, 就会重复使用该对象, 返回对象引用
String提供的intern方法,String.intern()是一个Native方法,它的作用是:如果运行时常量池中已经包含一个等于此String对象内容的字符串,则返回常量池中该字符串的引用,如果没有,则在常量池中创建与String内容相同的字符串,并返回常量池中创建的字符串的引用。