举例说明串池和堆中的字符串

常量池:
就是*.class 文件中的一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量信息

运行时常量池:
常量池是 *.class 文件中的,当该类被加载以后,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址
StringTable 的位置

jdk1.6 StringTable 位置是在永久代中,1.8 StringTable 位置是在堆中。

因为永久代的垃圾回收效率不高,串池太多,常量池太大会撑爆,会报永久代内存不足。

所以1.8将串池放入堆中,如果串池太大会报堆内存不足

StringTable – 串池

在这里插入图片描述

  • 常量池中的信息,都会被加载到运行时常量池中。这时其中的字符串仅是符号,只有在被用到时才会转化为对象(懒加载)。
  • ldc会从运行时常量池中加载符号,从而变成字符串对象。并将其放入 串池 ,存储机制是哈希表,也就是不重复,传池中没有才放入

​ 利用串池 哈希存储的机制,来避免重复创建字符串对象

  • 字符串变量拼接a+b的原理是StringBuilder(1.8) //相当于 new StringBuilder().append(“a”).apend(“b”).toString(); == new String(“ab”) 。。。。在编译期间不能确定,所以在运行期间创建为堆中对象。

在这里插入图片描述

  • 字符串常量拼接的原理是编译器优化: 已经再编译期间确定为不变的字符常量,所以不会再变了。就放入常量池

在这里插入图片描述

  • intern方法 1.8
    • 调用字符串对象的 intern 方法,会将该字符串对象尝试放入到串池中
    • 1.8中 如果有该字符串对象,则放入失败,,如果串池中没有该字符串对象,则放入成功(同一个对象)
      无论放入是否成功,都会返回串池中的字符串对象
      注意:此时如果调用 intern 方法成功,堆内存与串池中的字符串对象是同一个对象;如果失败,则不是同一个对象
    • 1.6中 如果有该字符串对象,则放入失败,,如果没有,则会将对象复制一份,放入串池中(两个不同对象)

例1

public class Main {
	public static void main(String[] args) {
		// "a" "b" 被放入串池中,str 则存在于堆内存之中
		String str = new String("a") + new String("b");
        
		// 调用 str 的 intern 方法,这时串池中没有 "ab" ,则会将该字符串对象放入到串池中,此时堆内存与串池中的 "ab" 是同一个对象
		String st2 = str.intern();
        
		// 给 str3 赋值,因为此时串池中已有 "ab" ,则直接将串池中的内容返回
		String str3 = "ab";
        
		// 因为堆内存与串池中的 "ab" 是同一个对象,所以以下两条语句打印的都为 true
		System.out.println(str == st2);
		System.out.println(str == str3);
	}
}

例2:


public class Main {
	public static void main(String[] args) {
        // 此处创建字符串对象 "ab" ,因为串池中还没有 "ab" ,所以将其放入串池中
		String str3 = "ab";
        
        // "a" "b" 被放入串池中,str 则存在于堆内存之中
		String str = new String("a") + new String("b");
        
        // 此时因为在创建 str3 时,"ab" 已存在与串池中,所以放入失败,但是会返回串池中的 "ab" 
		String str2 = str.intern();
        
        // false   内存中 不等于 串池中
		System.out.println(str == str2);  
        // false   内存中 不等于 传池中
		System.out.println(str == str3);
        // true	   串池中  等于  串池中
		System.out.println(str2 == str3);
	}
}

面试题:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值