Java String类相关知识梳理(含字符串常量池(String Pool)知识)

Posted 赖皮梅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java String类相关知识梳理(含字符串常量池(String Pool)知识)相关的知识,希望对你有一定的参考价值。

目录

1. String类是什么

  1.1 定义

  1.2 类结构

  1.3 所在的包

2. String类的底层数据结构

3. 关于 intern() 方法(重点)

  3.1 作用

  3.2 字符串常量池(String Pool)

4. String类所用的连接符

5. String类的主要作用(简)

 

正文

1. String类是什么

  1.1 定义

  String类表示字符串。Java程序中的所有字符串都是这个String的实例,比如"abc"。字符串为常数,它们的值在创建之后不能更改。因为字符串对象是不可变的,避免了现线程安全问题的出现,所以可以共享它们。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  问:“字符串为常数,它们的值在创建之后不能更改”——①这句话的具体表现(从String的使用角度出发)?②为什么要一经创建就不可更改?③怎么做到一经创建就不可更改的?

    答:

    ①通过调用String的方法我们可以发现,String并未真正提供“字符串的修改”方法,诸如replace这类的字符串替换方法,也只是创建一个新的字符串来替换,而非在原字符串上进行替换;

    ②这个问题从字符串的使用场景来解释比较好理解:从用户使用时的安全性考虑(线程安全),八种基本数据类型的“复制”是再新创建一份相同的数据,而String其实也相当于是一种基本的数据类型,只是它有引用,比较复杂一些,所以字符串要一经创建就不能更改。

    ③封装:虽然String的底层数据结构是char数组(数组的内容是可以更改的),但是,String将该字段声明为private,且并不对外暴露修改数组内容的方法。

  1.2 类结构

public final class String implements java.io.Serializable, Comparable<String>, CharSequence{……}

  ① final:String类不能被继承;

  ② Serializable:可序列化;

  ③ Comparable<String>:用于字符串之间的比较;

  1.3 所在的包:java.lang

  java.lang包是java语言的核心,它提供了java中的基础类。包括基本Object类、Class类、String类、基本类型的包装类、基本的数学类等等最基本的类。

 

2. String类的底层数据结构

private final char value[];//不可变的字符数组

  问1. 如果说String的底层数据结构是“不可变的char数组”,那不应该是声明为“ private final char[] value;”吗?

    答:这也是数组的一种声明方式,只是比较少见、少用,或许因为历史原因所以String保留使用着这种不常用的数组声明方式。

  问2. 不可变的字符数组的声明只能保证String对象的引用不可变,而用了char数组来作为存储结构,只能保证字符串一经声明其长度不可变,但是数组中存储的内容时可以改变的,从何保证字符串一经声明就不能再变呢?

    答:见 1.1的第③点;

  

3. 关于 intern() 方法(重点)

  3.1 作用:该方法用于返回字符串对象的规范表示形式。

public native String intern();// native方法,看不到具体实现。

  当调用intern方法时:

    ①如果字符串常量池中已经包含了一个由equals(object)方法确定的String对象的字符串,则返回池中的字符串。

    ②否则,将这个 String对象添加到池中(这是JDK1.8中intern()方法的注释给出的说明,但通过下面的测试,我认为是“将这个String对象的字符串添加到池中”会更好理解),并返回对这个String对象的引用。

    @Test
    public void test() {

        // 池中没有相应的字符串内容:
        String s1 = new String("hello");// 在堆中生成"hello"字符串对象
        String s2 = s1.intern();// 执行“s1.intern()”时,String Pool中没有"hello",会直接先将s1对象复制到池中
        System.out.println(s1 == s2); // false
        System.out.println(s1.intern()); // hello

        // 池中有:
        String s3 = "world"; // 直接在String Pool中生成"world"字符串
        String s4 = s3.intern(); // 从池中拿"world"字符串返回给s4
        System.out.println(s3 == s4); // true
    }

  3.2 字符串常量池(String Pool)

  字符串常量池最初是空的,由类 String私下维护。

  (1)在哪儿

    在JDK6及之前版本:字符串常量池是放在永久代中;

    在JDK7版本中:字符串常量池被移到了堆中。

  (2)数据结构

    在HotSpot VM中字符串常量池是通过一个StringTable类(一个Hash表,并非java实现类,所以知道即可)实现的;这个StringTable在每个HotSpot VM的实例中只有一份,被所有的类共享;

  (3)存放的内容

    在JDK6及之前版本:String Pool里放的都是字符串常量;

    在JDK7.0中:由于String.intern()发生了改变,因此String Pool中也可以存放放于堆内的字符串对象的引用。

  (4)特性:常量池中不存在两个相同的对象

  (5)字符串常量池存在的意义(为什么要有它?):避免字符串常量的重复创建,节省内存空间。

  (6)什么情况下生成的字符串才会被放到String Pool中?

    ① 字面量:代码中直接使用双引号引着的字符串都会被存储到字符串常量池中,如:String abc = "abc";;

    ② 调用String的 intern()方法,如果字符串内容是字符串常量池中没有的,那么会先复制一份内容到字符串常量池中;

 

4. String类所用的连接符

  Java语言为“+”连接符以及将对象转换为字符串提供了特殊的支持:

  字符串对象可以使用“+”连接其他对象。其实字符串连接是通过StringBuilder(或 StringBuffer)及其 append()方法 实现的。

  字符串转换是通过 toString()方法实现的,该方法由Object定义,并由Java中的所有类继承。

 

5. String类的主要作用(简) 

  ①检查序列的单个字符、
  ②比较字符串、
  ③搜索字符串、
  ④提取子字符串
  ⑤创建一个字符串的副本的方法,
  ⑥大小写转换;
  ⑦更多;

以上是关于Java String类相关知识梳理(含字符串常量池(String Pool)知识)的主要内容,如果未能解决你的问题,请参考以下文章

字符串相关类知识点总结

Java之String相关内容详解(字符串和字符串常量池)面试题

Java之String相关内容详解(字符串和字符串常量池)面试题

重新梳理IT知识之java-01语法

String类

java中StringStringBufferStringBuilder的总结