Java详解【String】+【StringBuilder vs StringBuffer】+【字符串拼接】

本文详细探讨了Java中的String类,强调其不可变性,并通过示例解释了对象和引用的区别。此外,对比了StringBuilder和StringBuffer在多线程和性能上的差异,以及字符串拼接的五种方法及其效率。最后总结了在不同场景下选择String、StringBuilder和StringBuffer的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

String详解

  • 注意区分对象和对象的引用

首先来看一下我在jdk中找到的String源代码,这里只截取开头的小小一部分

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

从这里可以看出,String类是被final所修饰的,因此String类对象不可变,也不可继承。这里要注意一个误区字符串对象不可变,但字符串变量所指的值是可变的,即引用地址可变。String变量存储的是对String对象的引用,String对象里存储的才是字符串的值【注意区分对象和对象的引用】。看下面的例子

String str = "abc"; //str是个对象引用
System.out.println(str); //输出abc
str = "abcde"; //不会出错
System.out.println(str); //输出abcde

当给str第二次赋值的时候,对象"abc"并没有被销毁,仍存放在常量池中(String自带),只是让str指向了"abcde"的内存地址,而字符串对象"abcde"是新生成的,即str第二次赋值时并不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。记住,对String对象的任何改变都不影响到原对象,相关的任何改变的操作都会生成新的对象。

 

  • String对象是否真的不可变?!

答案并不是的,那么该如何做呢?那就是使用反射(反射不太懂的可以点击链接学习——反射基础详解

从上面的源码可知String的成员变量是private final的,也就是初始化之后不可改变。那么在这几个成员中,value比较特殊,因为它是一个引用变量,而不是真正的对象。value是final修饰的,即final不能再指向其他数组对象,那么我想改变value指向的数组时,比如将数组中的某个位置上的字符变为下划线"_"。因为不能直接通过这个引用去修改数组,那么为了访问到至value这个引用,我们可以使用反射来访问私有成员,反射出String对象中的value属性,进而改变value数组的内容。

public static void testReflection() throws Exception {
    // 创建字符串"Hello World" 并赋给引用s
    String s = "Hello World";
    System.out.println("s = " + s); // 打印出Hello World
    // 获取String类中的value字段————Field类获取成员变量
    Field valueFieldOfString = String.class.getDeclaredField("value");
    valueFieldOf
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值