Java字符串常量池

一、字符串的创建方式

  在介绍字符串常量池之前先说一下常见的字符串的创建方式:

  1. 字面量的方式
    String str = "test";
  2. new String的方式
    String str1 = new String("test");
  3. StringBuilder.toString的方式
    StringBuilder sBuilder = new StringBuilder();
    sBuilder.append("test");
    String str2 = sBuilder.toString();
  4. intern的方式

    String str3 = "test";
    String str4 = str3.intern();

二、 字符串常量池的实现方式

  字符串常量池是JVM帮我们实现的,底层是像hotspot、openJ9这些实现了JVM标准的虚拟机通过C++代码做的一个类似于HashTable 的结构,里面保存这字符串对象的引用。

三、为什么要设计一个字符串常量池

  1. 字符串是引用类型,字符串的内存分配和其他对象分配是一样的,先由检查类有没有加载,没有加载的话先通过双亲委派机制去加载这个类,只不过像String这种类是Java的核心类,所以由引导类类加载器(BootStrap ClassLoader)去加载,像我们自己创建的类则是通过应用程序类加载器(Application ClassLoader)去加载。类加载完了之后,会在堆区创建一个该类的java.lang.Class对象,然后由JVM分配一块内存,再把这块内容做一次置零操作,然后设置对象头,然后就执行初始化操作,这样一个对象就创建完了。在这个过程中会发现,JVM需要去分配内存,而字符串又是我们平时用得最多的一个类型,就会导致JVM频繁的去分配内存。所以为了减少内存开销,引入了字符串常量池。
  2. 引入了字符串常量池后,新建字符串时会先在池子中找,找到了直接返回引用,找不到就创建一个丢到池子中,然后返回池子中的引用,这样能在一定程度上节省一部分内存空间。

四、举例子

String a = "test";
String b = "test";
System.out.println(a==b); // true:a 和 b都是从池子中取的,所以他们的引用地址一致

String c = new String("haha");
String d = c.intern();
System.out.println(c==d);// false: new String得到的c会先把"haha"放到池子中,
//然后再像正常创建对象一样返回一个堆区的引用赋值c,
//但是intern方法会先取池子中找有没有一个字符串“haha"如果有就返回池子的引用,
//所以c 和 d的引用不相同。

String e = "ha";
String f = "h"+"a";
System.out.println(e==f); // true: 因为f在编译期间,编译器会认为你这个是固定的,
//再生成字节码的时候,会呈现String f = "ha"的状态

String g = "gh";
String h = "h";
String i = "g"+h;
System.out.println(g==i);// false:因为i在编译期间是无法确定的h的值,
//所以会将"g"和h连接后一个新的引用地址赋值给i

String s0 = "gh";
final String s1 = "h";
String s2 = "g"+s1;
System.out.println(s0==s2);//true:因为s1是常量修饰的,所以在编译期间是可以确定的s1的值,
//所以编译器会优化,从而在运行时,s0和s2都是池子中的引用

String str1 = new StringBuilder("in").append("t").toString(); //没有出现"int"字面量,
//所以不会在常量池里生成"int"对象
System.out.println(str1 == str1.intern()); //false:int是关键字,
//在JVM初始化的相关类里肯定早就放进字符串常量池了

五、扩展

  像Java中八种基本数据类型的包装类型,其中六种 Byte、Short、Integer、Long、Character、Boolean都是有自己的常量池,只不过Byte、Short、Integer、Long这四种的常量池通常只会有值小于127的对象,因为JVM认为这些数据比较常用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值