博客
关于我
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/

你可能感兴趣的文章
NIFI大数据进阶_NIFI集群知识点_集群的断开_重连_退役_卸载_总结---大数据之Nifi工作笔记0018
查看>>
NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
查看>>
NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
查看>>
NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
查看>>
NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
查看>>
NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
查看>>
NIFI集群_内存溢出_CPU占用100%修复_GC overhead limit exceeded_NIFI: out of memory error ---大数据之Nifi工作笔记0017
查看>>
NIFI集群_队列Queue中数据无法清空_清除队列数据报错_无法删除queue_解决_集群中机器交替重启删除---大数据之Nifi工作笔记0061
查看>>
NIH发布包含10600张CT图像数据库 为AI算法测试铺路
查看>>
Nim教程【十二】
查看>>
Nim游戏
查看>>
NIO ByteBuffer实现原理
查看>>
Nio ByteBuffer组件读写指针切换原理与常用方法
查看>>
NIO Selector实现原理
查看>>
nio 中channel和buffer的基本使用
查看>>
NIO三大组件基础知识
查看>>
NIO与零拷贝和AIO
查看>>
NIO同步网络编程
查看>>