<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 閱讀(515) 評論(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年8月>
    303112345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

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

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    相冊

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 自拍日韩亚洲一区在线| 久久亚洲av无码精品浪潮| 亚洲日韩aⅴ在线视频| 人妻无码中文字幕免费视频蜜桃| 免费观看a级毛片| 亚洲老熟女五十路老熟女bbw| 国产啪精品视频网免费| 亚洲人成在久久综合网站| 青娱分类视频精品免费2| 久久亚洲国产成人影院| 日本二区免费一片黄2019| 国产成人亚洲精品电影| 亚洲免费日韩无码系列| 丁香花在线视频观看免费 | 免费一级毛片在线观看| 日本特黄特色AAA大片免费| 国产亚洲美日韩AV中文字幕无码成人 | 亚洲欧洲日本天天堂在线观看| 91久久精品国产免费直播| 国产亚洲中文日本不卡二区| 日本一道本高清免费| 男女一边桶一边摸一边脱视频免费| 亚洲精品无码久久久久| xx视频在线永久免费观看| 亚洲美国产亚洲AV| 久久久久亚洲AV综合波多野结衣| 13小箩利洗澡无码视频网站免费| 亚洲小视频在线播放| 国产免费私拍一区二区三区 | 成人在线免费观看| 日本激情猛烈在线看免费观看| 亚洲国产精品无码中文字| 无码国产精品一区二区免费式影视| 亚洲av无码专区在线电影天堂 | 亚洲AV日韩综合一区尤物| 亚洲精品亚洲人成在线观看下载| 免费无遮挡无码永久视频| 日韩亚洲人成网站| 亚洲国产成人久久精品动漫 | 好男人www免费高清视频在线| 一级特黄录像视频免费|