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类的主要作用(简) 

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

原文地址:https://www.cnblogs.com/laipimei/p/12177607.html

时间: 2024-10-29 19:06:47

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

常量池之字符串常量池String.intern()

运行时常量池是方法区(PermGen)的一部分. 需要提前了解: 1. JVM内存模型. 2. JAVA对象在JVM中内存分配 常量池的好处 常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享. - Java的自动装箱中其实就使用到了运行时常量池.详见:Java 自动装箱与拆箱的实现原理 - 还有字符串常量池. 字符串进入到常量池的两种方法: 1. new String()的实例调用intern()方法. ????执行intern()方法时,若常量池中不存在等值的字符串,JV

java值和地址值传递、字符串常量池的理解

#java值和地址值传递的理解: - 基本数据类型和基本数据类型的封装类都是:值传递 * 形式参数的改变不会影响实际参数的改变(相当于将值复制一份传递给形参,自身没做任何改变) - 引用数据类型都是 地址值传递 * 形式参数的改变会影响实际参数的改变(将地址值赋值给形参,形参就可以指向实参所指向的地址, 即形参也可以操作实参指向地址的数据了) #注意:String是个特例(当作基本类型处理) - 分析:从String类的源码可以知道,String相当于是char[]的封装类,即具有char类型的

Java字符串常量池是什么?为什么要有这种常量池?

简单介绍 Java中的字符串常量池(String Pool)是存储在Java堆内存中的字符串池.我们知道String是java中比较特殊的类,我们可以使用new运算符创建String对象,也可以用双引号("")创建字串对象. Java中的字符串常量池 下图,清楚地解释了如何在Java堆内存中维护字符串常量池,以及当我们使用不同的方式创建字符串时在堆内存中如何存放. 之所以有字符串常量池,是因为String在Java中是不可变(immutable)的,它是String interning

彻底弄懂字符串常量池等相关问题

前言: 在平时我们使用字符串一般就是拿来直接搞起,很少有深入的去想过这方面的知识,导致别人在考我们的时候,会问 String str = new String("123"); 这个一行代码执行创建了几个对象, String str1= str + new String("456");这行代码中str1存储在内存的哪个位置,堆or 字符串常量区(方法区)? 会把我们问的哑口无言了:哈哈哈哈,其实也不是水平问题,是我们平时可以仔细的去总结该类问题,下面就详细的对这类问题

对于JVM中方法区,永久代,元空间以及字符串常量池的迁移和string.intern方法

在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普遍的时候),类几乎是"静态的"并且很少被卸载和回收,因此类也可以被看成"永久的".另外由于类作为JVM实现的一部分,它们不由程序来创建,因为它们也被认为是"非堆"的内存. 在JDK8之前的HotSpot虚拟机中,类的这些"永久的"

String.intern()、字符串常量池

本文来自 唐大麦 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/soonfly/article/details/70147205?utm_source=copy 在翻<深入理解Java虚拟机>的书时,又看到了2-7的 String.intern()返回引用的测试. 其实要搞明白String.intern(),我总结了下面几条规则: 一.new String都是在堆上创建字符串对象.当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringT

Java中的字符串常量池

最近做到一个题目: 问题:String str = new String("abc"),"abc"在内存中是怎么分配的?    答案是:堆,字符串常量区. 题目考查的为Java中的字符串常量池和JVM运行时数据区的相关概念."abc"为字面量对象,其存储在堆内存中.而字符串常量池则存储的是字符串对象的一个引用. Java中的字符串常量池 Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid&qu

string字符串常量池在内存中的位置

这里仅仅是举个简单的样例说明字符串常量池在内存中的位置. 闲言少叙,直接上代码. Java代码   <span style="font-size: large;">import java.util.ArrayList; public class Test { public static void main(String[] args) { String str = "abc"; char[] array = {'a', 'b', 'c'}; String

C#之CLR内存字符串常量池(string)

C#之CLR内存字符串常量池(string) 投稿:shichen2014 字体:[增加 减小] 类型:转载 时间:2014-08-04我要评论 这篇文章主要介绍了C#之CLR内存字符串常量池(string),对于学习和理解C#内存原理很有帮助,需要的朋友可以参考下 C#中的string是比特殊的类,说引用类型,但不存在堆里面,而且String str=new String("HelloWorld")这样的重装也说没有的. 我们先来看一个方法: ? 1 2 3 4 5 6 7 8 cl