Java字符串的一些事儿

Java字符串的一些事儿

大家好,我是阿清,又是新的一天~

开门见山,今天简单聊下Java中的字符串,

包括四样:StringStringBuffer,  StringBuilderStringJoiner



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内部,它是靠字符数组来储存数据的,且被 finalprivate 修饰。

很多人会说,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


总结



今天聊的内容,我用以下几句话概括,

  1. String是不可变的,因为它被private与final修饰。

  2. 若需要频繁操作字符串,在不考虑线程安全时,可以使用StringBuilder, 考虑线程安全时,可以使用StringBuffer。

  3. StringJoiner可快速构造含有分隔符的字符串:通过在构造函数中传入分隔符、开头字符、结尾字符,再使用add方法进行拼接。

希望对你有帮助噢~


作者    阿清

编辑   一口栗子  

原文始发于微信公众号(六只栗子):Java字符串的一些事儿

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/88672.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!