IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 从面试题中学习StringTable -> 正文阅读

[Java知识库]从面试题中学习StringTable

一、StringTable

??StringTable也叫串池,听名字就可以知道它和String的存储有关。在1.6,它是存在于永久代中的,到了1.7之后,StringTable被放在了堆中。
??为了说明StringTable,我使用了几个例子。

1.1 例一 字面量创建字符串

public static void main(String[] args){
    String s1 = "a"; 
    String s2 = "b";
    String s3 = "ab";
}

??在上面这段代码中,通过字符串字面量的方式新建了几个String。对于变量s1,s2,s3,我们都知道它们被存在了栈中。可是后面的字符串呢?它被存储在哪个地方呢?
??经过反编译,我们得到如下jvm指令。
例一
??这里的#2就是“a”,当类加载的时候,常量池中的信息会加载到运行时常量池中,此时的a,b,ab都还是符号,没有变成java对象。当运行此方法,执行到对应的代码时,才会将符号a变成“a”字符串对象,并将对象放入StringTable中。 需要注意的是,普通的java对象在类加载的时候就会生成并放入堆中,而这种方式生成的String不同,只有当执行到新建String的代码时才会生成字符串对象。
??StringTable是一个哈希表,长度固定,“a”就是哈希表的key。一开始的时候,会根据“a”到串池中找其对象,一开始是没有的,所以就会创建一个并放入串池中。串池为 [“a”]。
??执行到指令ldc #3时,会和上面一样,生成一个“b”对象并放入串池中,串池变为[“a”, “b”]。
??同样地,后面会生成“ab”对象并放入串池中。串池变为[“a”, “b”, “ab”]。

??小结一下:字面量创建字符串对象是懒惰的,即只有执行到相应代码才会创建相应对象(和一般的类不同)并放入串池中。如果串池中已经有了,就直接使用串池中的对象(让引用变量指向已有的对象)。串池中的对象只会存在一份,也就是只会有一个“a”对象。

1.2 例二 字符串变量拼接

??观察下面的代码,请问输出结果是什么?

	String s1 = "a";
    String s2 = "b";
    String s3 = "ab";
    String s4 = s1 + s2; 
    
    System.out.println(s3 == s4);  // false

??一样,先拿到反编译的jvm指令。
例二
??前面的指令我们已经很熟悉,观察行号为9的指令,这里是个new。这就说明s4的创建方式和s1、s2、s3不同,它是在堆里新建了一个对象,前面根据字面量创建的则是在串池中生成了字符串对象。
??观察行号9的指令后面的注释,可以知道这里是new了一个StringBuilder对象。接着看17,21,可以发现“s1 + s2”的方式是通过StringBuilder对象调用append方法实现的。
??最后看24,最后是调用了toString方法生成了新的字符串对象。

// StringBuilder中的toString方法
public String toString(){
    // 即根据拼接好的值,创建一个新的字符串对象
	return new String(value, 0, count);
}

??以上分析就想要说明:即当两个字符串变量拼接时,jvm会创建一个StringBuilder对象,利用其append方法实现变量的拼接。最后再通过其toString方法生成一个新的String对象。
??最后我们看输出结果,发现s3不等于s4,这说明s3指向串池中的“ab”对象,s4指向堆中的“ab”对象。这是两个不同的对象

1.3 例三 字符串常量拼接

??观察下面的代码,请问输出结果是什么?

	String s1 = "a";
    String s2 = "b";
    String s3 = "ab";
    String s4 = s1 + s2;
    String s5 = "a" + "b"; 
    
    System.out.println(s4 == s5); // false

??直接反编译:
例三
??可以看到s5的创建和s3一样。这也就是说,即两个字符串常量拼接时,最后的结果和直接用一个字符串字面量新建一个String一样,都是在串池里创建对应的对象。所以最后s4也是不等于s5的。
??至于为什么会以这种方式创建s5,这其实是编译期的优化。编译期间,编译器发现这是两个常量相加,结果是确定的,所以就直接让s5等于“ab”。

1.4 例四 intern方法

??接下来,我们来聊聊String的intern方法。

	String s = new String("a") + new String("b");
	String s2 = s.intern(); 
	
    System.out.println(s1 == "ab"); // true
	System.out.println(s == "ab")// false

??首先反编译。
例四
??反编译的结果我们也很熟悉,也是新建了一个StringBuilder实现字符串的拼接与创建。最终的结果就是在堆中创建了一个“ab”字符串对象。并且在串池中加入“a”,“b”对象。
??intern方法的作用就是在尝试把堆中对象放入串池中。如果串池中已有,会返回串池中的对象。并且s调用intern方法后依旧指向堆中的对象。如果串池中没有,会在串池中创建一个“ab”对象并返回,并且会让s指向串池中的“ab”对象。
??注意上面是jdk1.7之后的做法,在jdk1.6,当一个String调用intern方法时,如果串池中没有,会将堆中的字符串对象复制一份放到串池中,最后返回StringTable中刚加入的对象。

1.5 小结

  • 懒加载。当用字符串常量创建字符串时,在执行到对应的代码之前,该常量只是符号,只有执行到该代码时,才会创建相应的字符串对象并放入串池中。
  • 可以利用串池的机制,来避免重复创建字符串的对象。
  • 字符串变量的拼接的原理时StringBuilder (1.8)。
  • 字符串常量拼接的原理时编译期优化。
  • 可以使用intern方法,主动将串池中还没有的字符串对象放入串池( s.intern() )。

二、StringTable调优

??1)StringTable是一个哈希表,所以它的性能就和它的大小密切相关,所以StringTable调优其实就是调桶的个数。桶的数量越大,就越不容易产生哈希碰撞,效率就越好。可以通过 -XX:StringTableSize = …进行设置。
??2)考虑将字符串对象是否入池。如果要存的字符串过多并且很多重复,可以通过intern方法,把字符串从堆中入池,就可以减少字符串对象的个数,节约堆内存。
喜马拉雅山

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-04 13:15:32  更:2021-12-04 13:18:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:39:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码