博客
关于我
Java中String和StringBuilder
阅读量:124 次
发布时间:2019-02-26

本文共 3723 字,大约阅读时间需要 12 分钟。

String、StringBuilder及其在Java中的应用

在Java编程中,String类的行为和特性是开发者需要深入理解的核心概念之一。本文将从String的不可变性、StringBuilder的可变性以及字符串操作的实现机制等方面,探讨这些概念的细节及其在实际开发中的应用。


一、String的对象不可变

String类在Java中是一个final类,这意味着它不能被继承。这一点非常重要,因为它决定了String对象的行为特性——不可变

1.1 String的内部结构

通过查看String类的源码,可以发现String对象内部存储了一个char[]数组,用来保存字符串的每个字符。由于这个数组是私有的,并且String类被final修饰,任何修改操作都无法改变原有的String对象。

1.2 String操作的实现

许多常见的String方法(如substringreplace等)在实现时,都会返回一个新的String对象,而不会修改原有的String对象。例如:

  • substring方法会根据给定的起始和结束索引创建一个新数组,并返回一个新的String对象。
  • replace方法则会创建一个新的字符数组,替换掉指定的字符。

1.3 实例验证

通过以下代码可以验证String对象的不可变性:

public void stringTest3() {    String a = "nihaoshije";    String b = a.substring(0, 4);    System.out.println(b); // niha    System.out.println(a); // nihaoshije}

输出结果表明,原字符串a并未被修改,而是返回了一个新的String对象b


二、StringBuilder的字符可变性

StringBuilder类是一个可变字符串容器,它允许对字符串进行高效的修改操作。与String类不同,StringBuilder的字符是可以被修改的。

2.1 StringBuilder的append方法

StringBuilder类通过append方法来添加字符或String对象。该方法返回的是当前StringBuilder对象本身,表明String对象被修改。例如:

public StringBuilder append(String str) {    super.append(str);    return this;}

实际上,append方法会调用父类的append方法,处理字符串追加操作。

2.2 字符数组操作

StringBuilder内部使用一个char[]数组存储字符。通过反编译可以看到,append方法会先检查数组的容量是否足够,如果不够则扩容。然后调用String类的getChars方法,将字符复制到数组中。

2.3 实例验证

以下代码可以直观地观察StringBuilder的可变性:

public void stringBuilderTest() {    StringBuilder stringBuilder = new StringBuilder("hello");    System.out.println(stringBuilder); // 输出: hello    stringBuilder.append("world");    System.out.println(stringBuilder); // 输出: helloworld}

可以看到,StringBuilder对象在调用append方法后,其内容确实发生了变化。


三、关于字符串相加

在Java中,字符串相加操作(如"hello" + "world")看似简单,却隐藏着深层的实现细节。

3.1 "+"运算符的重载

String类的+运算符是Java中唯一的重载运算符之一。当两个String对象相加时,Java会调用StringBuilderappend方法来高效地构建结果字符串。

3.2 字符串相加的实现

通过反编译可以发现,"hello" + "world"在编译期间会被优化为一个新的String对象。这个优化过程意味着,结果字符串会直接引用池中的常量。

3.3 两种相加方式的区别

  • 直接相加String str = "hello" + "world"。这种方式在编译阶段优化,效率较高。
  • 引用相加String b = "hello"; String c = "world"; String d = b + c。这种方式在运行时通过StringBuilder实现,效率相对较低。

3.4 实例验证

public void stringTest4() {    String a1 = "helloworld";    String a = "hello" + "world";    String b = "hello";    String c = "world";    String d = b + c;    System.out.println(a);    // helloworld    System.out.println(d);    // helloworld    System.out.println(a == d); // false    System.out.println(a1 == a); // true    System.out.println(a1 == d); // false}

输出结果表明,直接相加的字符串和引用相加的字符串在内存中是不同的对象。


四、String、StringBuffer、StringBuilder对比

4.1 执行效率

  • StringBuilder > StringBuffer > String
    StringBuilder在多次修改字符串时的效率远高于String,而StringBuffer的效率也低于StringBuilder。

4.2 线程安全

  • StringBuffer是线程安全的,而StringBuilder不是
    StringBuffer的方法都是同步的,适合多线程环境;而StringBuilder的方法则不具备同步性,需要在多线程环境中谨慎使用。

五、常见面试题目

5.1 字符串比较

String a = "hello";String b = "hello";String a1 = new String("hello");String a2 = new String("hello");StringBuilder c = new StringBuilder("hello");StringBuilder d = new StringBuilder("hello");System.out.println(a == b);   // trueSystem.out.println(a1 == a2); // trueSystem.out.println(c == d);   // falseSystem.out.println(a1.equals(a2)); // trueSystem.out.println(a.equals(c));   // falseSystem.out.println(c.equals(d));   // false

答案: true, false, false, true, false, false

5.2 字符串相加的结果

String a = "hellonihao";String b = "hello" + "nihao";System.out.println(a == b); // true

答案: true

原因:在编译阶段,"hello" + "nihao" 会被优化为 "hellonihao",因此 a 和 b 指向同一个常量池中的字符串。

5.3 字符串拼接的结果

String a = "nihaoshijie";String b = "nihao";String c = "shijie";String d = b + c;System.out.println(a == d); // false

答案: false

原因:字符串相加不会在编译阶段优化,因此 d 是一个新的字符串对象。

5.4 String的intern方法

String a = "hello";String b = new String("hello");String c = a.intern();System.out.println(a == b);   // falseSystem.out.println(c == a);   // true

答案: false, true

原因:intern方法会检查常量池中是否存在等于此字符串的实例。如果存在,则返回该实例;否则,将字符串添加到池中并返回新实例。

转载地址:http://fuuy.baihongyu.com/

你可能感兴趣的文章
pyqt出现“Ui_Dialog has no attribute “show””
查看>>
PyQt:如何使用QAxWidget引用发送参数
查看>>
PyQt:我可以制作一个带有图标和文本的工具栏按钮吗?
查看>>
pyscopg2:是否可以在循环中动态添加 %s
查看>>
Pyserial 缓冲区的填充速度比我读的快
查看>>
PySpark - 在数据框中求和一列并将结果返回为 int
查看>>
pyspark On Yarn 的模块依赖问题
查看>>
PySpeech(Python)-转录MP3文件?
查看>>
Pyspider WebUI 未授权访问致远程代码执行漏洞复现
查看>>
pyspider爬虫学习-文档翻译-Architecture.md
查看>>
pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it‘s not in your path
查看>>
Pytesseract集字符白名单
查看>>
PyTorch DataLoader 报错 Segmentation fault (core dumped) 的原因及解决方案
查看>>
Pytest ------ 标记函数
查看>>
Pytest Fixture的妙用:深度解析范围和实际运用!
查看>>
Pytest monkeypatch不适用于导入的函数
查看>>
Pytest 命令行报错: Hint: make sure your test modules/packages have valid Python names.
查看>>
pytest 的 request fixture:实现个性化测试需求
查看>>
Pytest+Allure 接口自动化测试平台开发实战
查看>>
pytest+allure使用动态级别,参数化severity
查看>>