【面试精讲】String是如何实现的?String源码分析
目录
三、String 和 StringBuilder、StringBuffer 的区别
在Java中,String
类是使用最频繁的类之一。由于其不可变性、效率以及如何影响内存使用等方面的特点,String
类成为了Java编程语言的一个核心组成部分。本文深入探讨String
的实现机制、它的源码结构、特点以及用final
修饰的好处。
一、String实现机制
在Java中,String
被设计为不可变(immutable)的对象。这意味着一旦String
对象被创建,它所包含的字符序列就不能被修改。每次对字符串进行操作时(例如拼接、替换字符等),实际上都会创建一个新的String
对象。
从JDK 1.0到JDK 8,String
内部是通过一个char
数组来实现的,保存着所有的字符数据。从JDK 9开始,String
类的内部实现改为使用byte
数组加上一个编码标记(coder
),以更有效地处理不同的字符集,优化内存使用和性能。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
// 用于存储字符串的值
private final char value[];
// 缓存字符串的 hash code
private int hash; // Default to 0
}
自JDK 9起,为了提升空间效率和性能,String
的内部表示发生了变化,使用byte
数组加上一个编码标志字段coder
来存储字符串,如下所示:
// JDK 9及以后的String内部结构
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
// 实际存储字符串内容的byte数组
private final byte[] value;
// 字符串使用的编码标识(用于区分使用Latin-1还是UTF-16编码)
private final byte coder;
// 缓存字符串的哈希码
private int hash; // 默认为0
// 构造方法之一,用于从字符数组初始化字符串
public String(char[] value) {
// 这里简化了实际的实现细节
this.value = StringLatin1.toBytes(value);
this.coder = LATIN1;
}
// length() 方法实现
public int length() {
return value.length >> coder;
}
}
二、String不可变性(使用final修饰)
String
对象一旦被创建,其内容就不能被改变。任何对String
的修改操作都会导致新的String
对象的生成。这个特性带来了以下好处:
安全性:String
常作为参数传递,其不可变性保证了数据不会被意外改变。防止子类改变父类(String
)的行为,确保所有String
实例都具有String
定义的行为。
线程安全:在多线程环境下,String
可以被自由共享而无需同步控制。
高效:因为String
的内容不变,所以其哈希码可以被缓存,提高哈希表操作的效率。性能优化:
简化设计:由于不需要考虑子类的影响,使得String
类的设计更简单、更稳定
三、String 和 StringBuilder、StringBuffer 的区别
String
类重载了+
运算符,使得字符串连接操作非常方便。然而,频繁的字符串连接操作会产生大量临时字符串对象,影响性能。为了解决这个问题,Java引入了StringBuilder
和StringBuffer
两个类,它们允许在单个字符序列上执行可变操作。
因为 String 类型是不可变的,所以在字符串拼接的时候如果使用 String 的话性能会很低,因此我们就需要使用另一个数据类型 StringBuffer,它提供了 append 和 insert 方法可用于字符串的拼接,它使用 synchronized 来保证线程安全。
在 JDK 1.5 有了 StringBuilder,它同样提供了 append 和 insert 的拼接方法,在非并发操作的环境下可使用 StringBuilder 来进行字符串拼接。
四、==和equals的区别
== 对于基本数据类型来说,是用于比较 “值”是否相等的;而对于引用类型来说,是用于比较引用地址是否相同的。
// Object 中的 equals() 方法其实就是 ==
public boolean equals(Object obj) {
return (this == obj);
}
// 而String重写equals()方法把它修改成比较两个字符串的值是否相等
public boolean equals(Object anObject) {
// 对象引用相同直接返回 true
if (this == anObject) {
return true;
}
// 判断需要对比的值是否为 String 类型,如果不是则直接返回 false
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
// 把两个字符串都转换为 char 数组对比
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
// 循环比对两个字符串的每一个字符
while (n-- != 0) {
// 如果其中有一个字符不相等就 true false,否则继续对比
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
五、String创建对象与JVM辨析
String 常见的创建方式有两种,new String() 的方式和直接赋值的方式
直接赋值的方式会先去字符串常量池中查找是否已经有此值,如果有则把引用地址直接指向此值,否则会先在常量池中创建,然后再把引用指向此值;
new String() 的方式一定会先在堆上创建一个字符串对象,然后再去常量池中查询此字符串的值是否已经存在,如果不存在会先在常量池中创建此字符串,然后把引用的值指向此字符串
JDK 1.7 之后把永生代换成的元空间,把字符串常量池从方法区移到了 Java 堆上。
六、String源码解析
1、compareTo()
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
// 获取到两个字符串长度最短的那个 int 值
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
// 对比每一个字符
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
// 有字符不相等就返回差值
return c1 - c2;
}
k++;
}
return len1 - len2;
}
2、 equals()
public boolean equals(Object anObject) {
// 对象引用相同直接返回 true
if (this == anObject) {
return true;
}
// 判断需要对比的值是否为 String 类型,如果不是则直接返回 false
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
// 把两个字符串都转换为 char 数组对比
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
// 循环比对两个字符串的每一个字符
while (n-- != 0) {
// 如果其中有一个字符不相等就 true false,否则继续对比
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
总结
String
在Java中的地位极其重要,其设计精巧、使用广泛。通过不可变性设计,String
提供了高度的安全性和线程安全,同时final
修饰符进一步确保了其不变契约的稳定性。了解String
的内部实现和特点对于写出高效、安全和易维护的Java代码至关重要。
Java开发者应当熟练掌握String
的使用,并在合适的场景选择使用StringBuilder
或StringBuffer
以优化性能。此外,深入理解String
的设计哲学也有助于开发者设计自己的不可变类,为构建稳定和高效的Java应用打下坚实的基础。
如果本文对你有帮助 欢迎 关注 、点赞 、收藏 、评论, 博主才有动力持续记录遇到的问题!!!
博主v:XiaoMing_Java
标签:Java,String,int,精讲,value,源码,字符串 From: https://blog.csdn.net/FMC_WBL/article/details/136695096