JAVA String对象和字符串常量的关系解析
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 NIO Selector
- 朴素贝叶斯分类算法-----java
- Java的if判断对象为null时,null放在比较运算符的左边还是右边较好?
- 深度剖析Java集合之TreeMap
- 26dwr - DWR中的JavaScript(创造一个与 Java 对象匹配的 Javascript 对象)
- 新一代最强开源UI自动化测试神器Playwright(Java版)环境搭建
- Java对象创建、分配、布局、访问小析(HotSpot虚拟机)(一)
- Java final static
- Java对象序列化给分布式计算带来的方便
- 面试题:Java 对象的创建过程
- java main 方法
- Java-struts2的问题 java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
- 深入理解Java虚拟机——Hotpot虚拟机对象
- Java数组排序和查找
- 本地代码中使用Java对象
- 使用Java visualVM监控远程JVM
- 解析Java的JNI编程中的对象引用与内存泄漏问题
- JAVA_SE进阶day02面向对象高级
- Java高手速成 | 对象-关系的映射、映射对象标识符与JPA API的级联操作
- java选择控制语句和循环控制语句和C语言的有什么区别?
- Java新手入门200例121之通过Java反射创建类对象
- Java笔记10:Struts2简单Demo
- 资深互联网大佬的5000字吐血总结——Java面向对象三大修饰符之abstract、static、final
- 接口 C#/Java 请求数据 raw 的方式传输复杂对象
- Java //EX2.15 设page是Graphics类的一个对象,编写一条语句画一条从(20, 30)到(50, 60)的线
- java对象上转型总结