zoukankan      html  css  js  c++  java
  • String和StringBuffer的一点研究

    转载自:http://www.cnblogs.com/heshan664754022/archive/2013/03/15/2961463.html


    首先请看下下面的这几个输出的结果,请仔细考虑,不要那么快回答!

    String str = new String("aaa");
     
    String str2 = new String("aaa");
     
    System.out.println(str == str2);
     
    System.out.println("----------------");
     
    String str3 = "bbb";
     
    String str4 = "bbb";
     
    System.out.println(str3 == str4);
     
      
     
    System.out.println("----------------");
     
    String str5 = new String("ccc");
     
    String str6 = "ccc";
     
    System.out.println(str5 == str6);
     
    System.out.println("----------------");
     
    String s = "hello";
     
    String s1 = "hel";
     
    String s2 = "lo";
     
    System.out.println(s == s1 + s2);
     
    System.out.println("----------------");
     
    System.out.println(s == "hel" + "lo");

      到了这里相信你已经做出了答案,正确的结果是:

      false   true  false  false    true

     

     下面让我们来仔细的分析下,首先是第一个

    String str = new String("aaa");
     
    String str2 = new String("aaa");
     
    System.out.println(str == str2);

      

    在看这道题的时候希望大家先看下下面这段原理性的描述

     

    String s = new String(“aaa”);

    1) 首先在String Pool中查找有没有“aaa”这个字符串对象,如果有,则不在String Pool中再去创建“aaa”这个对象了,直接在堆中(heap)中创建一个“aaa”字符串对象,然后将堆中的这个“aaa”对象的地址返回来,赋给s引用,导致s指向了堆中创建的这个“aaa”字符串对象。

    2) 如果没有,则首先在String Pool中创建一个“aaa“对象,然后再在堆中(heap)创建一个”aaa“对象,然后将堆中的这个”aaa“对象的地址返回来,赋给s引用,导致s指向了堆中所创建的这个”aaa“对象。

    看完上面这段描述,相信大家应该明白了吧 str和str2引用分别指向了堆中的不同对象,所以地址不同,结果当然为false

    然后第二个

    String str3 = "bbb";
     
    String str4 = "bbb";
     
    System.out.println(str3 == str4);

     在此之前我们同样也先看一段原理性的描述:

     

    String str3 = “bbb”;(采用字面值方式赋值)

    1) 查找String Pool中是否存在“bbb”这个对象,如果不存在,则在String Pool中创建一个“bbb”对象,然后将String Pool中的这个“bbb”对象的地址返回来,赋给引用变量str3 ,这样str3 会指向StringPool中的这个“bbb”字符串对象

    2) 如果存在,则不创建任何对象,直接将String Pool中的这个“bbb”对象地址返回来,赋给str3 引用。

    看完之后相信也不用我多说了吧,str3和str4引用指向了同一个对象地址,结果当然是true

    然后是第三个,相信如果你明白了前两个的话第三个就不用我多说什么了,如果不明白请先明白前两个。

    现在我们来看第四个

    String s = "hello";
     
    String s1 = "hel";
     
    String s2 = "lo";
     
    System.out.println(s == s1 + s2);

    在看这个问题时我们同样看一下一段原理性的描述:

    String是常量,其对象一旦创建完毕就无法改变。当使用+拼接字符串时,会生成新的String对象,而不是向原有的String对象追加内容。

     所以当s1+s2时其实是在堆里面重新创建了一个新的对象,所以s与s1+s2的地址是不一样的。

    对于最后一个问题

    System.out.println(s == "hel" + "lo");

    我的理解是JVM对于字符串常量的"+"号连接,将程序编译期,

    JVM就将常量字符串的"+"连接优化为连接后的值,拿"hel" + ”lo“来说,经编译器优化后在class中就已经是hello。

    在编译期其字符串常量的值就确定下来,存放在字符串常 量池中,故上面程序最终的结果都为true。

     下面附加一个Stringbuffer的题目:

    StringBuffer sb1 = new StringBuffer("hello"); 
    StringBuffer sb2 = new StringBuffer("hello");
    System.out.println(sb1.equals(sb2));
    不要回答是true哦,在StringBuffer里面没有重写equals方法,所以使用的是Object的equals方法,所以它们比较的是地址,结果当然是false了。

    总结:如果你能搞明白上面几个问题,相信你对String类有了一个更深的认识了,下面我们来总结一下:

    栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容

    堆中存放使用new关键字创建的对象.

    字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常量池中,而有的是运行时才被创建.使用new关键字,存放在堆中,我们要根据情况来判断,其实要是理解了原理一切类似的问题就迎刃而解。


  • 相关阅读:
    【flink】flink1.12 application mode on k8s
    【spark】读取高版本的elasticsearch
    [spark] spark2.4运行在k8s
    【spring】springboot使用jpa集成elasticsearch7.0
    【spark】cache不一定使用的场景
    JDK源码分析
    排序算法
    EagleEye鹰眼原理分析
    需求分析模版
    记一次线上事故内存泄漏:java.lang.OutOfMemoryError: unable to create new native thread
  • 原文地址:https://www.cnblogs.com/ycpanda/p/3637319.html
Copyright © 2011-2022 走看看