posts - 30,  comments - 28,  trackbacks - 0

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

          ?問:a的內(nèi)容最后是什么?
          ???????? 這兩個(gè)語句,共生成了幾個(gè)Java對(duì)象?

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

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

          ???第二個(gè)語句呢?
          ???? 3個(gè)對(duì)象。
          ???? 首先是“World”,毋庸質(zhì)疑。
          ???? 那么然后呢?注意了,String是final類,不可改變。平時(shí)我們寫Java會(huì)有個(gè)錯(cuò)覺,stringA+stringB就以為是前者尾巴接上后者腦袋。的確,在C/C++里就是如此。一點(diǎn)兒錯(cuò)都沒有。
          ??? 但是Java不是,Java設(shè)計(jì)者為了更多方面的考慮,他們把String設(shè)計(jì)成了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

          }

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


          總結(jié):兩句語句總共生成了4個(gè)或5個(gè)Java類實(shí)例

          PS:Java中沒有指針實(shí)在是太不方便了。特別是在操作原始數(shù)據(jù)類型的時(shí)候。個(gè)人認(rèn)為Java應(yīng)該在這點(diǎn)上學(xué)學(xué)C#。指針不是洪水猛獸,對(duì)優(yōu)秀程序員而言,指針是編程中的一種享受。
          ??????? 希望“海豚”(Java7)能出現(xiàn)指針吧---很不現(xiàn)實(shí),還是等開源后的Java版本吧


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


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

          你好,看了你的結(jié)論我有些不明白,是否可以指教一二?
          最近正巧在看關(guān)于Java字面量方面的內(nèi)容,看過來的總結(jié)就是Java的字面量可以理解為Java的常量,而String類型的字面量呢,是保存于字符串緩沖池中的,所以我覺得就上面的代碼而言,如果我們只討論它執(zhí)行一次生成幾個(gè)String類實(shí)例,你在文中提到“第一次執(zhí)行時(shí)創(chuàng)建了二個(gè), 一個(gè)為字面量"Hello"(它本身是一個(gè)String對(duì)象), 一個(gè)為new String("Hello")”我的理解是:第一個(gè)語句生成了一個(gè)String類的實(shí)例,而且同時(shí)有一個(gè)引用變量a指向該String實(shí)例,而第二個(gè)語句才在字面量緩沖池中生成了一個(gè)helloworld和world的實(shí)例,此時(shí)引用變量a指向helloworld字面量,總結(jié)下來應(yīng)該是又生成兩個(gè)實(shí)例,那么一共應(yīng)該是生成三個(gè)String實(shí)例。
          如果說要執(zhí)行多次的話,那么每一次都要增加一個(gè)String實(shí)例,因?yàn)橛械谝粋€(gè)語句。
          我的理解不曉得正確與否,因?yàn)槲抑皇强戳艘恍┙榻B,并不懂得看JVM的匯編語句  回復(fù)  更多評(píng)論
            
          # re: 繼續(xù)鞏固Java基礎(chǔ),一道綜合題
          2006-09-20 17:36 | murainwood
          "Hello"如果是第一次出現(xiàn),會(huì)生成一個(gè)新的實(shí)例,然后放入常量Pool中。
          調(diào)用了new 語句,總能新生成一個(gè)對(duì)象實(shí)例。
          所以 String a="Hello"和 String a=new String("Hello")是不同的。而且后者被認(rèn)為是"劣質(zhì)代碼"
          而a+="World";這個(gè)你可以用javap -c 來看JVM匯編碼。
          String做所謂的"連接"時(shí),總是通過臨時(shí)變量 StringBuffer 或StringBuilder來實(shí)現(xiàn)的。(后者是JDK5.0中的新類,是一個(gè)多線程不安全的StringBuffer)
            回復(fù)  更多評(píng)論
            
          # re: 繼續(xù)鞏固Java基礎(chǔ),一道綜合題
          2006-09-20 19:17 | Winnie
          正巧我對(duì)在網(wǎng)上看到的一些內(nèi)容不是很了解,在此可否再請(qǐng)教一下:
          “String a="Hello"和 String a=new String("Hello")是不同的”
          據(jù)我在網(wǎng)上看到的一些資料可以這么解釋:前者是生成一個(gè)引導(dǎo)變量a,然后查看“字符串池”中是否有hello這個(gè)常量,如果有,直接把該常量的內(nèi)存地址賦值給a,如果沒有,則在“字符串池”中創(chuàng)建一個(gè)hello實(shí)例,將新創(chuàng)建的內(nèi)存自己賦值給a;而后者是生成一個(gè)引導(dǎo)變量a,同時(shí)創(chuàng)建一個(gè)字符串實(shí)例,將該字符串實(shí)例的內(nèi)存地址賦值給a。
          你在上文中提到“"Hello"如果是第一次出現(xiàn),會(huì)生成一個(gè)新的實(shí)例,然后放入常量Pool中?!薄N铱吹降囊恍┵Y料說,字符串池可以理解為一塊特殊的地方,和內(nèi)存稍有區(qū)別。如果hello是第一次出現(xiàn),那么給該實(shí)例開辟的內(nèi)存空間可否認(rèn)為是在pool中的,以后再次出現(xiàn)new語句時(shí),再另外開辟內(nèi)存空間?
          換言之,String a=new String("Hello")第一次運(yùn)行中,開辟了一個(gè)內(nèi)存空間,且把該空間算到pool中去,如果pool中沒有hello實(shí)例的話?  回復(fù)  更多評(píng)論
            
          # re: 繼續(xù)鞏固Java基礎(chǔ),一道綜合題
          2006-09-20 21:08 | murainwood
          我的觀點(diǎn)是可以反過來想。
          下面是我寫的代碼
          //:~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則是另外的地址。
          我認(rèn)為的常量池的觀點(diǎn)是正確的,String the2ed="hello"這語句甚至一個(gè)對(duì)象實(shí)例都沒有創(chuàng)造!

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

          很明白了吧?  回復(fù)  更多評(píng)論
            
          <2006年8月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

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

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          相冊(cè)

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 吴江市| 广河县| 韶山市| 涟水县| 延川县| 天水市| 东台市| 定陶县| 辽宁省| 德惠市| 裕民县| 阿坝县| 华容县| 青阳县| 如皋市| 龙海市| 株洲市| 乳源| 秭归县| 藁城市| 炎陵县| 朔州市| 襄樊市| 武功县| 读书| 辽宁省| 微山县| 宁都县| 安塞县| 定西市| 福海县| 任丘市| 河北省| 漠河县| 庆云县| 阜平县| 万全县| 龙陵县| 鞍山市| 高台县| 汶川县|