当前位置: 首页 > article >正文

String常量池

Java常量池划分: 

  • 字面量:给基本类型变量赋值的方式就叫做字面量或者字面值。 比如:String a=“b” ,这里“b”就是字符串字面量,同样类推还有整数字面值、浮点类型字面量、字符字面量。
    用final修饰的成员变量、静态变量、实例变量、局部变量
  • 符号引用:类和接口的全限定名(Full Qualified Name),也就是Ljava/lang/String;,主要用于在运行时解析得到类的直接引用
    字段的名称和描述符(Descriptor),字段也就是类或者接口中声明的变量,包括类级别变量(static)和实例级的变量
    方法的名称和描述符
  • 字符串常量池:字符串常量池里的内容是在类加载、验证、准备阶段之后在堆中生成字符串对象实例,然后将该字符串对象实例的引用值存到string pool中。 
    在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个哈希表。
    这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享。

new String("hello")做了什么:

在字符串常量池中创建一个字符串hello。
new关键字创建一个实例对象String,并指向字符串常量池hello的引用。

注意:

String s1 = new String("he") + new String("llo");

s1涉及动态拼接,底层调用StringBuilder.append("he").append("llo").toString();,StringBuilder拼接后的toString()方法不会将字符串存入常量池,只会在堆中创建新对象

这种情况也不会放入常量池:

String s6 = new String(new char[]{'h', 'e', 'l', 'l', 'o'});
String s7 = s6.intern();

在构建String s6的时候,使用new String(new char[]{'h', 'e', 'l', 'l', 'o'})初始化字符串时(不会自动调用intern(),字符串采用懒加载方式进入到常量池),并没有在字符串常量池中构建hello这个字符串实例。
所以当调用s6.intern()方法时,会把该String对象添加到字符常量池中,并返回对该String对象的引用,所以s6和b指向的引用地址是同一个。

intern()方法做了什么:

intern()方法的作用是:拿String的内容去Stringtable里查表,如果存在,则返回引用,不存在,就把该对象的"引用"保存在Stringtable表里,注意并不会新建对象。

注意:JDK1.6及以前,字符串常量池在永久代里,StringTable不存在时,会在永久代上新建一个实例,并存入常量池中;
JDK1.7及以后,字符串常量池挪到了堆里,因此,JDK 7(以及部分其他虚拟机,例如JRockit)的intern()方法实现就不需要再拷贝字符串的实例到永久代了,既然字符串常量池已经移到Java堆中,那只需要在常量池里记录一下首次出现的实例引用即可,即不存在不会复制,直接返回堆中对象的地址,堆中对象的地址和常量池中的地址是一样的。

下面这段代码:

String s1 = new String("he") + new String("llo");
//涉及动态拼接,底层调用
//StringBuilder.append("he").append("llo").toString();
//StringBuilder拼接后的toString()方法不会将字符串存入常量池,所以上述JDK1.7为true
String s2 = s1.intern();//s1.intern()返回的仍是s1的引用地址
System.out.println(s1 == s2);// jdk1.7及以后true,jDK1.6及以前false

jdk6:

jdk7:

例子: 

public static void main(String[] args) {
	String s1 = new String("he") + new String("llo");// 涉及动态拼接,底层调用StringBuilder.append("he").append("llo").toString();
	// StringBuilder拼接后的toString()方法不会将字符串存入常量池,所以上述JDK1.7为true,s1.intern()返回的仍是s1的引用地址
	String s2 = s1.intern();
	System.out.println(s1 == s2);    // jdk1.7及以后true,jDK1.6及以前false

	System.out.println("=============================");
	
	String s3 = "hello";
	String s4 = new String("he") + new String("llo"); // 涉及动态拼接,底层调用StringBuilder.append("he").append("llo").toString();
	String s5 = s1.intern();
	System.out.println(s4 == s5);    // jdk1.7及以后false,jDK1.6及以前false

	System.out.println("=============================");

	String s6 = new String(new char[]{'h', 'e', 'l', 'l', 'o'});
	String s7 = s6.intern();
	System.out.println(s6 == s7);// true

	System.out.println("=============================");

	String s8 = new String("hello");
	String s9 = s8.intern();
	System.out.println(s8 == s9);// false
}


http://www.kler.cn/a/372652.html

相关文章:

  • 电子信息-毕业设计选题推荐
  • 项目里MongodbTemplate用法
  • Docker:容器化和虚拟化
  • kubernetes——part2-3 使用RKE构建企业生产级Kubernetes集群
  • Java 锁机制
  • Qt——信号和槽
  • 【秋招笔试-支持在线评测】10.30花子秋招(已改编)-三语言题解
  • Codeforces Global Round 27 D.Yet Another Real Number Problem
  • 双11来了,云计算优惠大集合
  • android 10 后台启动activity
  • Unity Editor 快速移动资源
  • VB中如何创建和使用自定义控件
  • 【动手学电机驱动】 STM32-FOC(1)IHM03 电机控制套件的介绍
  • 微服务技术,SpringCloudAlibaba,Redis,RocketMQ,Docker,分库分表
  • 基于SSM+VUE园艺生活植物网站JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解
  • 一七一、React性能优化方式
  • 计算机网络(Ⅴ)网络核心
  • 【ChatGPT】让ChatGPT帮助进行头脑风暴与创意生成
  • 指针进阶(四)(C 语言)
  • Java项目实战II基于Spring Boot的火锅店管理系统设计与实现(开发文档+数据库+源码)
  • gpio子系统-通过io来控制gpio
  • 详解:单例模式中的饿汉式和懒汉式
  • lego-loam mapOptmization 源码注释(一)
  • Lua语法基础全面剖析(中篇)
  • uni-app应用级生命周期和页面级生命周期
  • huggingface之tokenization基础结构Trie-代码解读