大家好,我是阿清,又是新的一天~
开门见山,今天简单聊下Java中的字符串,
包括四样:String,StringBuffer, StringBuilder,StringJoiner
01
—
String
String是一个对象,且它最重要的特点:它是不可变的。
观察源码:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
...
}
在String内部,它是靠字符数组来储存数据的,且被 final 和 private 修饰。
很多人会说,String不可变的原因是它被final修饰,但这样的描述并不准确。
因为被final修饰只表示它不能指向新的数组,而它指向的原数组的本身内部的数据还是能被改变的。
真正的原因是它同时还被private修饰了,且在String类的内部中对外没有提供任何可以改变数组的方法。
而当调用substring、concat、等方法时都返回的是新的String,我们可以看下substring的源码
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
可以看出最后一句,返回的是一个新的String对象。
且正是因为,被final修饰,String也不可被继承, 也不存在对String进行扩展的情况。
02
—
StringBuffer 与 StringBuilder
在实际的业务场景中,我们肯定会遇到需要频繁修改字符串的情况,这时候如果使用String将会产生非常多的String对象,
这对内存是巨大的损耗,因此,Java推出了可变字符串:StringBuffer 与 StringBuilder。
它们都继承了AbstractStringBuilder,观察它的源码开头:
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
...
}
可以看到,同String一样,AbstractStringBuilder也是通过char数组保存数据的,但它并没有被private 与 final修饰。
且它提供了许多修改字符串的方法,这些方法返回的都是原对象本身,是对原对象进行修改。
比如我们看一个最常用的append方法:
public AbstractStringBuilder append(char[] str) {
int len = str.length;
ensureCapacityInternal(count + len);
System.arraycopy(str, 0, value, count, len);
count += len;
return this;
}
最后一句,return this
,表明返回的是这个对象本身。
StringBuffer 与 StringBuilder的区别主要在于:
StringBuffer是线程安全的,StringBuilder是线程不安全的。
在StringBuffer中,有关字符串操作的方法都使用 synchronized 关键字进行修饰,以此保证线程安全。
因此StringBuffer的性能要低于StrngBuilder。
03
—
StringJoiner
关于StringJoiner,阿清也是这段时间才知道java有这么个东西,它其实能简化一些字符串构造的代码。
一句话概括,StringJoiner能够快速构造一个含有分隔符与开头、结尾的字符串。
譬如,如果我们希望构造一个这样的字符串:[1, 2, 3, 4, 5, 6]
它的开头是”[“,结尾是”]”,分隔符是”,“
你也许会这样写:·
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("[");
for (int i = 1; i <= 6; ++i) {
sb.append(i).append(",");
}
sb.delete(sb.length() - 1, sb.length());
sb.append("]");
System.out.println(sb.toString());
}
你需要控制开头与结尾,同时还要删除最后一个元素后面的分隔符。
有了StringJoiner,编写的代码将十分简洁:
public static void main(String[] args) {
StringJoiner sj = new StringJoiner(",","[","]");
for (int i = 1; i <= 6; ++i) {
String s = new String("");
s += i;
sj.add(s);
}
System.out.println(sj.toString());
}
只需要构造一个StringJoiner对象,在构造方法中,依次传入分隔符、前缀字符(开头)、后缀字符(结尾)即可。
再使用add方法添加你的元素即可。
但是要注意,StringJoiner的add方法只接受CharSequence类型的参数。
CharSequence 是一个接口,目前实现了该接口的类,正是上述的String、StringBuilder、StringBuffer三个类。
因此,使用StringJoiner进行字符串拼接时,要保证参数为字符串。
04
—
总结
今天聊的内容,我用以下几句话概括,
-
String是不可变的,因为它被private与final修饰。
-
若需要频繁操作字符串,在不考虑线程安全时,可以使用StringBuilder, 考虑线程安全时,可以使用StringBuffer。
-
StringJoiner可快速构造含有分隔符的字符串:通过在构造函数中传入分隔符、开头字符、结尾字符,再使用add方法进行拼接。
希望对你有帮助噢~
作者 阿清
编辑 一口栗子
原文始发于微信公众号(六只栗子):Java字符串的一些事儿
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/88672.html