String详解

String详解

String源码

private final char value[];

​ String的底层实现是靠char[]数组来实现的,因为加上了final修饰,也是就说value被赋值后是不能够指向别的空间的。所以说String对象是无法被修改的。

字符串常量池

​ 字符串常量池就是jvm对字符串的缓存。对于jdk8来说,常量池空间是在堆区的。由c++实现,本质就是一个HashTable,是有固定的长度的,所以大量字符串放入到pool里,势必会引起table里的链表变长,引起查找效率的低下。

代码分析

String a = "a"; //双引号的写法 只会在常量池里创建字符串对象
String a1 = new String("a"); //会在堆中创建一个对象,如果pool里没有还会在pool中创建
System.out.println(a == a1);  //false a指向pool里对象。a1指向堆里的对象

String a1 = new String("a"); //指向堆里的对象
String a2 = new String("a");  //指向堆里的对象
System.out.println(a1 == a2);  //false  两个对象在堆中占的空间不同

String c = "a" + "b";   //编译期被优化  直接就是“ab”  字节码如下图
String d = "ab";
System.out.println(c == d);  //true

image-20230420205653169


String a = "a";
String b = "b";
String c = "a" + b; //见字节码,编译期无法被优化,实际上是通过StringBuilder拼接出来
//String c = a + b. 同理 也会为false
String d = "ab";
System.out.println(c == d); //false  c指向堆  d指向常量池

image-20230420205914715


    public static void main(String[] args) {
        final String b = "b";  //final修饰即为常量 编译期间能被优化
        String c = "a" + b;
        String d = "ab";
        System.out.println(c == d);  //true  都指向常量池空间
    }

image-20230420210450643


    public static void main(String[] args) {
        String a = "a";
        String b = new String("b");
        String c = a + b;   //字节码通过StringBuilder拼接 在通过stringbuilder.toString() new出来的对象
        String d = "ab";
        System.out.println(c == d); //false.  c指向堆。d指向常量池
    }

    public static void main(String[] args) {
        String a = new String("a"); //两个对象 堆里一个  常量池里一个
        String b = "a";
        System.out.println(b == a.intern());//true
      //intern()方法:常量池里已经有“a”了,所以返回常量池里的引用
      //所以相等,因为b也指向的是常量池里的引用
    }

    public static void main(String[] args) {
        String a = new String("a") + new String("b");
        String b = "ab";
        System.out.println(a == b); //false. a指向堆里对象 b指向常量池
    }

//但是
    public static void main(String[] args) {
        String a = new String("a") + new String("b");
        a.intern();
        String b = "ab";
        System.out.println(a == b);  //true
      //a的赋值实际通过stringbuilder拼接,最后调用sb.toString(),会在堆里生成string对象,但是由于没有字面量“ab”所以不会在常量池里创建对象
      //a.inter()由于常量池里没有“ab”,对于jdk8,该方法会将“ab”在堆里的引用写进常量池,此时常量池里存的是堆对象“ab”的引用,所以后面给b赋值时,也是将常量池里保存的堆里ab的引用赋值给了b,所以a == b成立。
    }

intern()总结

  • 如果常量池里有,则返回常量池里字符串的引用
  • 如果常量池里没有,将堆里对象的引用写进常量池
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张嘉書

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值