珊珊老师 的笔记

做最负责任的教育~我是执行者珊珊

2024-10-29 14:56

String 类详解:字符串操作的必备知识

珊珊老师

JavaEE

(88)

(0)

收藏

基本概念

java.lang.String 类用于描述字符串,Java程序中所有的字符串面值都可以用该类的对象加以描述。


该类由 final 关键字修饰,表示该类不能被继承。

从 jdk1.9开始该类的底层不使用 char[] 来存储数据,而是改成 byte[] 加上编码标记,从而节约了一些空间。

该类描述的字符串内容是个常量,不可更改,可以被共享使用。


创建字符串 String:

// 方式一:使用常量串构造
String str = "Hello Bit";
// 方式二:直接newString对象
String str2 = new String("Hello Bit");
// 方式三:使用字符数组进行构造
char[] array = {'a', 'b', 'c'};
String str3 = new String(array);

字符串常量池

常量池(了解):由于String 类型描述的字符串内容是常量不可改变,因此 Java 虚拟机将首次出现的字符串放入常量池中,若后续代码中出现了相同字符串内容则直接使用池中已有的字符串对象而无需申请内存及创建对象,从而提高了性能


在下面的例子中, String类的两种实例化操作, 直接赋值和 new 一个新的 String


(1)直接赋值

String str1 = "hello" ;
String str2 = "hello" ;
String str3 = "hello" ;
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // true
System.out.println(str2 == str3); // true

image.png


为什么现在并没有开辟新的堆内存空间呢?

String类的设计使用了共享设计模式

在JVM底层实际上会自动维护一个对象池(字符串常量池)

  • 如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中.

  • 如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用

  • 如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用

理解 "池" (pool)

"池" 是编程中的一种常见的, 重要的提升效率的方式, 我们会在未来的学习中遇到各种 "内存池", "线程池", "数据库连接池" ....

举个栗子:

假如 A 对象为 B ,并且同时还有一个备胎 C,当 A 与 B 分手之后,A 就可以立即找 C接盘,这样 脱单效率比较高,如果 A 不止一个备胎的话,那么我们就称这些备胎就称为 备胎池。


(2)采用构造方法

类对象使用构造方法实例化是标准做法。分析如下程序:

String str = new String("hello") ;

image.png


这样的做法有两个缺点:

  • 如果使用String构造方法就会开辟两块堆内存空间,并且其中一块堆内存将成为垃圾空间(字符串常量 "hello" 也是一个匿名对象,用了一次之后就不再使用了, 就成为垃圾空间, 会被 JVM 自动回收掉).

  •  字符串共享问题。 同一个字符串可能会被存储多次,比较浪费空间。我们可以使用 String 的 intern 方法来手动把 String 对象加入到字符串常量池中

// 该字符串常量并没有保存在对象池之中
String str1 = new String("hello") ;
String str2 = "hello" ;
System.out.println(str1 == str2);
// 执行结果
false
 
String str1 = new String("hello").intern() ;
String str2 = "hello" ;
System.out.println(str1 == str2);
// 执行结果
true

image.png



因此我们就可以知道String类中两种对象实例化的区别

  1.  直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。

  2.  构造方法:会开辟两块堆内存空间,不会自动保存在对象池中,可以使用intern()方法手工入池。


0条评论

点击登录参与评论