sharky的點(diǎn)滴積累

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            56 隨筆 :: 104 文章 :: 10 評(píng)論 :: 0 Trackbacks

                網(wǎng)上關(guān)于String類(lèi)一些有關(guān)問(wèn)題的討論很多,在這里自我總結(jié)一下。希望對(duì)剛開(kāi)始學(xué)Java的朋友一對(duì)幫助。

          【問(wèn)題一:字符串的引用比較問(wèn)題】
          先看個(gè)例子,大家預(yù)測(cè)下結(jié)果:
          例1
          package base;

          public class StringTest
          {
              public static void main(String[] args) 
             {
              String A = "test";
              String B = "test";
              String C = new String("test");
              String D = new String("test");
              System.out.println("A==B?" + (A == B));
              System.out.println("C==D?" + (C == D));
              System.out.println("C==A?" + (C == A));
              System.out.println("C equals D?" + (C.equals(D)));

            }
          }

          運(yùn)行結(jié)果:
          A==B? true
          C==D?false
          C==A?false
          C equals D?true

          幾點(diǎn)認(rèn)識(shí):

          1.引用之間的“=="操作符,表示比較兩邊引用是否相等,即是否指向同一個(gè)對(duì)象。
          2.對(duì)于"String A = "test""這樣建立的字符串對(duì)象,如果在下次"String B = "test"",如果內(nèi)容一樣,JVM就不會(huì)在創(chuàng)建新的對(duì)象,而是簡(jiǎn)單地把新的引用指向已經(jīng)存在的對(duì)象(編譯時(shí))。(即便是在不同的包中)
          3.String.equals(String)是比較字符串的內(nèi)容。

          理解這幾點(diǎn),通過(guò)分析,很快得出上例結(jié)果。
          這里再給出個(gè)例子
          例2.

          String s1 = "I love Java";
          String s2 = "I love ";
          String s3 = "Java";
          String s4 = s2 + s3;
          String s5 = "I love "+"Java";

          if (s1 == s4) System.out.println("yes");
          else System.out.println("no");

          if (s1 == s5) System.out.println("yes");
          else System.out.println("no");

          運(yùn)行結(jié)果:
          no
          yes

          分析:s2+s3雖然其內(nèi)容也是"I love Java",但是s4 的值是運(yùn)行后出來(lái)的,不是編譯的時(shí)候。JVM只是把編譯時(shí) "=" 方式創(chuàng)建的 String 對(duì)象優(yōu)化為內(nèi)容相同時(shí)指向相同的對(duì)象實(shí)體。而當(dāng)一個(gè)字符串由多個(gè)字符串常量連接而成時(shí),在編譯期就解析為一個(gè)字符串常量。s5就是這樣,自然打出"yes"。
                  有的說(shuō)String+String中的"+"時(shí)JVM自動(dòng)重載的,用于連接字符串,String s1="java"是對(duì)"="的重載,重載為創(chuàng)建一個(gè)對(duì)象,并把對(duì)象地址賦給引用。本質(zhì)是一樣。




          ----------------------------------
          【問(wèn)題二:Java的參數(shù)傳遞問(wèn)題】
          引出:論壇上一個(gè)朋友提出的一道華為的面試題:

          例3:
          package test;

          public class TestString {
          public TestString() {
          }

          public static void main(String[] args) {
          String s=new String("Hello");
          modify(s);
          System.out.println("s = "+s);
          }

          public static void modify(String s)
          {
          s+="world";
          }
          }


          運(yùn)行結(jié)果:
          s = Hello
          為什么是輸出Hello,而不是Helloworld?謝謝

          ------------------------

          首先要確認(rèn)的幾點(diǎn)認(rèn)識(shí):
          1.引用不是對(duì)象,它沒(méi)有屬性和方法,而是指向某一個(gè)對(duì)象的變量,跟基本數(shù)據(jù)類(lèi)型的變量意義一樣。(引用是C中指針的隱藏化)

          例4:
                       String a ="Hello World";
                      String b =a;

          分析:a,b是不同的引用變量,但是都是指向同一個(gè)對(duì)象,即對(duì)象"String World"。a,b都是存放了同一個(gè)對(duì)象的地址,而這個(gè)地址指向內(nèi)存域存放的是"Hello World".

          2.Java中的參數(shù)傳遞都是值傳遞,都是拷貝式的,基本數(shù)據(jù)類(lèi)型是這樣,不用多說(shuō),當(dāng)傳入的參數(shù)是一個(gè)對(duì)象的引用時(shí),也時(shí)值傳遞,只不過(guò)傳遞的"值",非對(duì)象本身,而是對(duì)象雜在內(nèi)存中的地址。
                 所以在例1中:modify(String s)的"s"得到是String s=new String("Hello")中的"s"的引用值拷貝.

          3. String是常量性的,看看JDK文檔里面怎么說(shuō)String的吧,“Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared”。String的內(nèi)容是無(wú)法改變的,如果需要改變,要考慮用StringBuffer。

          例5:
                   1、 String s = "Hello";
                   2、 String s1 = s;
                   3、 s1 += "World!";

          分析:
                1->2步:s1和s這兩個(gè)引用,都指向同一個(gè)字符串對(duì)象"Hello",此時(shí)有2個(gè)引用,1個(gè)對(duì)象
               第3步:   由于String的不可更改性,所以“+=”操作后面操作是:返回一個(gè)新的字符串"HelloWorld",并把這個(gè)新的字符串的地址給引用s1,而引用s仍然引用原來(lái)的"Hello"。
          此時(shí),有2個(gè)引用("s","s1"),兩個(gè)字符串對(duì)象("Hello","HelloWorld")。大家要記?。篠tring的值的改變其實(shí)是創(chuàng)建一個(gè)新的String對(duì)象.
           即:
                      s1 += "World!";

                     s1 = new String("HelloWold")
          語(yǔ)義上是等價(jià)。

          何為語(yǔ)義?   簡(jiǎn)單的說(shuō)就是”你這條語(yǔ)句背后到底讓編譯器做了些什么?“

          這里在提及一個(gè)例子
          例6.

          public class Test
          {
            StringBuffer a ;
            public static void main(String[] args)
            {
             Test test = new Test();
             test.a = new StringBuffer("Hello");
             test.test(test.a);
             
             System.out.println("a is "+ test.a);
             
            }
            
            public  void test(StringBuffer strbuf)
            {
             strbuf.append("World");
             System.out.println(strbuf == a);

            }

          運(yùn)行結(jié)果:

          true
          a is HelloWorld

                   那這里"strbuf==a",怎么又為true了呢,并且"a is HelloWorld"了,按上面的道理,不是不會(huì)修改數(shù)據(jù)源嗎?注意我們這里運(yùn)用的是StringBuffer,不同于String,它能修改自己的內(nèi)容。test方法中傳入的strbuf引用的值為a引用值的拷貝值,但是strbuf.append("World")這句話(huà),是通過(guò)引用的值,修改了該值指向?qū)ο蟮膬?nèi)容,a可以調(diào)用append修改,strbuf自然也可以。所以,最后打印出a的值是strbuf修改后的對(duì)象的值。好比往test方法中傳入的一個(gè)可以操作a所指對(duì)象的"句柄",可以讓方法里的代碼操作目的對(duì)象。

                   如果理解上面幾點(diǎn),理解起來(lái)例3為什么是"Hello",我想就比較容易了。
          所以通過(guò)這個(gè)問(wèn)題,也告訴我們,在學(xué)習(xí)語(yǔ)言基礎(chǔ)的時(shí)候,不光要讀懂這個(gè)語(yǔ)句怎么寫(xiě),更應(yīng)該通過(guò)現(xiàn)象看本質(zhì),了解語(yǔ)句背后編譯器做了些什么,尤其是內(nèi)存分配上的操作。雖然Java淡化了內(nèi)存有關(guān)的概念,但是了解更多機(jī)制,會(huì)幫我對(duì)計(jì)算機(jī)編譯代碼的了解更深一個(gè)層次。

          -------------------------------

          相關(guān)問(wèn)題的參考:
          http://www.ideagrace.com/html/doc/2005/09/19/00626.html

          http://www.matrix.org.cn/thread.shtml?forumId=1&topicId=1142&page=1

          http://www.matrix.org.cn/thread.shtml?forumId=1&topicId=27155&page=1

          posted on 2005-10-02 12:17 sharky的點(diǎn)滴積累 閱讀(321) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 中方县| 张掖市| 福安市| 施甸县| 长海县| 弥渡县| 鄂托克旗| 浏阳市| 黔江区| 忻州市| 乳山市| 仁怀市| 酒泉市| 宽甸| 苗栗县| 河北省| 西贡区| 肃宁县| 丹东市| 印江| 织金县| 汶上县| 阿城市| 安西县| 东明县| 新巴尔虎左旗| 壶关县| 贞丰县| 扎兰屯市| 保靖县| 伊吾县| 盐边县| 探索| 鹰潭市| 安乡县| 新津县| 加查县| 拜城县| 青龙| 舒兰市| 松原市|