操作字符串的类都有哪些?区别是什么?
操作字符串的类主要用三个,分别是String类,StringBuffer类和StringBuilder类.
不可变字符串
String类
public class StringTest { public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; String s3 = new String("abc"); System.out.println(s1 == s2); // true System.out.println(s2 == s3); // false s2 = "abc" + "def"; System.out.println(s1 == s2); // false String s4 = "abcdef"; System.out.println(s4 == s2); // true } }
1.当使用=
对String类初始化的时候,会在常量池创建对象,将引用s1指向常量池中的地址.
2.创建s2的时候,会先在常量池中检查是否有"abc"
的对象,如果有则直接将s2指向常量池中的"abc"
.所以s1和s2指向的是相同的对象.
3.使用new
关键字创建String对象的时候,会在堆空间中开辟一块内存,然后在堆中对s3进行初始化,s3指向的是堆内存空间中的一块区域.
4.当我们对s2进行修改的时候,其实是在常量池中添加了新的对象"abcdef"
,此时我们创建新的对象s4会和创建s2的步骤相同.s4在常量池中找到了"abcdef"
,所以直接指向这个对象.
当我们对String类型的变量进行操作的时候,其实每次改变都是创建除了新的对象.
可变字符串
StringBuffer和StringBuilder类中都提供了增删字符串的方法,下面展示一个在原始对象上增加新的字符的示例.
public class StringTest2 { public static void main(String[] args) { StringBuffer sb1 = new StringBuffer("abc"); StringBuilder sb2 = new StringBuilder("abc"); System.out.println(sb1.hashCode()); // 460141958 System.out.println(sb2.hashCode()); // 1163157884 sb1.append("def"); sb2.append("def"); System.out.println(sb1.hashCode()); // 460141958 System.out.println(sb2.hashCode()); // 1163157884 } }
通过这个例子我们能清晰看到,s1和s2在增加元素前后仍旧是同一个对象.
StringBuffer和StringBuilder都继承了AbstractStringBuilder
类.
StringBuffer类
和StringBuilder类对比发现,StringBuffer类中的方法没有使用synchronized
关键字进行修饰.
@Override public StringBuilder append(String str) { super.append(str); return this; }
StringBuilder类
@Override public synchronized StringBuffer append(Object obj) { toStringCache = null; super.append(String.valueOf(obj)); return this; }
AbstractStringBuilder类的append方法
扩容方法:调用ensureCapacityInternal()方法检查初始char[] value
空间是否足够,如果不够的话,就进行扩容操作.
public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); // 查看空间是否足够 ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; }
private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code // 如果空间不够就重新开辟一块新的空间 if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value, newCapacity(minimumCapacity)); } }
copyOf方法:重新创建一个新的char数组然后将原数组数据拷贝到新数组去.
public static char[] copyOf(char[] original, int newLength) { char[] copy = new char[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
小结
Java操作字符串的类主要有三个,分别是String类,StringBuffer类和StringBuilder类.这三个类的底层都是以char[]
形式保存字符串对象的.他们之间的区别主要体现在:
1.String类型进行修改操作之后相当于重新创建对象,StringBuffer和StringBuilder进行增删操作都是针对同一个对象.
2.StringBuffer中的大部分方法都没有使用synchronized关键字修饰,所以性能更高(我刷题的时候也都是写这个).单线程情况下首选使用StringBuffer类,多线程环境下需要使用StringBuilder类保证线程安全.
3.如果字符串声明之后不需要进行改动,则直接声明String类是最好的选择,不使用new关键字声明String对象时,它不会再堆内存中开辟空间,而是直接指向String常量池.这样可以实现复用,降低资源消耗.
扩展阅读
Java基础系列第一弹之方法重载和方法重写的区别
Java基础系列第二弹之Java多态成员访问的特点
到此这篇关于Java有哪些操作字符串的类?区别在哪?的文章就介绍到这了,更多相关Java操作字符串的类内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!
- 本文固定链接: https://zxbcw.cn/post/214804/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)