常量池与Strinig.intern()

常量池


  • 为什么要使用常量池?
    从内存上:合并相同的字面量,减少不必要的内存空间;
    从时间上:对于字符串的比较,对常量池中的字符串使用“==”判断引用是否相等比equals快。
1. Class文件常量池

 编译器间生成的字面量与符号引用1,在类加载后移至运行时常量池,保存在方法区中。

2. 运行时常量池

 除Class常量池的内容,运行时也可将常量加入常量池中,存储在方法区中(元空间)。每个类都有一个。

3. 全局字符串常量池

 全局字符串常量池在虚拟机中唯一,被所有类共享。存放在堆中

常量池加载过程

  1. 编译 —> 字面量与符号引用存入Class文件常量池
  2. 加载阶段 —> 转存入运行时常量池
  3. 准备阶段 —> 在堆中创建类变量的字符串实例,再将引用值存储到String Pool中,被所有类共享。
  4. 解析阶段 —> 将符号引用转换为直接引用,查询String Pool,以确保运行时常量池与全局字符串常量池的引用是一致的。
String.intern()方法与常量池
String.intern
String是否存在于常量池中
Y
返回该常量的引用
N
将当前对象的引用复制到常量池,返回改引用
String a1="AA";
System.out.println(a1==a1.intern());
String a2=new String("B")+new String("B");
a2.intern();
String a3=new String("B")+new String("B");
System.out.println(a2==a3.intern());
System.out.println(a3==a3.intern());
String a4="BB";
System.out.println(a2==a4);
System.out.println(a2==a3);
String a5="B"+"B";
System.out.println(a4==a5);
/**
true:在堆中创建"AA"的实例,同时将引用放在常量池中;常量池中有值,所以a1.intern()返回的是a1的引用。
true:字符串连接符"+",本质上是调用了StringBuilder.append().toString方法。会在堆中创建"BB"对象,
调用intern()方法之后在常量池复制"BB"的引用,因此a3.intern()调用的是a2的引用。
flase:a3是自己在堆中创建的对象,a3.intern()是a2存储在常量池中的对象
true:a4直接调用常量池的引用
flase:a2与a3在堆中的对象不同
true:虚拟机针对字面量"B"+"B"会在编译器优化为"BB",因此相等。
*/

    1. 类和接口和全限定名:例如对于String这个类,它的全限定名就是java/lang/String。
    2. 字段的名称和描述符:所谓字段就是类或者接口中声明的变量,包括类级别变量(static)和实例级的变量。
    3. 方法的名称和描述符。所谓描述符就相当于方法的参数类型+返回值类型。
    ↩︎
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值