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

你可能感兴趣的文章
Nginx配置ssl实现https
查看>>
Nginx配置TCP代理指南
查看>>
Nginx配置——不记录指定文件类型日志
查看>>
nginx配置一、二级域名、多域名对应(api接口、前端网站、后台管理网站)
查看>>
Nginx配置代理解决本地html进行ajax请求接口跨域问题
查看>>
nginx配置全解
查看>>
Nginx配置参数中文说明
查看>>
nginx配置域名和ip同时访问、开放多端口
查看>>
Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
查看>>
Nginx配置如何一键生成
查看>>
Nginx配置实例-负载均衡实例:平均访问多台服务器
查看>>
Nginx配置文件nginx.conf中文详解(总结)
查看>>
Nginx配置负载均衡到后台网关集群
查看>>
ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
查看>>
NHibernate学习[1]
查看>>
NHibernate异常:No persister for的解决办法
查看>>
NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
查看>>
NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
查看>>
NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
查看>>
NIFI从MySql中增量同步数据_通过Mysql的binlog功能_实时同步mysql数据_根据binlog实现数据实时delete同步_实际操作04---大数据之Nifi工作笔记0043
查看>>