StringBuilder与String的区别

很久之前看过尚硅谷的视频,最近用到了所以想总结一下

1.String内存解析:

字符串不属于基本数据类型,但是可以通过字面量赋值”=”,也可以使用new关键字。
使用“=”与使用new关键字有很大的区别。
下面先介绍几个存储区域:
:存放引用(基本数据类型与对象的引用),是指向对象实际存储位置的指针(堆空间或者常量池)。
:对象的实际存储位置(使用关键字new创建),栈空间内的引用保存的是对应堆空间的内存地址。
常量池:存放显式的String常量和基本数据类型,常量池内的数据可以共享

public void testString(){
        String str1 = "abc";
        String str4 = "abc";
        String str2 = "def";
        String str3 = "abcdef";
        String str11 = str1 + "def";
        //从反编译中可得str5指向的是str5在堆空间中的内存地址(使用StringBuilder连接)
        String str5 = str1 + str2;
        String str6 = str5.intern();
        //str7的引用直接指向常量池中"abcdef"的内存地址
        String str7 = "abc" + "def";
        //结果为true,因为str1与str4("="赋值)指向的是常量池的内存地址,而常量池内的数据可以共享。当创建str1时因为常量池内没有"abc",创建str2是常量池内已存在"abc",所以不再重新创建
        System.out.println(str1 == str4);//true
        //str5使用操作符重载创建,并且"="右侧包含变量,其本质是使用StringBuilder(new 关键字)创建对象(可以使用javap命令查看反编译结果),所有str5指向的是堆空间的引用,而堆空间指向的是常量池
        System.out.println(str3 == str5);//false
        //intern()方法,查看api可以发现其返回字符串的规范化表达形式,当其被调用后,如果常量池中存在一个相同的字符串,那么直接返回这个字符串,否则将其添加到常量池中去,所以虽然str5指向堆空间,但是str6指向的是常量池
        System.out.println(str3 == str6);//true
        //str7虽然使用操作符重载,但是"="右侧没有变量
        System.out.println(str3 == str7);//true
        //与str5原理相同
        System.out.println(str11 == str3);//false
        System.out.println("str3's hasCode is:" + Integer.toHexString(str3.hashCode()));
        System.out.println("str5's hasCode is:" + Integer.toHexString(str5.hashCode()));
        System.out.println("str7's hasCode is:" + Integer.toHexString(str7.hashCode()));
        //final常量在编译后会直接替换为对应的值,在这种情况下编译器会直接将str8与str9合并
        final String str8 = "a";
        final String str9 = "bc";
        String str10 = str8+str9;
        //final常量在编译后会直接替换为对应的值,在这种情况下编译器会直接将str8与str9合并
        //编译后为String Str10 = "a" + "bc";
        System.out.println(str10 == str1);//true
    }

2.String与StringBuilder的区别
查看源码可发现String是final类,而StringBuilder不是final类

/**
     * 值传递与引用传递
     */
    @Test
    public void testStringBuilder(){
        StringBuilder str1 = new StringBuilder("a");
        StringBuilder str2 = new StringBuilder("b");
        String str3 = "a";
        String str4 = "b";
        append(str3, str4);
        append(str1, str2);
        System.out.println(str1 + " " + str2);//ab b
        System.out.println(str3 + " " + str4);//a b

    }
    /**
     * 
     * @param a
     * @param b
     *      调用此方法后,a的指针与str1相同,b与str2的指针相同
     *  StringBuilder是可变字符序列
     */
    public void append(StringBuilder a, StringBuilder b){
        //a.append(b),a的指针并没有改变,与str1相同
        a.append(b);
        //b的指针与str2相同,但是执行b = a操作后,b的指针指向了a在堆空间的内存地址,但是不会改变str2的指针
        b = a;
    }
    /**
     * 
     * @param a
     * @param b
     *      调用此方法后,a的指针与str1相同,b与str2的指针相同
     *  String为final类,不可变
     */
    public void append(String a,String b){
        //a与str1指针相同,但是String是final类,执行a=a+b后,a的指针会改变,str1的指针不会改变
        a = a + b;
        //执行b=a后,b的指针会改变,但是str2的指针并不会改变
        b = a;
    }

结合String内存解析,会深刻理解两者的区别

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值