<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 30,  comments - 28,  trackbacks - 0

    自己想的一道題,算是30%原創吧?
    String a=new String("Hello");
    ? a+="World";

    ?問:a的內容最后是什么?
    ???????? 這兩個語句,共生成了幾個Java對象?

    簡單不?看樣子非常簡單吧,呵呵。
    第一問:a(確切地說a引用的內容)是HelloWorld
    ?
    第二問: 兩個語句,一共生成了幾個對象?
    ????看第一個語句,說實話,用這種方式初始化String,實在是代碼垃圾。這先不管啦。這個語句是老生長談,一個或兩個對象。
    ??? 為何?第一次執行時創建了二個, 一個為字面量"Hello"(它本身是一個String對象), 一個為new String("Hello")(它是通過new創建的, 功能上和字面量"foo"完全一樣, 但卻是另一個對象).

    第二次執行時, 只創建一個, 即new String("Hello"), 這是因為: "Hello"作為String字面量, 是存在于String Pool里面的, 第二次使用它時, 直接指向原有的String, 而不再創建新的String; 但new String("Hello")卻每執行一次都創建一個新的,完全一樣的String對象.

    ???第二個語句呢?
    ???? 3個對象。
    ???? 首先是“World”,毋庸質疑。
    ???? 那么然后呢?注意了,String是final類,不可改變。平時我們寫Java會有個錯覺,stringA+stringB就以為是前者尾巴接上后者腦袋。的確,在C/C++里就是如此。一點兒錯都沒有。
    ??? 但是Java不是,Java設計者為了更多方面的考慮,他們把String設計成了final。
    ??? 看一下JVM匯編指令吧
    ? 0:?aload_0
    ?? 1:?invokespecial?#1; //Method java/lang/Object."<init>":()V
    ?? 4:?return

    static void inti();
    ? 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_0
    ?? 10:?new?#5; //class java/lang/StringBuilder
    ?? 13:?dup
    ?? 14:?invokespecial?#6; //Method java/lang/StringBuilder."<init>":()V
    ?? 17:?aload_0
    ?? 18:?invokevirtual?#7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    ?? 21:?ldc?#3; //String Hello
    ?? 23:?invokevirtual?#7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    ?? 26:?invokevirtual?#8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    ?? 29:?astore_0
    ?? 30:?return

    }

    仔細看一下我做的標記,JVM給我們生成了一個StringBuilder類。(我用的是JDK5,舊版本是StringBuffer類,單單這一點小改動就能讓Java的速度提高很多)。讓后用append方法載入Hello和World兩個String的引用(明確地說轉化成字符數組)。
    當載入完成后,StringBuilder實例調用toString,生成一個新的String實例(暫時稱為TempString)。
    ?最后把引用a指向TempString


    總結:兩句語句總共生成了4個或5個Java類實例

    PS:Java中沒有指針實在是太不方便了。特別是在操作原始數據類型的時候。個人認為Java應該在這點上學學C#。指針不是洪水猛獸,對優秀程序員而言,指針是編程中的一種享受。
    ??????? 希望“海豚”(Java7)能出現指針吧---很不現實,還是等開源后的Java版本吧


    posted on 2006-08-14 03:18 murainwood 閱讀(509) 評論(4)  編輯  收藏 所屬分類: Java讀書筆記


    FeedBack:
    # re: 繼續鞏固Java基礎,一道綜合題
    2006-09-19 21:19 | Winnie
    String a=new String("Hello");
    a+="World";
    總結:兩句語句總共生成了4個或5個Java類實例

    你好,看了你的結論我有些不明白,是否可以指教一二?
    最近正巧在看關于Java字面量方面的內容,看過來的總結就是Java的字面量可以理解為Java的常量,而String類型的字面量呢,是保存于字符串緩沖池中的,所以我覺得就上面的代碼而言,如果我們只討論它執行一次生成幾個String類實例,你在文中提到“第一次執行時創建了二個, 一個為字面量"Hello"(它本身是一個String對象), 一個為new String("Hello")”我的理解是:第一個語句生成了一個String類的實例,而且同時有一個引用變量a指向該String實例,而第二個語句才在字面量緩沖池中生成了一個helloworld和world的實例,此時引用變量a指向helloworld字面量,總結下來應該是又生成兩個實例,那么一共應該是生成三個String實例。
    如果說要執行多次的話,那么每一次都要增加一個String實例,因為有第一個語句。
    我的理解不曉得正確與否,因為我只是看了一些介紹,并不懂得看JVM的匯編語句  回復  更多評論
      
    # re: 繼續鞏固Java基礎,一道綜合題
    2006-09-20 17:36 | murainwood
    "Hello"如果是第一次出現,會生成一個新的實例,然后放入常量Pool中。
    調用了new 語句,總能新生成一個對象實例。
    所以 String a="Hello"和 String a=new String("Hello")是不同的。而且后者被認為是"劣質代碼"
    而a+="World";這個你可以用javap -c 來看JVM匯編碼。
    String做所謂的"連接"時,總是通過臨時變量 StringBuffer 或StringBuilder來實現的。(后者是JDK5.0中的新類,是一個多線程不安全的StringBuffer)
      回復  更多評論
      
    # re: 繼續鞏固Java基礎,一道綜合題
    2006-09-20 19:17 | Winnie
    正巧我對在網上看到的一些內容不是很了解,在此可否再請教一下:
    “String a="Hello"和 String a=new String("Hello")是不同的”
    據我在網上看到的一些資料可以這么解釋:前者是生成一個引導變量a,然后查看“字符串池”中是否有hello這個常量,如果有,直接把該常量的內存地址賦值給a,如果沒有,則在“字符串池”中創建一個hello實例,將新創建的內存自己賦值給a;而后者是生成一個引導變量a,同時創建一個字符串實例,將該字符串實例的內存地址賦值給a。
    你在上文中提到“"Hello"如果是第一次出現,會生成一個新的實例,然后放入常量Pool中。”。我看到的一些資料說,字符串池可以理解為一塊特殊的地方,和內存稍有區別。如果hello是第一次出現,那么給該實例開辟的內存空間可否認為是在pool中的,以后再次出現new語句時,再另外開辟內存空間?
    換言之,String a=new String("Hello")第一次運行中,開辟了一個內存空間,且把該空間算到pool中去,如果pool中沒有hello實例的話?  回復  更多評論
      
    # re: 繼續鞏固Java基礎,一道綜合題
    2006-09-20 21:08 | murainwood
    我的觀點是可以反過來想。
    下面是我寫的代碼
    //:~To compare the reference of string
    public class StringConstPool {

    /**
    * @param args
    */
    public static void main(String[] args) {

    String the1st="hello";

    String the2ed="hello";

    //the result is "the two string are Same"
    //so i'm sure the the1st and the2ed refer the same address
    System.out.println("The two strings are "+(the1st==the2ed?"Same":"Different"));

    String the3ed=new String("hello");
    //the result is different from upper
    //so the the3ed refers another address,thought they have
    System.out.println("The two strings are "+(the1st==the3ed?"Same":"Different"));

    }

    }

    可以看到,變量the1st 和 the2ed 所指的地址是一樣的。而the3ed則是另外的地址。
    我認為的常量池的觀點是正確的,String the2ed="hello"這語句甚至一個對象實例都沒有創造!

    這是JDK API中文版的說明:
    String
    public String(String original)初始化一個新創建的 String 對象,表示一個與該參數相同的字符序列;換句話說,新創建的字符串是該參數字符串的一個副本。由于 String 是不可變的,不必使用該構造方法,除非需要 original 的 顯式副本。

    很明白了吧?  回復  更多評論
      
    <2006年9月>
    272829303112
    3456789
    10111213141516
    17181920212223
    24252627282930
    1234567

    如果真的給你一片天,你敢不敢要?

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    相冊

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产va在线观看免费| 性色av极品无码专区亚洲| 成人A毛片免费观看网站| 亚洲乱码日产精品a级毛片久久 | 激情综合亚洲色婷婷五月APP| 免费国产叼嘿视频大全网站| 亚洲av中文无码乱人伦在线咪咕| 成人影片一区免费观看| 13小箩利洗澡无码视频网站免费| 亚洲综合色自拍一区| 久久99免费视频| 亚洲a在线视频视频| 亚欧色视频在线观看免费| 国产v亚洲v天堂a无| 国产成人精品高清免费| a级毛片免费观看在线| 亚洲欧洲成人精品香蕉网| 亚洲AV色欲色欲WWW| 亚洲国产精品成人久久蜜臀 | 久久精品亚洲一区二区| 日日麻批免费40分钟无码| 亚洲一区免费在线观看| 四虎免费久久影院| 成年免费a级毛片免费看无码| 亚洲福利视频导航| 日韩免费精品视频| 边摸边吃奶边做爽免费视频网站 | 精品视频一区二区三区免费| 亚洲福利视频一区二区三区| 成人免费无码大片A毛片抽搐| 亚洲精品中文字幕无码AV| 四虎成人免费观看在线网址 | 国产精品免费电影| 色www永久免费| 四虎亚洲精品高清在线观看| 亚洲日本韩国在线| 24小时在线免费视频| 免费国产高清毛不卡片基地 | 亚洲欧洲久久精品| 57pao国产成视频免费播放| 亚洲国产精品无码中文lv|