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

你可能感兴趣的文章
Node第一天
查看>>
node编译程序内存溢出
查看>>
Node读取并输出txt文件内容
查看>>
node防xss攻击插件
查看>>
noi 1996 登山
查看>>
noi 7827 质数的和与积
查看>>
NOI-1.3-11-计算浮点数相除的余数
查看>>
noi.ac #36 模拟
查看>>
NOI2010 海拔(平面图最大流)
查看>>
NOIp2005 过河
查看>>
NOIP2011T1 数字反转
查看>>
NOIP2014 提高组 Day2——寻找道路
查看>>
noip借教室 题解
查看>>
NOIP模拟测试19
查看>>
NOIp模拟赛二十九
查看>>
Vue3+element plus+sortablejs实现table列表拖拽
查看>>
Nokia5233手机和我装的几个symbian V5手机软件
查看>>
non linear processor
查看>>
Non-final field ‘code‘ in enum StateEnum‘
查看>>
none 和 host 网络的适用场景 - 每天5分钟玩转 Docker 容器技术(31)
查看>>