String 相关知识点总结

字符串的不可变性

概述

String 被声明为 final,因此它不可继承

在 Java8 中,String 内部使用 char 数组存储数据

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

在 Java9 之后,String 类的实现改用 byte 数组存储字符串,同时使用 coder 来表示使用了哪种编码。

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final byte[] value; /** The identifier of the encoding used to encode the bytes in {@code value}. */
private final byte coder;
}

value 数组被声明为 final,这意味着 value 数组初始化后就不能引用其他数组。并且 String 内部没有改变 value 的方法,因此可以保证 String 不可变。

字符串的连接

String s = "abcd";
s.concat("ef");

s 中保存的是一个重新创建出来的string对象的引用。

如果你需要一个可修改的字符串,应该使用StringBuffer 或者 StringBuilder。否则会有大量时间浪费在垃圾回收上,因为每次试图修改都有新的string对象被创建出来。

不可变的好处

1. 可以缓存 hash 值

因为 String 的 hash 值经常被使用,例如 String 用作 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。

2. String Pool 的需要

如果一个 String 对象以及被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。

3. 安全性

String 经常作为参数,String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中,String 被改变,改变 String 对象的那一方以为现在连接的是其他主机,而实际情况却不一定。

4. 线程安全

String 不可变性天生具备线程安全,可以在多个线程中使用。

String,StringBuffer,StringBuilder

1. 可变性

  • String 不可变
  • StringBuffer 和 StringBuilder 可变

2. 线程安全

  • String 不可变,因此是线程安全的
  • StringBuilder 不是线程安全的
  • StringBuffer 是线程安全的,内部使用 synchronized 进行同步

String Pool

字符串常量池(String Pool)保存着所有字符串的字面量(literal strings),这些字面量在编译时期就确定。不仅如此,还可以使用 String 的 intern() 方法在运行过程中将字符串添加到 String Pool 中。

当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串,并返回这个字符串的引用。

下面实例中,s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得一个字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中,然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。

String s1 = new String("aaa");
String s2 = new String("aaa");
System.out.println(s1 == s2); // false
String s3 = s1.intern();
String s4 = s1.intern();
System.out.println(s3 == s4); // true

如果是采用 "bbb" 这种字面量的形式创建字符串,会自动地将字符串放入 String Pool 中。

String s5 = "bbb";
String s6 = "bbb";
System.out.println(s5 == s6); // true

在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。

new String("abc")

使用这种方法会创建两个字符串对象(前提是 String Pool)中还没有 “abc” 字符串对象。

  • "abc" 属于字符串字面量,因此编译时期会在 String Pool 中创建一个字符串对象,指向这个 “abc” 字符串字面量;
  • 而使用 new 的方式会在堆中创建一个字符串对象。

    创建一个测试类,其 main 方法中使用这种方式来创建字符串对象。
public class NewStringTest {
public static void main(String[] args) {
String s = new String("abc");
}
}

使用 javap -verbose 进行反编译,得到以下内容:

// ...
Constant pool:
// ...
#2 = Class #18 // java/lang/String
#3 = String #19 // abc
// ...
#18 = Utf8 java/lang/String
#19 = Utf8 abc
// ... public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String abc
6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
// ...

在 Constant Pool 中,#19 存储这字符串字面量 “abc”,#3 是 String Pool 的字符串对象,它指向 #19 这个字符串字面量。在 main 方法中,0:行使用 new #2 在堆中创建了一个字符串对象,并且使用 ldc #3 将 String Pool 中的字符串对象作为 String 的构造函数的参数。

以下是 String 构造函数的源码,可以看到,在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容,而是都会指向同一个 value 数组。

public String(String original) {
this.value = original.value;
this.hash = original.hash;
}

参考

如有侵权,请联系删除!

【Java基础】String 相关知识点总结的更多相关文章

  1. Java基础String的方法

    Java基础String的方法 字符串类型写法格式如下: 格式一: String 变量名称; 变量名称=赋值(自定义或传入的变量值); 格式二: String 变量名称=赋值(自定义或传入的变量值); ...

  2. Java基础 String 裸暴力算法- 五个小练习

      之间的博客,承上启下:    Java基础 String/StringBuff 常用操作方法复习/内存分析 Java数组直接选择排序.sort()排序 Java基础 String 算法 - 五个练 ...

  3. Java基础—String构造方法

    Java基础--String构造方法 public String(): 创建一个空表字符串对象,不包含任何内容 public String(char[]chs): 根据字符数组的内容,来创建字符串对象 ...

  4. Java基础之疑难知识点

    问题列表: 1. Java中子类中可以有与父类相同的属性名吗? 2. Java中子类继承了父类的私有属性及方法吗? 3. Java中抽象类到底能不能被实例化? 1. Java中子类中可以有与父类相同的 ...

  5. 2.7w字!Java基础面试题/知识点总结!(2021 最新版)

    这篇<Java 基础知识总结>是 JavaGuide 上阅读量最高的一篇文章,由于我对其进行了重构完善并且修复了很多小问题,所以,在博客园再同步一下! 文章内容比较多,目录如下: 基础概念 ...

  6. Java基础 -- String,StringBuilder,StringBuffer三者的区别

    结论 1-String,StringBuilder,StringBuffer 之间的区别主要是在两个方面,即运行速度和线程安全这两方面: 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:St ...

  7. Java基础——String

    前言 从去年八月末开始工作一年了,有了大半年的java开发经验,自认为比在大学时期编码能力强了很多,但是基础方面概念模糊的地方感觉越来越多了 (:´д`)ゞ 所以,我准备把这些问题以及工作中遇到的问题 ...

  8. java基础 String

    标准格式:数据类型[] 数组名称 = new 数据类型[] {元素1,元素2,...};省略格式:数据类型[] 数组名称 = {元素1,元素2,...}; Scanner类实现的功能,可以实现键盘输入 ...

  9. java基础-String不可变的好处

    一.java内部String类的实现: java 8: public final class String implements java.io.Serializable, Comparable< ...

随机推荐

  1. go proxy athens 部署到k8s

    目录 go proxy athens 部署到k8s 一.athens简介 二.部署 1.创建 PersistentVolume 2.创建service 3.创建deployment 4.ci/cd中使 ...

  2. 利用python进行微信好友分析

    欢迎python爱好者加入:学习交流群 667279387 本文主要利用python对个人微信好友进行分析并把结果输出到一个html文档当中,主要用到的python包为itchat,pandas,py ...

  3. 洛谷 题解 P1351 【联合权值】

    Problem P1351 [联合权值] record 用时: 99ms 空间: 13068KB(12.76MB) 代码长度: 3.96KB 提交记录: R9883701 注: 使用了 o1 优化 o ...

  4. tensorflow word2vec详解

    maybe_download 下载text8.zip.可以手工下载下来.然后指定text8.zip的路径. read_data 解压text8.zip,把数据读入到data中. data是一个长数组, ...

  5. 虚拟链路(virtual-link)

    第四部分,虚拟链路配置.我们都知道,在ospf多区域中,所有与主干区域(ospf0)相连接的其他区域可以相互学系路由信息,但是,如果是非主干区域和非主干区域相连,就不能相互学习路由信息,这时候,我们可 ...

  6. 在VS2017中连接到SQLite数据源(dbfist)

    在VS2017中配置.连接到SQLite数据源(dbfist) 需要安装的VS插件 SQLite/SQL Server Compact ToolBox 这个插件安装后,在选择数据源时已经可以选择SQL ...

  7. python学习-price

    """登录功能:用户名和密码存在{'name':'huahua','pwd':'123456'}字典中,通过控制台输入用户名和密码判读是否正确,然后给出对应的提示消息:登 ...

  8. Java堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?

    JVM的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存.它在JVM启动的时候被创建.对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收. 堆内存是由存活和死亡的对象组成的.存活的对象是应 ...

  9. 在 VSCode 中 Angular 的字符串报错的问题

    使用 Angular 时,报错 [tslint] " should be ' 报错原因是因为 ESLint 的严格模式,限制了使用 ' ,甚至多一个空格都会报错. 我们只需要在 settin ...

  10. Docker 以及 docker-compose 的部署

    Docker部署 方式一 #下载软件源 wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.ustc.edu.cn/docker-ce/li ...