博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java字符串常亮池
阅读量:7252 次
发布时间:2019-06-29

本文共 2253 字,大约阅读时间需要 7 分钟。

hot3.png

http://blog.csdn.net/u010297957/article/details/50995869

概念:

1、常量池表(constant_pool table) 

        Class文件中存储所有常量(包括字符串)的table

        这是Class文件中的内容,还不是运行时的内容,不要理解它是个池子,其实就是Class文件中的字节码指令.

2、运行时常量池(Runtime Constant Pool)

        JVM内存中方法区的一部分,这是运行时的内容

        这部分内容(绝大部分)是随着JVM运行时候,从常量池转化而来,每个Class对应一个运行时常量池

        2中说绝大部分是因为:除了 Class中常量池内容,还可能包括动态生成并加入这里的内容

3. 字符串常量池(String Pool)

这部分也在方法区中,但与Runtime Constant Pool不是一个概念,String Pool是JVM实例全局共享的,全局只有一个

JVM规范要求进入这里的String实例叫“被驻留的interned string”,各个JVM可以有不同的实现,HotSpot是设置了一个哈希表StringTable来引用堆中的字符串实例,被引用就是被驻留

(JDK1.6字符串常量池在方法区中存储,JDK1.7中放在了堆。(不知道正确性在一个ppt中看到的,不过和上面这句话形容的一样。))

 

这里的使用了一种设计模式:享元模式。也就是说:一个系统中如果有多处用到了相同的一个元素,那么我们应该只存储一份此元素,而让所有地方都引用这一个元素。

. 描述

我觉的好像前面1和2随便说了点概念,就好像快说完了……

那么,来个Example吧!在*.java文件中有如下代码:

int a = 1;String b = "asd";
  1. 首先,1"asd"会在经过javac(或者其他编译器)编译过后变为Class文件中constant_pool table的内容

  2. 当我们的程序运行时,也就是说JVM运行时,每个Classconstant_pool table中的内容会被加载到JVM内存中的方法区中各自Class的Runtime Constant Pool

  3. 一个没有被String Pool包含的Runtime Constant Pool中的字符串(这里是"asd")会被加入到String Pool中(HosSpot使用hashtable引用方式),步骤如下:

    1. 在Java Heap中根据"asd"字面量create一个字符串对象
    2. 将字面量"asd"与字符串对象的引用在hashtable中关联起来,键 - 值 形式是:"asd" = 对象的引用地址

另外来说,当一个新的字符串出现在Runtime Constant Pool中时怎么判断需不需要在Java Heap中创建新对象呢?

策略是这样:会先去根据equals来比较Runtime Constant Pool中的这个字符串是否和String Pool中某一个是相等的(也就是找是否已经存在),如果有那么就不创建,直接使用其引用;反之,如上3

如此,就实现了享元模式,提高的内存利用效率

2. 例子

上面的描述其实对于能看到这篇文章的程序员们来说很好懂,下面我们来找一些面试题练练手吧

1. String s = new String(“abc”) 创建了几个对象?

答:

2个

解析:

  1. 首先,出现了字面量"abc",那么去String Pool中查找是否有相同字符串存在,因为程序就这一行代码所以肯定没有,那么就在Java Heap中用字面量"abc"首先创建1个String对象

  2. 接着,new String("abc"),关键字new又在Java Heap中创建了1个对象,然后调用接收String参数的构造器进行了初始化。最终s的引用是这个String对象

    如上:2个

2. 下面程序的输出?

public static void main(String[] args) {    String s1 = "abc";    String s2 = new String("abc");    String s3 = "a" + "bc";    System.out.println(s1 == s2);    System.out.println(s1 == s3);    System.out.println(s1 == s1.intern());}

答:

System.out.println(s1 == s2);//flaseSystem.out.println(s1 == s3);//trueSystem.out.println(s1 == s1.intern());//true

 

解析

  1. 首先,根据题1所述,这里同理,s1和s2肯定不是一个引用;

  2. 其次String s3 = "a" + "bc";这行代码最终是"abc",根据s1,它已经在String pool中了,所以s3和s1是引用的同一个对象;

  3. 最后,s1.intern()方法:将某个String对象在运行期动态的加入String pool(如果pool中已经有一个了就不加)并返回String pool中保证唯一的一个字符串对象的引用。 

    所以,还是会返回和s1同一个对象的引用,所以true;

转载于:https://my.oschina.net/u/3714931/blog/1558679

你可能感兴趣的文章
JVM 总体结构
查看>>
MySQL 教程分享
查看>>
php使用ffmpeg向视频中添加文字字幕
查看>>
标识符与关键字
查看>>
可视化展示工具-power map
查看>>
体育考试
查看>>
ubuntu搭建mediawiki
查看>>
jQuery给CheckBox全选与不全选
查看>>
uoj#274. 【清华集训2016】温暖会指引我们前行(LCT)
查看>>
[51nod1222] 最小公倍数计数(莫比乌斯反演)
查看>>
LeetCode - 37. Sudoku Solver
查看>>
公钥,私钥和数字签名这样最好理解
查看>>
SqlBulkCopy 类
查看>>
Java知多少(104)网络编程之统一资源定位符URL
查看>>
csu1811(树上启发式合并)
查看>>
spring 整合maven 定时任务调度,多个任务写法
查看>>
New Concept English Two 15 37
查看>>
L125
查看>>
poj2192
查看>>
json的内容回顾
查看>>