JAVA String对象和字符串常量的关系解析

1 字符串内部列表

JAVA中所有的对象都存放在堆里面,包括String对象。字符串常量保存在JAVA的.class文件的常量池中,在编译期就确定好了。 虚拟机为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合,包括直接常量(string、integer和float point常量)和对其他类型、字段和方法的符号引用。

例如,

String s = new String( "myString" );

其中字符串常量是"myString",在编译时被存储在常量池的某个位置。在解析阶段,虚拟机发现字符串常量"myString",它会在一个内部字符串常量列表中查找,如果没有找到,那么会在堆里面创建一个包含字符序列[myString]的String对象s1,然后把这个字符序列和对应的String对象作为名值对( [myString], s1 )保存到内部字符串常量列表中。如下图所示:

如果虚拟机后面又发现了一个相同的字符串常量myString,它会在这个内部字符串常量列表内找到相同的字符序列,然后返回对应的String对象的引用。维护这个内部列表的关键是任何特定的字符序列在这个列表上只出现一次。

例如,String s2 = "myString",运行时s2会从内部字符串常量列表内得到s1的返回值,所以s2和s1都指向同一个String对象。但是String对象s在堆里的一个不同位置,所以和s1不相同。

JAVA中的字符串常量可以作为String对象使用,字符串常量的字符序列本身是存放在常量池中,在字符串内部列表中每个字符串常量的字符序列对应一个String对象,实际使用的就是这个对象。

2 字符串截留intern

在某些上下文环境下,仅仅保留某个字符串的一份copy能够提高内存的使用和效率。String类的intern()方法可以截留字符串,如果String对象包含的字符序列不在字符串常量内部列表中,那么就把这个String对象包含的字符序列和String对象的引用作为名值对保存到内部列表中,最后intern()返回一个指向String对象本身的引用;如果 String对象包含的字符序列在字符串常量内部列表中,那么就返回列表的名值对中的对应的字符串对象引用,而String对象本身的就会被丢弃。

例如,s.intern()就会返回和s2相同的引用,而以前的s对象就会被垃圾回收。

使用intern()要注意,被放到字符串内部列表中的字符串对象是不会被垃圾回收的,生命周期和整个程序相同,所以如果使用不当会造成内存泄露。

JAVA String对象和字符串常量的关系解析的更多相关文章

  1. java 创建string对象机制 字符串缓冲池 字符串拼接机制

    对于创建String对象的机制,在这一过程中涉及的东西还是值得探究一番的. 首先看通过new String对象和直接赋值的方式有什么区别,看如下代码: public static void main( ...

  2. java 创建string对象机制 字符串缓冲池 字符串拼接机制 字符串中intern()方法

    字符串常量池:字符串常量池在方法区中 为了优化空间,为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池.如果字符串已经存在池中,就 ...

  3. Java——String对象

    前言 实际上任何语言都没有提供字符串这个概念,而是使用字符数组来描述字符串.Java里面严格来说也是没有字符串的,在所有的开发里面字符串的应用有很多,于是Java为了应对便创建了String类这个字符 ...

  4. 关于Java String对象创建的几点疑问

    我们通过JDK源码会知道String实质是字符数组,而且是不可被继承(final)和具有不可变性(immutable).可以如果想要了解String的创建我们需要先了解下JVM的内存结构. 1.JVM ...

  5. Java String对象的问题 String s="a"+"b"+"c"+"d"

    1, String s="a"+"b"+"c"+"d"创建了几个对象(假设之前串池是空的) 2,StringBuilde ...

  6. Java String对象的经典问题

     先来看一个样例,代码例如以下:  public class Test {       public static void main(String[] args) {           Strin ...

  7. Java String对象的经典问题(转)

    public class StringTest { public static void main(String[] args) { String strA = "abc"; St ...

  8. Java String 对象,你真的了解了吗?

    String 对象的实现 String对象是 Java 中使用最频繁的对象之一,所以 Java 公司也在不断的对String对象的实现进行优化,以便提升String对象的性能,看下面这张图,一起了解一 ...

  9. 深入理解java String 对象的不可变性

    下面我们通过一组图表来解释Java字符串的不可变性 1.声明一个String对象 String s = "abcd"; 2.将一个String变量赋值给另一个String变量 St ...

随机推荐

  1. Tomcat从安装到配置Https SSL证书

    为什么要写本文? 今天一个群友在群里问怎么给Tomcat配置SSL,也就是HTTPS,他买的阿里云的服务器,自带公网ip,还找到了免费的SSL证书 既然@我了,我就帮忙搞一搞呗,我就要了一个带sudo ...

  2. llinux重启、用户切换、注销命令

    一.指令 shutdown命令 shutdown -h now //立即关机 shutdown -h 2 //分钟后关机 shutdown -r now //立即重启 shutdown -r 1 // ...

  3. OSS上传图片无法在线预览的解决方案

    OSS上传图片无法在线预览的解决方案 最近在做的项目涉及到商品详情,由于前端用的flutter框架并且该详情为富文本,dart语言关于富文本的组件不是非常友好,当富文本中的图片无法在浏览器中直接预览的 ...

  4. JS单元测试及原理

    单元测试 单元测试是指对软件中的最小可测试单元进行检查和验证,通过单元测试可以检测出潜在的bug,还可以快速反馈功能输出,验证代码是否达到预期,也可以保证代码重构的安全性. 有这样一个方法: let ...

  5. Web及网络基础学习(一)

    ---恢复内容开始--- 2019.10.16 1.TCP.IP分层  应用层.网络层.传输层.数据链路层 2.各层讲解 应用层 决定了向用户提供应用服务时通信的活动.例如FTP(File Trans ...

  6. vnpy源码阅读学习(2):学习PyQt5

    PyQt5的学习 花费了一个下午把PyQt5大概的学习了下.找了一个教程 PyQt5教程 跟着挨着把上面的案例做了一遍,大概知道PyQt5是如何生成窗体,以及控件的.基本上做到如果有需求要实现,查查手 ...

  7. Spring Boot2 系列教程 (九) | SpringBoot 整合 Mybatis

    前言 如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,本文通过注解的形式实现. 什么是 Mybatis MyBatis 是支持定制化 SQL.存储过程以及 ...

  8. 区间dp - 全部按下一列石头

    There is one last gate between the hero and the dragon. But opening the gate isn't an easy task. The ...

  9. Core 定时任务之TimeJob

    第一:引入NuGet包: Install-Package Pomelo.AspNetCore.TimedJob -Version -rtm- 第二: 在StartUp 中注册Job: public c ...

  10. Vmware Ubuntu18.04更换清华源

    一.安装Ubuntu18.04 省略 二.安装VmwareTool 1.选择机器右击安装2.打开文件,copy压缩文件到其它目录(理由: 内存不够解压)3.解压文件,运行./忘记名字了.pl文件4.注 ...