2021-08-17

String 字符串全面理解

它的本质

​ “Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings.Because String objects are immutable they can be shared”

​ 大致意思:字符串是一个常量,它们的值创建后无法更改,字符串缓冲区支持可变 字符串,因为字符串对象是不可变的,所以可以分享它们

1、String 的基本概念

1.1、字符串的定义

​ 字符串可以分为两大类:一类是创建之后不会再做修改和变动的字符串变量;另一类是创建之后允许再做修改的字符串变量

思考:为什么字符串创建后不会修改和变动,创建后可以修改的字符串变量是什么类?(下面一一解读)

1.2、字符串变量的创建

  • 格式一:
String s;				//声明字符串型引用变量s,此时s的值为null
s = new String("字符串");//在堆内存分配空间,并将s指向该字符串首地址
  • 格式二:
String s = new String("字符串");
  • 格式三
String s = "字符串"//声明字符串变量时直接初始化

由于字符串是引用类型变量,所以其存储方式与数组方式基本相同(详情在第3节)

1.3、字符串的拼接(+)

​ Java语言定义 “+” 运算符可以用于两个字符串的连接操作,如:

str = "Hello" + "Java";

如果字符串与其他类型的变量进行 “+” 运算,系统自动将其他类型数据转换为字符串型 ,如:

int i = 10;
String s = "s" + i		//结果为:"s10"

​ Tips:利用String类创建的字符串变量,一旦被初始化或赋值,它的值和所分配的内存内容就不可再改变,如果硬要改变它的值,就会产生一个新的字符串,如:

String str1 = "Java";
str1 = str1 + "Good";

​ 上面的过程再程序的解释过程:程序首先产生str1 的一个字符串对象并再内存中申请了一块空间,由于发现有需要重新赋值,再原来的空间已经不可能再追加新的内容,系统不得不将这个对象放弃,再重新生成第二个新的对象str1,并重新申请一个新的内存空间,虽然 str1 指向的内存地址是同一个,但对象已经不再是同一个了

2、String类解析

String 类被 final 修饰,所以String对象是不可变量,String类实现了Serializable,Comparable,CharSequence

2.1、 String的内部创建过程

方法一: 首先使用String的构造方法创建一个字符串

String s = new String("字符串");

​ debug进入String类中查看其创建该字符串的具体逻辑

//String的构造方法
public String(String original) { //original:"字符串"
        this.value = original.value; // value:{字,符,串}
        this.hash = original.hash;//hash:0  original:"字符串"
    }

这种创建方式会在堆内存中开辟内存空间,用来存放生成的字符数组,让我们来看另一种创建字符串的方法

方法二: 直接赋值创建 String

String s = "字符串";	//在编译期直接在常量池中创建字符串

tips:此处我们需要知道常量池(constant pool)的大致概念:在编译期被确定,并保存在已编译的.class文件中的一些数据,它包括了关于类、方法、接口等中的常量,也包括字符串常量,–常量池是JVM的一块特殊的内存空间。

总结

​ new String() 创建的字符串不是常量,不能在编译期就确定,所以 new String() 创建的字符串不放入常量池中,它们有自己的内存地址空间。

​ 直接赋值的字符串则是会在编译器确定下来,并存储在常量池中,由于String对象的不可变机制会导致修改 String 时产生大量对象,Java为了更有效的使用内存,常量池在编译期遇见直接赋值的String字符串,会检查池内是否已经存在相同的String字符串,如果有,把新变量的引用指向现有的字符串对象,不会创建任何新的String 常量对象,如果没找到就创建新的。

​ 所以对一个字符串对象的任何修改,都会产生一个新的字符串对象,原来的依然存在,等待垃圾回收

2.2、String的不可变

​ 在 String 类的开头有如下定义:

 /** The value is used for character storage. */
    private final char value[];

定义了一个字符数组,使用final修饰,final修饰的字符数组 char 创建后不可继承,因为String类被final修饰,其内部主要存储字符串的char 数组的访问修饰符为private,禁止用户对String 类进行继承,这些因素确保了String的不可变

3、String常量池问题的例子

转载自CSDN:https://blog.csdn.net/gaopeng0071/article/details/11741027

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值