栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

关于字符串与字符串常量池

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

关于字符串与字符串常量池

JDK1.8-1.9,String底层从char数组变成了byte数组,原因是部分字符仅占一个byte,而堆中含有大量的String字符串,该优化能节省较多空间。

StringTable为什么要调整(移入堆内)(JDK1.6-1.7)

  • permSize默认比较小
  • 永久代垃圾回收频率低

字符串拼接操作

  • 常量与常量的拼接结果在常量池,原理是编译器优化
  • 常量池中不会存在相同内容的常量
  • 只要其中一个是变量,结果就在堆中。变量拼接的原理是StringBuilder(final不算变量),返回String对象
  • 如果拼接的结果调用intern()方法,则注定将常量池中还没有的字符串对象放入池中,并返回此对象地址

所以建议多使用final定义字符串

字符串的创建与常量池

String两种创建方式

String两种创建方式

  • 方式一(str值和字符串常量池中字面量地址相等)
String str = "abc"
  1. 检查字符串常量池是否存在该字符串,存在则不创建并且返回该字符串的引用
  2. 不存在则在字符串常量池中创建该字符串常量并返回其常量池中地址
  • 方式二(str值和字符串常量池中字面量地址不相等)
String str = new String("abc")
  1. 检查字符串常量池是否存在该字符串,存在则不创建,不存在则创建该字符串常量
  2. 在堆中创建该对象
  3. 返回堆中该对象的引用

普遍地

使用双引号方式显式存在的字符串,则直接放入字符串常量池中

一些测试(JDK1.8)

情况一:

    public static void main(String[] args) {
        String a1 = "a";
        String a2 = new String("b");
        String a3 = "c";
        String a4 = a1 + a2;
        String a5 = a1 + a3;
//        String at = "a"+"c";
//        String at1 = "a"+"b";

        System.out.println(IsInPool(a1));//true
        System.out.println(IsInPool("b"));//true
        System.out.println(IsInPool(a2));//false
        System.out.println(IsInPool(a3));//true

        System.out.println(IsInPool(a4));//true
        System.out.println(IsInPool("ab"));//true
        System.out.println(IsInPool(a5));//true
        System.out.println(IsInPool("ac"));//true
    }

情况二:

    public static void main(String[] args) {
        String a1 = "a";
        String a2 = new String("b");
        String a3 = "c";
        String a4 = a1 + a2;
        String a5 = a1 + a3;
        String at = "a"+"c";
        String at1 = "a"+"b";

        System.out.println(IsInPool(a1));//true
        System.out.println(IsInPool("b"));//true
        System.out.println(IsInPool(a2));//false
        System.out.println(IsInPool(a3));//true

        System.out.println(IsInPool(a4));//false
        System.out.println(IsInPool("ab"));//true
        System.out.println(IsInPool(a5));//true
        System.out.println(IsInPool("ac"));//false
    }

IsInpool函数

    public static boolean IsInPool(String str){
        return str == str.intern();
    }

对于intern函数的理解

调用这个方法之后就是去看当前字符串是否在常量池中存在

(1)存 在:那就直接返回该字符串在字符串常量池中所对应的地址给栈中要引用这个字符串的变量。

(2)不存在:
① jdk 1.6:先在字符串常量池中创建该字符串,地址与堆中字符串地址不相同。然后再返回刚创建的字符串在字符串常量池中所对应的地址给栈中要引用这个字符串的变量。

② jdk 1.7及以后:直接将堆中(不是字符串常量池中)该字符串的地址复制到字符串常量池中,这样字符串常量池就有了该字符串的地址引用,也可以说此时字符串常量池中的字符串只是一个对 堆中字符串对象的引用,它们两个的地址相同,然后再把这个地址返回给栈中要引用这个字符串的变量。

对测试的解释
  • 第一次两个拼接测试为true,因为intern函数将堆中字符串对象引用复制到字符串常量池中,所以二者自然相等
  • 第二次两个拼接测试为false,因为intern检查到已经存在该字符常量,且堆常量池中保存的是字符串的值,二者自然不相等
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/305821.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号