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. Spring Security详解

    Spring Security 一. 简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文 ...

  2. 公子奇带你进入Java8流的世界(一)

    在说流之前,我们先来看看集合,为什么呢?作为Java8中的新成员,它和集合有很多相似之处,同时它们也是可以互相转化的.集合不仅仅是Java语言,任何一门高级开发语言都有集合的概念,集合顾名思义,就是很 ...

  3. 洛谷P1035 级数求和 题解 简单模拟

    题目链接:https://www.luogu.com.cn/problem/P1035 题目描述 已知:\(S_n= 1+1/2+1/3+-+1/n\).显然对于任意一个整数 \(k\),当 \(n\ ...

  4. Groovy重载操作符

    重载一时爽,一直重载一直爽. 最近在读<Groovy in action>一本书重新复习了Groovy的一些语法特性,迷恋上这个重载操作符的功能,坚持爽的不要要的.分享一个Demo. 由于 ...

  5. Go并发编程

    概述 简而言之,所谓并发编程是指在一台处理器上"同时"处理多个任务. 随着硬件的发展,并发程序变得越来越重要.Web服务器会一次处理成千上万的请求.平板电脑和手机app在渲染用户画 ...

  6. oracle-按年、月、周、日、时、分 分组查询统计数据,无数据补零(connect by)

    目的:统计一段时间内每年.每月.每周.每日.每时.每分数据,无数据时自动补零 思路:1. 生成给定时间段对应日期 2. 将原表中该时间段内的不为0的数据量统计出来 3. 用left join连接起来, ...

  7. .Net Framework为什么需要联网?

    .Net Framework在安装时需要从微软官方网站下载语言包,所以需要联网. 如果想要真正离线安装,需要先把所需的语言包下载下来.

  8. c++ 快读快输模板

    快读 inline int read() { ; ; char ch=getchar(); ; ch=getchar();} )+(X<<)+ch-'; ch=getchar();} if ...

  9. 18个Java8日期处理的实践,对于程序员太有用了!

    18个Java8日期处理的实践,对于程序员太有用了! Java 8 推出了全新的日期时间API,在教程中我们将通过一些简单的实例来学习如何使用新API. Java处理日期.日历和时间的方式一直为社区所 ...

  10. iOS使用fastlane自动化打包到fir(最全最详细流程)

    # iOS使用fastlane自动化打包到fir(最全最详细流程)1. **首先确认是否安装了ruby,终端查看下ruby版本**> ruby -v终端输出:ruby 2.4.1p111 (20 ...