继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

java笔记-String、stringBuider、StringBuffer

幕布斯6054654
关注TA
已关注
手记 1258
粉丝 219
获赞 1011
先干个代码先
 private static void test01() {        String str1 = "hello world";        String str2 = new String("hello world");        String str3 = "hello world";        String str4 = new String("hello world");
        System.out.println(str1 == str2);//false
        System.out.println(str1 == str3);//true
        System.out.println(str2 == str4);//false
    }

运行结果

falsetruefalse
我知道你想问什么,别急往下看
  • 在class文件中有一部分来存储编译期间生成的字面常量以及符号引用,这部分叫做class文件常量池,在运行期间对应着方法区的运行时常量池。
    因此在上述代码中,String str1 = "hello world";和String str3 = "hello world"; 都在编译期间生成了字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池(当然只保存了一份)。通过这种方式来将String对象跟引用绑定的话,JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量,如果存在,则直接将引用指向已经存在的字面常量;否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。
    所以,通过new关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过new来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。

StringBuffer和StringBuider有什么不同

先截取哈各自的insert方法的代码
StringBuffer的insert

   /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @since      1.5
     */
    @Override
    public synchronized StringBuffer insert(int dstOffset, CharSequence s,            int start, int end)
    {
        toStringCache = null;        super.insert(dstOffset, s, start, end);        return this;
    }    /**
     * @throws StringIndexOutOfBoundsException {@inheritDoc}
     */

StringBuilder的insert:

    /**
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    @Override
    public StringBuilder insert(int dstOffset, CharSequence s,                                int start, int end)
    {        super.insert(dstOffset, s, start, end);        return this;
    }    /**
     * @throws StringIndexOutOfBoundsException

总结:的确,stringBuffer 是线程安全的

性能比较

* 对于直接相加字符串,效率很高,因为在编译器便确定了它的值,也就是说形如"I"+"love"+"java"; 的字符串相加,在编译期间便被优化成了"Ilovejava"。这个可以用javap -c命令反编译生成的class文件进行验证。
  对于间接相加(即包含字符串引用),形如s1+s2+s3; 效率要比直接相加低,因为在编译器不会对引用变量进行优化。
  * String、StringBuilder、StringBuffer三者的执行效率:
StringBuilder > StringBuffer > String

注意:

当然这个是相对的,不一定在所有情况下都是这样。
比如String str = "hello"+ "world"的效率就比 StringBuilder st  = new StringBuilder().append("hello").append("world")要高。
因此,这三个类是各有利弊,应当根据不同的情况来进行选择使用:
当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;
当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。

附加一个有意思的面试题(鄙人认为的)

问: String str = new String("abc")创建了多少个对象?


分析: 首先必须弄清楚创建对象的含义,创建是什么时候创建的?这段代码在运行期间会创建2个对象么?毫无疑问不可能,用javap -c反编译即可得到JVM执行的字节码内容

webp

image.png


很显然,new只调用了一次,也就是说只创建了一个对象。

  而这道题目让人混淆的地方就是这里,这段代码在运行期间确实只创建了一个对象,即在堆上创建了"abc"对象。而为什么大家都在说是2个对象呢,这里面要澄清一个概念  该段代码执行过程和类的加载过程是有区别的。在类加载的过程中,确实在运行时常量池中创建了一个"abc"对象,而在代码执行过程中确实只创建了一个String对象。
  因此,这个问题如果换成 String str = new String("abc")涉及到几个String对象?合理的解释是2个。
  个人觉得在面试的时候如果遇到这个问题,可以向面试官询问清楚”是这段代码执行过程中创建了多少个对象还是涉及到多少个对象“再根据具体的来进行回答。



作者:一个喜欢烧砖的人
链接:https://www.jianshu.com/p/b4f520e761fb


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP