posts - 3,  comments - 7,  trackbacks - 0
          題目:String s = new String("xyz"); 這么一題簡單的java筆試題,對于java新手來說可能會做錯,看只要是PAPER,看一遍,聽人家講一遍就知道了。
          問:執行這一語句,一共創建了幾個String對象?
          答:2個,1個在String池中,一個在堆內存中。

          但其實這題目具有很大的靈活度,如果不真正理解String的運作機制,換個樣子就有可能把PAPER難住了。
          String s1 = "xyz"; String s2 = "x"+"yz"; String s3 = "x"+new String("yz"); String s4=new String("xyz");
          如果說s1==s2,那s1為什么!=s3呢?為什么s1!=s4呢?

          String類是java中一個比較特殊的類,與其相關的還有java中僅有的兩個內置重載操作符:"+"和"+="。
          String類對象是不可變的,而StringBuffer & String Builder類對象是可變的;String類重寫了equals方法,而StringBuffer & String Builder類卻沒有重寫。

          拿操作符"+"來說,其兩邊的操作元類型無非就5種情況(注意操作符的左結合性):
          1、兩個操作元都是基本類型(原始類型):效果是重載前的算術運算
          2、兩個操作元都是非String類型的引用類型:編譯無法通過,不支持
          3、兩個操作元都是String類型:重載操作
          4、一個是String類型,一個是基本類型:重載操作
          5、一個是String類型,一個是引用類型:重載操作

          其實對于3、4兩種情況,由于String類型的特殊性,編譯器會在編譯時做一些特殊處理,所以情況會變得稍微復雜一點。
           1public class StringTest
           2{
           3    public static void main(String[] args)
           4    {
           5        //1.操作符兩邊都是基本類型(原始類型),則"+"操作符代表算術運算
           6        //2.操作符兩邊都是非String類型的引用類型,重載操作不支持,編譯錯誤
           7        //3.操作符兩邊都是String類型
           8        String s1 = new String("hello");
           9        String s2 = new String("world");
          10        String s3 = s1+s2; //重載操作是通過StringBuilder實現的
          11        
          12        //4.操作符一邊是基本類型(原始類型)
          13        int i = 2008;
          14        String s4 = new String("beijing");
          15        String s5 = s4+i; //重載操作是通過StringBuilder實現的,
          16        //對于基本類型也并不是轉化成String字符串再進行連接
          17
          18        //5.操作符一邊是引用類型
          19        Integer in = new Integer(2008);
          20        String s6 = s4+in; //重載操作是通過StringBuilder實現的,
          21        //對于引用類型in,通過in.toString()方法返回字符串,再進行連接
          22
          23        //6.操作符都是String類型,且都是編譯時可計算的
          24        String s7 = "hello"+"world"//編譯后就確定了s7取值,并不需要等到運行時
          25        System.out.println(s3==s7); //false, s3指向StringBuilder返回的,指向堆內存的新String對象,s7則指向String池
          26
          27        //7.操作符一邊是基本類型(原始類型)
          28        String s8 = "beijing"+2008//編譯后就確定了s8取值,并不需要等到運行時
          29        System.out.println(s5==s8); //false, s5指向StringBuilder返回的,指向堆內存的新String對象,s8則指向String池
          30
          31        String s9 = "beijing"+i; //編譯時無法計算出取值,s9的結果是指向堆內存
          32        System.out.println(s8==s9); //false, s9指向的是堆內存,而s8指向String池
          33        s7 += " blogjava"//編譯時無法計算出取值,s7的結果是指向堆內存
          34        System.out.println(s7=="helloworld blogjava".intern()); //false, s7指向的是堆內存
          35    }

          36}

          37

          查看反編譯后的源代碼或許更能理解String的運作機制:
          Compiled from "StringTest.java"
          public class StringTest extends java.lang.Object{
          public StringTest();
            Code:
             
          0:    aload_0
             
          1:    invokespecial    #1//Method java/lang/Object."<init>":()V
             4:    return

          public static void main(java.lang.String[]);
            Code:
             
          0:    new    #2//class java/lang/String
             3:    dup
             
          4:    ldc    #3//String hello
             6:    invokespecial    #4//Method java/lang/String."<init>":(Ljava/lang/String;)V
             9:    astore_1
             
          10:    new    #2//class java/lang/String
             13:    dup
             
          14:    ldc    #5//String world
             16:    invokespecial    #4//Method java/lang/String."<init>":(Ljava/lang/String;)V
             19:    astore_2
             
          20:    new    #6//class java/lang/StringBuilder
             23:    dup
             
          24:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
             27:    aload_1
             
          28:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
             31:    aload_2
             
          32:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
             35:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
             38:    astore_3
             
          39:    sipush    2008
             
          42:    istore    4
             
          44:    new    #2//class java/lang/String
             47:    dup
             
          48:    ldc    #10//String beijing
             50:    invokespecial    #4//Method java/lang/String."<init>":(Ljava/lang/String;)V
             53:    astore    5
             
          55:    new    #6//class java/lang/StringBuilder
             58:    dup
             
          59:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
             62:    aload    5
             
          64:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
             67:    iload    4
             
          69:    invokevirtual    #11//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
             72:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
             75:    astore    6
             
          77:    new    #12//class java/lang/Integer
             80:    dup
             
          81:    sipush    2008
             
          84:    invokespecial    #13//Method java/lang/Integer."<init>":(I)V
             87:    astore    7
             
          89:    new    #6//class java/lang/StringBuilder
             92:    dup
             
          93:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
             96:    aload    5
             
          98:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
             101:    aload    7
             
          103:    invokevirtual    #14//Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
             106:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
             109:    astore    8
             
          111:    ldc    #15//String helloworld
             113:    astore    9
             
          115:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
             118:    aload_3
             
          119:    aload    9
             
          121:    if_acmpne    128
             
          124:    iconst_1
             
          125:    goto    129
             
          128:    iconst_0
             
          129:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
             132:    ldc    #18//String beijing2008
             134:    astore    10
             
          136:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
             139:    aload    6
             
          141:    aload    10
             
          143:    if_acmpne    150
             
          146:    iconst_1
             
          147:    goto    151
             
          150:    iconst_0
             
          151:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
             154:    new    #6//class java/lang/StringBuilder
             157:    dup
             
          158:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
             161:    ldc    #10//String beijing
             163:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
             166:    iload    4
             
          168:    invokevirtual    #11//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
             171:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
             174:    astore    11
             
          176:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
             179:    aload    10
             
          181:    aload    11
             
          183:    if_acmpne    190
             
          186:    iconst_1
             
          187:    goto    191
             
          190:    iconst_0
             
          191:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
             194:    new    #6//class java/lang/StringBuilder
             197:    dup
             
          198:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
             201:    aload    9
             
          203:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
             206:    ldc    #19//String  blogjava
             208:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
             211:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
             214:    astore    9
             
          216:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
             219:    aload    9
             
          221:    ldc    #20//String helloworld blogjava
             223:    invokevirtual    #21//Method java/lang/String.intern:()Ljava/lang/String;
             226:    if_acmpne    233
             
          229:    iconst_1
             
          230:    goto    234
             
          233:    iconst_0
             
          234:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
             237:    return

          }




          posted on 2008-01-09 00:08 菜園小鳥 閱讀(1950) 評論(6)  編輯  收藏

          FeedBack:
          # re: 一題有關String筆試題的分析
          2008-01-09 07:46 | vagrant
          其實這也和另一個知識相關:= 和 equals區別.equals是判斷兩個對象的值是否相等,而=則判斷值和地址是否相等.  回復  更多評論
            
          # re: 一題有關String筆試題的分析
          2008-01-09 08:24 | Matthew Chen
          第一題不是說一種嗎,好像看哪里說過常量池是編譯期結束就創建好的,運行時不會創建。  回復  更多評論
            
          # re: 一題有關String筆試題的分析
          2008-01-09 09:29 | 隔葉黃鶯
          對于這種問題我基本是不愿多看細看的,討論多了都無益,如果照很多人的想法可以無限伸展,就比如一個有許多個對象屬性的類
          Class1{
          Object obj1;
          Object obj1;
          Object obj1;
          Object obj1;
          Object obj1;
          .........
          }

          new Class1() 誰能說創建了幾個對象,那如果屬性嵌屬性,很深很深層次的,又會創建幾個對象,有多大意義呢

          可能對于 new String("xyz") 就是存在一個常量池的問題,有時要考慮編譯優化的問題,就這么簡單,何必搞得這么復雜。  回復  更多評論
            
          # re: 一題有關String筆試題的分析[未登錄]
          2008-01-09 10:34 | abc
          這些原理是屬于編程基礎吧?  回復  更多評論
            
          # re: 一題有關String筆試題的分析
          2008-01-09 13:14 | 你是樓豬
          討論這沒多大意義,很討厭死摳這些的hr  回復  更多評論
            
          # re: 一題有關String筆試題的分析
          2008-01-09 20:10 | sitinspring
          留個記號。  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          <2008年1月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(1)

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 来凤县| 三江| 石城县| 微博| 闻喜县| 廉江市| 永和县| 陆良县| 永修县| 潮州市| 庐江县| 南城县| 宁陕县| 和田县| 商南县| 洛南县| 罗江县| 福州市| 怀安县| 旌德县| 天镇县| 张掖市| 阜新| 紫金县| 新田县| 海口市| 黄浦区| 固原市| 枣庄市| 拉萨市| 福建省| 杂多县| 东海县| 丘北县| 土默特右旗| 双柏县| 曲沃县| 梨树县| 大余县| 信丰县| 成都市|