隨筆 - 7  文章 - 5  trackbacks - 0
          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          目前在研究生階段,主要是做基于J2EE的web services

          常用鏈接

          留言簿(2)

          隨筆分類

          文章分類

          最新隨筆

          最新評論

          ????? 今天修改了jsf的驗證器部分...看到了對于email的驗證.....看起來還是有點頭大呀.....于是乎翻javadoc....找到了java.util.regex.Pattern類....挺有意思的...一起分享一下......?

          java.util.regex
          類 Pattern

          java.lang.Objectjava.util.regex.Pattern
          所有已實現(xiàn)的接口:
          Serializable

          public final class Pattern
          extends Object
          implements Serializable

          正則表達(dá)式的編譯表示形式。

          指定為字符串的正則表達(dá)式必須首先被編譯為此類的實例。然后,可將得到的模式用于創(chuàng)建 Matcher 對象,依照正則表達(dá)式,該對象可以與任意字符序列匹配。執(zhí)行匹配所涉及的所有狀態(tài)都駐留在匹配器中,所以多個匹配器可以共享同一模式。

          因此,典型的調(diào)用順序是

           Pattern p = Pattern.compile("a*b");
           Matcher m = p.matcher("aaaaab");
           boolean b = m.matches();

          在僅使用一次正則表達(dá)式時,可以方便地通過此類定義 matches 方法。此方法編譯表達(dá)式并在單個調(diào)用中將輸入序列與其匹配。語句

           boolean b = Pattern.matches("a*b", "aaaaab");
          等效于上面的三個語句,盡管對于重復(fù)的匹配而言它效率不高,因為它不允許重用已編譯的模式。

          此類的實例是不可變的,可供多個并發(fā)線程安全使用。Matcher 類的實例用于此目的則不安全。

          正則表達(dá)式的構(gòu)造摘要

          構(gòu)造匹配
          ?
          字符
          x字符 x
          \\反斜線字符
          \0n帶有八進(jìn)制值 0 的字符 n (0?<=?n?<=?7)
          \0nn帶有八進(jìn)制值 0 的字符 nn (0?<=?n?<=?7)
          \0mnn帶有八進(jìn)制值 0 的字符 mnn(0?<=?m?<=?3、0?<=?n?<=?7)
          \xhh帶有十六進(jìn)制值?0x 的字符 hh
          \uhhhh帶有十六進(jìn)制值?0x 的字符 hhhh
          \t制表符 ('\u0009')
          \n新行(換行)符 ('\u000A')
          \r回車符 ('\u000D')
          \f換頁符 ('\u000C')
          \a報警 (bell) 符 ('\u0007')
          \e轉(zhuǎn)義符 ('\u001B')
          \cx對應(yīng)于 x 的控制符
          ?
          字符類
          [abc]abc(簡單類)
          [^abc]任何字符,除了 abc(否定)
          [a-zA-Z]azAZ,兩頭的字母包括在內(nèi)(范圍)
          [a-d[m-p]]admp[a-dm-p](并集)
          [a-z&&[def]]def(交集)
          [a-z&&[^bc]]az,除了 bc[ad-z](減去)
          [a-z&&[^m-p]]az,而非 mp[a-lq-z](減去)
          ?
          預(yù)定義字符類
          .任何字符(與行結(jié)束符可能匹配也可能不匹配)
          \d數(shù)字:[0-9]
          \D非數(shù)字: [^0-9]
          \s空白字符:[ \t\n\x0B\f\r]
          \S非空白字符:[^\s]
          \w單詞字符:[a-zA-Z_0-9]
          \W非單詞字符:[^\w]
          ?
          POSIX 字符類(僅 US-ASCII)
          \p{Lower}小寫字母字符:[a-z]
          \p{Upper}大寫字母字符:[A-Z]
          \p{ASCII}所有 ASCII:[\x00-\x7F]
          \p{Alpha}字母字符:[\p{Lower}\p{Upper}]
          \p{Digit}十進(jìn)制數(shù)字:[0-9]
          \p{Alnum}字母數(shù)字字符:[\p{Alpha}\p{Digit}]
          \p{Punct}標(biāo)點符號:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
          \p{Graph}可見字符:[\p{Alnum}\p{Punct}]
          \p{Print}可打印字符:[\p{Graph}\x20]
          \p{Blank}空格或制表符:[ \t]
          \p{Cntrl}控制字符:[\x00-\x1F\x7F]
          \p{XDigit}十六進(jìn)制數(shù)字:[0-9a-fA-F]
          \p{Space}空白字符:[ \t\n\x0B\f\r]
          ?
          java.lang.Character 類(簡單的 java 字符類型
          \p{javaLowerCase}等效于 java.lang.Character.isLowerCase()
          \p{javaUpperCase}等效于 java.lang.Character.isUpperCase()
          \p{javaWhitespace}等效于 java.lang.Character.isWhitespace()
          \p{javaMirrored}等效于 java.lang.Character.isMirrored()
          ?
          Unicode 塊和類別的類
          \p{InGreek}Greek?塊(簡單)中的字符
          \p{Lu}大寫字母(簡單類別
          \p{Sc}貨幣符號
          \P{InGreek}所有字符,Greek 塊中的除外(否定)
          [\p{L}&&[^\p{Lu}]]?所有字母,大寫字母除外(減去)
          ?
          邊界匹配器
          ^行的開頭
          $行的結(jié)尾
          \b單詞邊界
          \B非單詞邊界
          \A輸入的開頭
          \G上一個匹配的結(jié)尾
          \Z輸入的結(jié)尾,僅用于最后的結(jié)束符(如果有的話)
          \z輸入的結(jié)尾
          ?
          Greedy 數(shù)量詞
          X?X,一次或一次也沒有
          X*X,零次或多次
          X+X,一次或多次
          X{n}X,恰好 n
          X{n,}X,至少 n
          X{n,m}X,至少 n 次,但是不超過 m
          ?
          Reluctant 數(shù)量詞
          X??X,一次或一次也沒有
          X*?X,零次或多次
          X+?X,一次或多次
          X{n}?X,恰好 n
          X{n,}?X,至少 n
          X{n,m}?X,至少 n 次,但是不超過 m
          ?
          Possessive 數(shù)量詞
          X?+X,一次或一次也沒有
          X*+X,零次或多次
          X++X,一次或多次
          X{n}+X,恰好 n
          X{n,}+X,至少 n
          X{n,m}+X,至少 n 次,但是不超過 m
          ?
          Logical 運(yùn)算符
          XYX 后跟 Y
          X|YXY
          (X)X,作為捕獲組
          ?
          Back 引用
          \n任何匹配的 nth捕獲組
          ?
          引用
          \Nothing,但是引用以下字符
          \QNothing,但是引用所有字符,直到 \E
          \ENothing,但是結(jié)束從 \Q 開始的引用
          ?
          特殊構(gòu)造(非捕獲)
          (?:X)X,作為非捕獲組
          (?idmsux-idmsux)?Nothing,但是將匹配標(biāo)志由 on 轉(zhuǎn)為 off
          (?idmsux-idmsux:X)??X,作為帶有給定標(biāo)志 on - off 的非捕獲組
          (?=X)X,通過零寬度的正 lookahead
          (?!X)X,通過零寬度的負(fù) lookahead
          (?<=X)X,通過零寬度的正 lookbehind
          (?<!X)X,通過零寬度的負(fù) lookbehind
          (?>X)X,作為獨立的非捕獲組

          反斜線、轉(zhuǎn)義和引用

          反斜線字符 ('\') 用于引用轉(zhuǎn)義構(gòu)造,如上表所定義的,同時還用于引用其他將被解釋為非轉(zhuǎn)義構(gòu)造的字符。因此,表達(dá)式 \\ 與單個反斜線匹配,而 \{ 與左括號匹配。

          在不表示轉(zhuǎn)義構(gòu)造的任何字母字符前使用反斜線都是錯誤的;它們是為將來擴(kuò)展正則表達(dá)式語言保留的。可以在非字母字符前使用反斜線,不管該字符是否非轉(zhuǎn)義構(gòu)造的一部分。

          根據(jù) Java Language Specification 的要求,Java 源代碼的字符串中的反斜線被解釋為 Unicode 轉(zhuǎn)義或其他字符轉(zhuǎn)義。因此必須在字符串字面值中使用兩個反斜線,表示正則表達(dá)式受到保護(hù),不被 Java 字節(jié)碼編譯器解釋。例如,當(dāng)解釋為正則表達(dá)式時,字符串字面值 "\b" 與單個退格字符匹配,而 "\\b" 與單詞邊界匹配。字符串字面值 "\(hello\)" 是非法的,將導(dǎo)致編譯時錯誤;要與字符串 (hello) 匹配,必須使用字符串字面值 "\\(hello\\)"

          字符類

          字符類可以出現(xiàn)在其他字符類中,并且可以包含并集運(yùn)算符(隱式)和交集運(yùn)算符 (&&)。并集運(yùn)算符表示至少包含其某個操作數(shù)類中所有字符的類。交集運(yùn)算符表示包含同時位于其兩個操作數(shù)類中所有字符的類。

          字符類運(yùn)算符的優(yōu)先級如下所示,按從最高到最低的順序排列:

          1????字面值轉(zhuǎn)義????\x
          2????分組[...]
          3????范圍a-z
          4????并集[a-e][i-u]
          5????交集[a-z&&[aeiou]]

          注意,元字符的不同集合實際上位于字符類的內(nèi)部,而非字符類的外部。例如,正則表達(dá)式 . 在字符類內(nèi)部就失去了其特殊意義,而表達(dá)式 - 變成了形成元字符的范圍。

          行結(jié)束符

          行結(jié)束符 是一個或兩個字符的序列,標(biāo)記輸入字符序列的行結(jié)尾。以下代碼被識別為行結(jié)束符:

          如果激活 UNIX_LINES 模式,則新行符是惟一識別的行結(jié)束符。

          如果未指定 DOTALL 標(biāo)志,則正則表達(dá)式 . 可以與任何字符(行結(jié)束符除外)匹配。

          默認(rèn)情況下,正則表達(dá)式 ^$ 忽略行結(jié)束符,僅分別與整個輸入序列的開頭和結(jié)尾匹配。如果激活 MULTILINE 模式,則 ^ 在輸入的開頭和行結(jié)束符之后(輸入的結(jié)尾)才發(fā)生匹配。處于 MULTILINE 模式中時,$ 僅在行結(jié)束符之前或輸入序列的結(jié)尾處匹配。

          組和捕獲

          捕獲組可以通過從左到右計算其開括號來編號。例如,在表達(dá)式 ((A)(B(C))) 中,存在四個這樣的組:

          1????((A)(B(C)))
          2????\A
          3????(B(C))
          4????(C)

          組零始終代表整個表達(dá)式。

          之所以這樣命名捕獲組是因為在匹配中,保存了與這些組匹配的輸入序列的每個子序列。捕獲的子序列稍后可以通過 Back 引用在表達(dá)式中使用,也可以在匹配操作完成后從匹配器檢索。

          與組關(guān)聯(lián)的捕獲輸入始終是與組最近匹配的子序列。如果由于量化的緣故再次計算了組,則在第二次計算失敗時將保留其以前捕獲的值(如果有的話)例如,將字符串 "aba" 與表達(dá)式 (a(b)?)+ 相匹配,會將第二組設(shè)置為 "b"。在每個匹配的開頭,所有捕獲的輸入都會被丟棄。

          (?) 開頭的組是純的非捕獲 組,它不捕獲文本,也不針對組合計進(jìn)行計數(shù)。

          Unicode 支持

          此類符合 Unicode Technical Standard #18:Unicode Regular Expression Guidelines 第 1 級和 RL2.1 Canonical Equivalents。

          Java 源代碼中的 Unicode 轉(zhuǎn)義序列(如 \u2014)是按照 Java Language Specification 的 第 3.3 節(jié)中的描述處理的。這樣的轉(zhuǎn)義序列還可以由正則表達(dá)式分析器直接實現(xiàn),以便在從文件或鍵盤擊鍵讀取的表達(dá)式中使用 Unicode 轉(zhuǎn)義。因此,可以將不相等的字符串 "\u2014""\\u2014" 編譯為相同的模式,從而與帶有十六進(jìn)制值 0x2014 的字符匹配。

          與 Perl 中一樣,Unicode 塊和類別是使用 \p\P 構(gòu)造編寫的。如果輸入具有屬性 prop,則與 \p{prop} 匹配,而輸入具有該屬性時與 \P{prop} 不匹配。塊使用前綴 In 指定,與在 InMongolian 中一樣。可以使用可選前綴 Is 指定類別:\p{L}\p{IsL} 都表示 Unicode 字母的類別。塊和類別在字符類的內(nèi)部和外部都可以使用。

          受支持的類別是由 Character 類指定版本中的 The Unicode Standard 的類別。類別名稱是在 Standard 中定義的,即標(biāo)準(zhǔn)又豐富。Pattern 所支持的塊名稱是 UnicodeBlock.forName 所接受和定義的有效塊名稱。

          行為類似 java.lang.Character boolean 是 methodname 方法(廢棄的類別除外)的類別,可以通過相同的 \p{prop} 語法來提供,其中指定的屬性具有名稱 javamethodname

          與 Perl 5 相比較

          Pattern 引擎用有序替換項執(zhí)行傳統(tǒng)上基于 NFA 的匹配,與 Perl 5 中進(jìn)行的相同。

          此類不支持 Perl 構(gòu)造:

          此類支持但 Perl 不支持的構(gòu)造:

          與 Perl 的顯著不同點是:

          • 在 Perl 中,\1\9 始終被解釋為 Back 引用;如果至少存在多個子表達(dá)式,則大于 9 的反斜線轉(zhuǎn)義數(shù)按 Back 引用對待,否則在可能的情況下,它將被解釋為八進(jìn)制轉(zhuǎn)義。在此類中,八進(jìn)制轉(zhuǎn)義必須始終以零開頭。在此類中,\1\9 始終被解釋為 Back 引用,較大的數(shù)被接受為 Back 引用,如果在正則表達(dá)式中至少存在多個子表達(dá)式的話;否則,分析器將刪除數(shù)字,直到該數(shù)小于或等于組的現(xiàn)有數(shù)或者其為一個數(shù)字。

          • Perl 使用 g 標(biāo)志請求恢復(fù)最后匹配丟失的匹配。此功能是由 Matcher 類顯式提供的:重復(fù)執(zhí)行 find 方法調(diào)用可以恢復(fù)丟失的最后匹配,除非匹配器被重置。

          • 在 Perl 中,位于表達(dá)式頂級的嵌入式標(biāo)記對整個表達(dá)式都有影響。在此類中,嵌入式標(biāo)志始終在它們出現(xiàn)的時候才起作用,不管它們位于頂級還是組中;在后一種情況下,與在 Perl 中類似,標(biāo)志在組的結(jié)尾處還原。

          • Perl 允許錯誤匹配構(gòu)造,如在表達(dá)式 *a 中,以及不匹配的括號,如在在表達(dá)式 abc] 中,并將其作為字面值對待。此類還接受不匹配的括號,但對 +、? 和 * 不匹配元字符有嚴(yán)格限制;如果遇到它們,則拋出 PatternSyntaxException

          有關(guān)正則表達(dá)式構(gòu)造行為更準(zhǔn)確的描述,請參見《Mastering Regular Expressions, 2nd Edition》,該書由 Jeffrey E. F. Friedl、O'Reilly 和 Associates 合著,于 2002 年出版。

          從以下版本開始:
          1.4
          另請參見:
          String.split(String, int), String.split(String), 序列化表格

          字段摘要
          static?intCANON_EQ
          ??????????啟用規(guī)范等價。
          static?intCASE_INSENSITIVE
          ??????????啟用不區(qū)分大小寫的匹配。
          static?intCOMMENTS
          ??????????模式中允許空白和注釋。
          static?intDOTALL
          ??????????啟用 dotall 模式。
          static?intLITERAL
          ??????????啟用模式的字面值分析。
          static?intMULTILINE
          ??????????啟用多行模式。
          static?intUNICODE_CASE
          ??????????啟用 Unicode 感知的大小寫折疊。
          static?intUNIX_LINES
          ??????????啟用 Unix 行模式。
          ?
          方法摘要
          static?Patterncompile(String?regex)
          ??????????將給定的正則表達(dá)式編譯到模式中。
          static?Patterncompile(String?regex, int?flags)
          ??????????將給定的正則表達(dá)式編譯到具有給定標(biāo)志的模式中。
          ?intflags()
          ??????????返回此模式的匹配標(biāo)志。
          ?Matchermatcher(CharSequence?input)
          ??????????創(chuàng)建匹配給定輸入與此模式的匹配器。
          static?booleanmatches(String?regex, CharSequence?input)
          ??????????編譯給定正則表達(dá)式并嘗試將給定輸入與其匹配。
          ?Stringpattern()
          ??????????返回在其中編譯過此模式的正則表達(dá)式。
          static?Stringquote(String?s)
          ??????????返回指定 String 的字面值模式 String
          ?String[]split(CharSequence?input)
          ??????????圍繞此模式的匹配拆分給定輸入序列。
          ?String[]split(CharSequence?input, int?limit)
          ??????????圍繞此模式的匹配拆分給定輸入序列。
          ?StringtoString()
          ??????????返回此模式的字符串表示形式。
          ?
          從類 java.lang.Object 繼承的方法
          clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait


          這樣下來檢驗email的代碼也是相當(dāng)簡單呀....
          ???? boolean b = Pattern.matches("^\\w+@\\w+(\\.\\w+)+", email);

          posted @ 2006-11-18 22:38 Stefanie 閱讀(5930) | 評論 (1)編輯 收藏

          P2P網(wǎng)絡(luò)的拓?fù)浣Y(jié)構(gòu)

          拓?fù)浣Y(jié)構(gòu)是指分布式系統(tǒng)中各個計算單元之間的物理或邏輯的互聯(lián)關(guān)系,結(jié)點之間的拓?fù)浣Y(jié)構(gòu)一直是確定系統(tǒng)類型的重要依據(jù)。目前互聯(lián)網(wǎng)絡(luò)中廣泛使用集中式、層次式等拓?fù)浣Y(jié)構(gòu)。Internet本身是世界上最大的非集中式的互聯(lián)網(wǎng)絡(luò),但是九十年代所建立的一些網(wǎng)絡(luò)應(yīng)用系統(tǒng)卻是完全的集中式的系統(tǒng),許多Web應(yīng)用都是運(yùn)行在集中式的服務(wù)器系統(tǒng)上。集中式拓?fù)浣Y(jié)構(gòu)系統(tǒng)目前面臨著過量存儲負(fù)載、DOS(Denial of Service,拒絕服務(wù))攻擊,網(wǎng)絡(luò)帶寬限制等一些難以解決的問題。Peer-to-Peer (簡稱P2P) 系統(tǒng)主要采用非集中式的拓?fù)浣Y(jié)構(gòu),一般來說不存在上述這些難題。根據(jù)結(jié)構(gòu)關(guān)系可以將P2P系統(tǒng)細(xì)分為四種拓?fù)湫问剑?/p>

          • 中心化拓?fù)?/strong>(Centralized Topology);
          • 全分布式非結(jié)構(gòu)化拓?fù)?/strong>(Decentralized Unstructured Topology);
          • 全分布式結(jié)構(gòu)化拓?fù)?/strong>(Decentralized Structured Topology,也稱作DHT網(wǎng)絡(luò));
          • 半分布式拓?fù)?/strong>(Partially Decentralized Topology)。

          其中,中心化拓?fù)?/strong>最大的優(yōu)點是維護(hù)簡單,資源發(fā)現(xiàn)效率高。由于資源的發(fā)現(xiàn)依賴中心化的目錄系統(tǒng),發(fā)現(xiàn)算法靈活高效并能夠?qū)崿F(xiàn)復(fù)雜查詢。最大的問題與傳統(tǒng)客戶機(jī)/服務(wù)器結(jié)構(gòu)類似,容易造成單點故障,訪問的“熱點”現(xiàn)象和版權(quán)糾紛等相關(guān)問題,這是第一代P2P網(wǎng)絡(luò)采用的結(jié)構(gòu)模式,經(jīng)典案例就是著名的MP3共享軟件Napster[1].

          Napster是最早出現(xiàn)的P2P系統(tǒng)之一,并在短期內(nèi)迅速成長起來。它實質(zhì)上并非是純粹的P2P系統(tǒng),而是通過一個中央索引服務(wù)器保存所有Napster用戶上傳的音樂文件索引和存放位置的信息。它的工作原理如圖1所示。當(dāng)某個用戶需要某個音樂文件時,首先連接到Napster中央索引服務(wù)器,在服務(wù)器上進(jìn)行檢索,服務(wù)器返回存有該文件的用戶信息,再由請求者直接連到文件的所有者傳輸文件。Napster首先實現(xiàn)了文件查詢與文件傳輸?shù)姆蛛x,有效地節(jié)省了中央服務(wù)器的帶寬消耗,減少了系統(tǒng)的文件傳輸延時。

          圖1 Napster的拓?fù)浣Y(jié)構(gòu)

          然而,這種對等網(wǎng)絡(luò)模型存在以下這些問題:

          • 中央索引服務(wù)器的癱瘓容易導(dǎo)致整個網(wǎng)絡(luò)的崩潰,因此可靠性和安全性較低。
          • 隨著網(wǎng)絡(luò)規(guī)模的擴(kuò)大,對中央索引服務(wù)器進(jìn)行維護(hù)和更新的費用將急劇增加,所需成本較高。
          • 中央索引服務(wù)器的存在常引起版權(quán)問題上的糾紛,服務(wù)提供商容易被追究法律責(zé)任。

          綜合上述優(yōu)缺點,對小型網(wǎng)絡(luò)而言,中心化拓?fù)?/strong>模型在管理和控制方面占一定優(yōu)勢。但鑒于其存在的上述缺陷,該模型并不適合大型網(wǎng)絡(luò)應(yīng)用。

          全分布式非結(jié)構(gòu)化拓?fù)涞腜2P網(wǎng)絡(luò)是在重疊網(wǎng)絡(luò)(Overlay Network)(見標(biāo)注1)采用了隨機(jī)圖的組織方式,結(jié)點度數(shù)服從Power-law規(guī)律(冪次法則)[2],從而能夠較快發(fā)現(xiàn)目的結(jié)點,面對網(wǎng)絡(luò)的動態(tài)變化體現(xiàn)了較好的容錯能力,因此具有較好的可用性。同時可以支持復(fù)雜查詢,如帶有規(guī)則表達(dá)式的多關(guān)鍵詞查詢,模糊查詢等,采用這種拓?fù)浣Y(jié)構(gòu)最典型的案例便是Gnutella(音譯:紐特拉)。準(zhǔn)確地說,Gnutella不是特指某一款軟件,而是指遵守Gnutella協(xié)議[3]的網(wǎng)絡(luò)以及客戶端軟件的統(tǒng)稱。目前基于Gnutella網(wǎng)絡(luò)的客戶端軟件非常多,著名的有ShareazaLimeWire和BearShare等。

          圖2Gnutella的拓?fù)浣Y(jié)構(gòu)和文件檢索方法

          Gnutella和Napster最大的區(qū)別在于Gnutella是更加純粹的P2P系統(tǒng),因為它沒有中央索引服務(wù)器,每臺機(jī)器在Gnutella網(wǎng)絡(luò)中是真正的對等關(guān)系,既是客戶機(jī)同時又是服務(wù)器,所以被稱為對等機(jī)(Servent,Server+Client的組合)。在文件檢索方面,它與Napster也不相同。在Gnutella網(wǎng)絡(luò)的發(fā)展初期,它主要采用基于完全隨機(jī)圖的Flooding搜索算法。圖2 顯示了Flooding的工作流程:當(dāng)一臺計算機(jī)要下載一個文件,它首先以文件名或者關(guān)鍵字生成一個查詢,并把這個查詢發(fā)送給與它相連的所有計算機(jī),這些計算機(jī)如果存在這個文件,則與查詢的機(jī)器建立連接,如果不存在這個文件,則繼續(xù)在自己相鄰的計算機(jī)之間轉(zhuǎn)發(fā)這個查詢,直到找到文件為止。為了控制搜索消息不至于永遠(yuǎn)這樣傳遞下去,一般通過TTL (Time To Live)的減值來控制查詢的深度。

          但是,隨著聯(lián)網(wǎng)節(jié)點的不斷增多,網(wǎng)絡(luò)規(guī)模不斷擴(kuò)大,通過這種Flooding方式定位對等點的方法將造成網(wǎng)絡(luò)流量急劇增加,從而導(dǎo)致網(wǎng)絡(luò)中部分低帶寬節(jié)點因網(wǎng)絡(luò)資源過載而失效。所以在初期的Gnutella網(wǎng)絡(luò)中,存在比較嚴(yán)重的分區(qū),斷鏈現(xiàn)象。也就是說,一個查詢訪問只能在網(wǎng)絡(luò)的很小一部分進(jìn)行,因此網(wǎng)絡(luò)的可擴(kuò)展性不好。所以,后來許多研究人員在Flooding的基礎(chǔ)上作了許多改進(jìn),例如采用Random work [4]、Dynamic Query[5]等方法。

          由于非結(jié)構(gòu)化網(wǎng)絡(luò)將重疊網(wǎng)絡(luò)認(rèn)為是一個完全隨機(jī)圖,結(jié)點之間的鏈路沒有遵循某些預(yù)先定義的拓?fù)鋪順?gòu)建。這些系統(tǒng)一般不提供性能保證,但容錯性好,支持復(fù)雜的查詢,并受結(jié)點頻繁加入和退出系統(tǒng)的影響小。但是查詢的結(jié)果可能不完全,查詢速度較慢,采用Flooding查詢的系統(tǒng)對網(wǎng)絡(luò)帶寬的消耗非常大,并由此帶來可擴(kuò)展性差等問題。

          全分布式結(jié)構(gòu)化拓?fù)?/strong>的P2P網(wǎng)絡(luò)主要是采用分布式散列表(Distributed Hash Table, 簡寫成DHT)技術(shù)來組織網(wǎng)絡(luò)中的結(jié)點。DHT是一個由廣域范圍大量結(jié)點共同維護(hù)的巨大散列表。散列表被分割成不連續(xù)的塊,每個結(jié)點被分配給一個屬于自己的散列塊,并成為這個散列塊的管理者。通過加密散列函數(shù),一個對象的名字或關(guān)鍵詞被映射為128位或160位的散列值。分布式散列表起源于SDDS(Scalable Distribute Data Structures)[6]研究,Gribble等實現(xiàn)了一個高度可擴(kuò)展,容錯的SDDS集群。DHT類結(jié)構(gòu)能夠自適應(yīng)結(jié)點的動態(tài)加入/退出,有著良好的可擴(kuò)展性、魯棒性、結(jié)點ID分配的均勻性和自組織能力。由于重疊網(wǎng)絡(luò)采用了確定性拓?fù)浣Y(jié)構(gòu),DHT可以提供精確的發(fā)現(xiàn)。只要目的結(jié)點存在于網(wǎng)絡(luò)中DHT總能發(fā)現(xiàn)它,發(fā)現(xiàn)的準(zhǔn)確性得到了保證,最經(jīng)典的案例是Tapestry,Pastry,Chord和CAN。

          Tapestry [7]提供了一個分布式容錯查找和路由基礎(chǔ)平臺,在此平臺基礎(chǔ)之上,可以開發(fā)各種P2P應(yīng)用(OceanStore[8]即是此平臺上的一個應(yīng)用)。Tapestry的思想來源于Plaxton。在Plaxton中,結(jié)點使用自己所知道的鄰近結(jié)點表,按照目的ID來逐步傳遞消息。Tapestry基于Plaxton的思想,加入了容錯機(jī)制,從而可適應(yīng)P2P的動態(tài)變化的特點。OceanStore是以Tapestry為路由和查找基礎(chǔ)設(shè)施的P2P平臺。它是一個適合于全球數(shù)據(jù)存儲的P2P應(yīng)用系統(tǒng)。任何用戶均可以加入OceanStore系統(tǒng),或者共享自己的存儲空間,或者使用該系統(tǒng)中的資源。通過使用復(fù)制和緩存技術(shù),OceanStore可提高查找的效率。最近,Tapestry為適應(yīng)P2P網(wǎng)絡(luò)的動態(tài)特性,作了很多改進(jìn),增加了額外的機(jī)制實現(xiàn)了網(wǎng)絡(luò)的軟狀態(tài)(soft state),并提供了自組織、魯棒性、可擴(kuò)展性和動態(tài)適應(yīng)性,當(dāng)網(wǎng)絡(luò)高負(fù)載且有失效結(jié)點時候性能有限降低,消除了對全局信息的依賴、根結(jié)點易失效和彈性差的問題。

          Pastry 是微軟研究院提出的可擴(kuò)展的分布式對象定位和路由協(xié)議,可用于構(gòu)建大規(guī)模的P2P系統(tǒng)。如圖3 所示,在Pastry中,每個結(jié)點分配一個128位的結(jié)點標(biāo)識符號(nodeID) ,所有的結(jié)點標(biāo)識符形成了一個環(huán)形的nodeID空間,范圍從0到2128 - 1 ,結(jié)點加入系統(tǒng)時通過散列結(jié)點IP地址在128位nodeID空間中隨機(jī)分配。網(wǎng)絡(luò)結(jié)點的加入與退出,資源查詢的過程可以參考文獻(xiàn)[9]。

          圖3Pastry的消息路由

          Chord [10]項目誕生于美國的麻省理工學(xué)院。它的目標(biāo)是提供一個適合于P2P環(huán)境的分布式資源發(fā)現(xiàn)服務(wù),它通過使用DHT技術(shù)使得發(fā)現(xiàn)指定對象只需要維護(hù)O(logN)長度的路由表。在DHT技術(shù)中,網(wǎng)絡(luò)結(jié)點按照一定的方式分配一個唯一結(jié)點標(biāo)識符(Node ID) ,資源對象通過散列運(yùn)算產(chǎn)生一個唯一的資源標(biāo)識符(Object ID) ,且該資源將存儲在結(jié)點ID與之相等或者相近的結(jié)點上。需要查找該資源時,采用同樣的方法可定位到存儲該資源的結(jié)點。因此,Chord的主要貢獻(xiàn)是提出了一個分布式查找協(xié)議,該協(xié)議可將指定的關(guān)鍵字(Key) 映射到對應(yīng)的結(jié)點(Node) 。從算法來看,Chord是相容散列算法的變體。

          圖4 Chord的拓?fù)湫螤?/p>

          CAN(Content Addressable Networks)[11] 項目采用多維的標(biāo)識符空間來實現(xiàn)分布式散列算法。CAN將所有結(jié)點映射到一個n維的笛卡爾空間中,并為每個結(jié)點盡可能均勻的分配一塊區(qū)域。CAN采用的散列函數(shù)通過對(key, value) 對中的key進(jìn)行散列運(yùn)算,得到笛卡爾空間中的一個點,并將(key, value) 對存儲在擁有該點所在區(qū)域的結(jié)點內(nèi)。CAN采用的路由算法相當(dāng)直接和簡單,知道目標(biāo)點的坐標(biāo)后,就將請求傳給當(dāng)前結(jié)點四鄰中坐標(biāo)最接近目標(biāo)點的結(jié)點。CAN是一個具有良好可擴(kuò)展性的系統(tǒng),給定N個結(jié)點,系統(tǒng)維數(shù)為d,則路由路徑長度為O(n1/d) ,每結(jié)點維護(hù)的路由表信息和網(wǎng)絡(luò)規(guī)模無關(guān)為O(d) 。

          上述四種基于DHT的P2P系統(tǒng)的性能比較可以參照[12]。DHT這類結(jié)構(gòu)最大的問題是DHT的維護(hù)機(jī)制較為復(fù)雜,尤其是結(jié)點頻繁加入退出造成的網(wǎng)絡(luò)波動(Churn)會極大增加DHT的維護(hù)代價。DHT所面臨的另外一個問題是DHT僅支持精確關(guān)鍵詞匹配查詢,無法支持內(nèi)容/語義等復(fù)雜查詢。

          半分布式拓?fù)浣Y(jié)構(gòu)(有的文獻(xiàn)亦稱作混雜模式,英文表達(dá)為Hybrid Structure)吸取了中心化結(jié)構(gòu)和全分布式非結(jié)構(gòu)化拓?fù)涞膬?yōu)點,選擇性能較高(處理、存儲、帶寬等方面性能)的結(jié)點作為超級結(jié)點(英文表達(dá)為SuperNodes或者Hubs),在各個超級結(jié)點上存儲了系統(tǒng)中其他部分結(jié)點的信息,發(fā)現(xiàn)算法僅在超級結(jié)點之間轉(zhuǎn)發(fā),超級結(jié)點再將查詢請求轉(zhuǎn)發(fā)給適當(dāng)?shù)娜~子結(jié)點。半分布式結(jié)構(gòu)也是一個層次式結(jié)構(gòu),超級結(jié)點之間構(gòu)成一個高速轉(zhuǎn)發(fā)層,超級結(jié)點和所負(fù)責(zé)的普通結(jié)點構(gòu)成若干層次。采用這種結(jié)構(gòu)的最典型的案例就是KaZaa

          圖5 半分布式拓?fù)浣Y(jié)構(gòu)(網(wǎng)絡(luò)中包含Super Node)

          KaZaa是當(dāng)前世界最流行的幾款P2P文件共享軟件之一。根據(jù)CA公司統(tǒng)計,全球KaZaa的下載量超過2.5億次。使用KaZaa軟件進(jìn)行文件傳輸消耗了互聯(lián)網(wǎng)40%的帶寬。之所以它如此的成功,是因為它結(jié)合了Napster和Gnutella共同的優(yōu)點。從結(jié)構(gòu)上來說,它使用了Gnutella的全分布式的結(jié)構(gòu),這樣可以是系統(tǒng)更好的擴(kuò)展,因為它無需中央索引服務(wù)器存儲文件名,它是自動的把性能好的機(jī)器成為SuperNode,它存儲著離它最近的葉子節(jié)點的文件信息,這些SuperNode,再連通起來形成一個Overlay Network. 由于SuperNode的索引功能,使搜索效率大大提高。

          圖6 KaZaa的軟件界面

          半分布式結(jié)構(gòu)的優(yōu)點是性能、可擴(kuò)展性較好,較容易管理,但對超級點依賴性大,易于受到攻擊,容錯性也受到影響。

          在實際應(yīng)用中,每種拓?fù)浣Y(jié)構(gòu)的P2P網(wǎng)絡(luò)都有其優(yōu)缺點,下表從可擴(kuò)展性、可靠性、可維護(hù)性、發(fā)現(xiàn)算法的效率、復(fù)雜查詢等方面比較了這四種拓?fù)浣Y(jié)構(gòu)的綜合性能。

          比較標(biāo)準(zhǔn)/拓?fù)浣Y(jié)構(gòu)

          中心化拓?fù)?/p>

          全分布式非結(jié)構(gòu)化拓?fù)?/p>

          全分布式結(jié)構(gòu)化拓?fù)?/p>

          半分布式拓?fù)?/p>

          可擴(kuò)展性

          可靠性

          可維護(hù)性

          最好

          最好

          發(fā)現(xiàn)算法效率

          最高

          復(fù)雜查詢

          支持

          支持

          不支持

          支持



          我還是比較看好chord...雖然目前還有不少問題沒有解決....
          順便附上一篇經(jīng)典的chord論文: Chord: A Scalable Peertopeer Lookup Service for Internet Applications
          http://www.aygfsteel.com/Files/heiyuchuanxia/chord_sigcomm.rar
          posted @ 2006-11-15 15:28 Stefanie 閱讀(3473) | 評論 (0)編輯 收藏
               摘要: The Summery of OWL-S 1.2 OWL-S is an ontology, within the OWL-based framework of the Semantic Web, for describing Web services. This documen...  閱讀全文
          posted @ 2006-11-12 14:00 Stefanie 閱讀(690) | 評論 (1)編輯 收藏
          ????? 最近的程序中總是出現(xiàn)寫奇怪的問題....于是乎就查了一點相關(guān)的資料....找到了這樣一片相關(guān)的文章....感覺收獲挺多了.....??????分享分享.......
          ??
          ????? 關(guān)于Java 初始化,有多文章都用了很大篇幅的介紹。經(jīng)典的<<Thinking in java>>更是用了專門的一章來介紹Java初始化。但在大量有代碼實例后面,感覺上仍然沒有真正深入到初始化的本質(zhì)。

            本文以作者對JVM的理解和自己的經(jīng)驗,對Java的初始化做一個比深入的說明,由于作者有水平限制,以及JDK各實現(xiàn)版本的變化,可能仍然有不少錯誤和缺點。歡迎行家高手賜教。

            要深入了解Java初始化,我們無法知道從程序流程上知道JVM是按什么順序來執(zhí)行的。了解JVM的執(zhí)行機(jī)制和堆棧跟蹤是有效的手段。可惜的是,到目前為止。JDK1。4和JDK1。5在javap功能上卻仍然存在著BUG。所以有些過程我無法用實際的結(jié)果向你證明兩種相反的情況。

            <<Thinking in java>>(第三版)在第四章一開始的時候,這樣來描述Java的初始化工作:

            以下譯文原文:

            可以這樣認(rèn)為,每個類都有一個名為Initialize()的方法,這個名字就暗示了它得在使用之前調(diào)用,不幸的是,這么做的話,用戶就得記住要調(diào)用這個方法,java類庫的設(shè)計者們可以通過一種被稱為構(gòu)造函數(shù)的特殊方法,來保證每個對象都能得到被始化.如果類有構(gòu)造函數(shù),那么java就會在對象剛剛創(chuàng)建,用戶還來不及得到的時候,自動調(diào)用那個構(gòu)造函數(shù),這樣初始化就有保障了。

            我不知道原作者的描述和譯者的理解之間有多大的差異,結(jié)合全章,我沒有發(fā)現(xiàn)兩個最關(guān)鍵的字"<clinit>"和"<init>"。至少說明原作者和譯者并沒有真正說明JVM在初始化時做了什么,或者說并不了解JVM的初始化內(nèi)幕,要不然明明有這兩個方法,卻為什么要認(rèn)為有一個事實上并不存在的"Initialize()"方法呢?

            "<clinit>"和"<init>"方法在哪里?這兩個方法是實際存在而你又找不到的方法,也許正是這樣才使得一些大師都犯暈。加上jdk實現(xiàn)上的一些BUG,如果沒有深入了解,真的讓人摸不著北。

            現(xiàn)在科學(xué)體系有一個奇怪的現(xiàn)象,那么龐大的體系最初都是建立在一個假設(shè)的基礎(chǔ)是,假設(shè)1是正確的,由此推導(dǎo)出2,再繼續(xù)推導(dǎo)出10000000000。可惜的是太多的人根本不在乎2-100000000000這樣的體系都是建立在假設(shè)1是正確的基礎(chǔ)上的。我并不會用“可以這樣認(rèn)為”這樣的假設(shè),我要確實證明"<clinit>"和"<init>"方法是真真實實的存在的:

           package debug;
           public class MyTest{
            static int i = 100/0;
            public static void main(String[] args){
             Ssytem.out.println("Hello,World!");
            }
           }
          

            執(zhí)行一下看看,這是jdk1.5的輸出:

          java.lang.ExceptionInInitializerError
          Caused by: java.lang.ArithmeticException: / by zero
           at debug.MyTest.(Test.java:3)
          Exception in thread "main" 
          

            請注意,和其它方法調(diào)用時產(chǎn)生的異常一樣,異常被定位于debug.MyTest的<clinit>.

            再來看:

          package debug;
          public class Test {
            Test(){
                int i = 100 / 0;
            }
            public static void main(String[] args) {
              new Test();
            }
          }
          jdk1.5輸入:
          Exception in thread "main" java.lang.ArithmeticException: / by zero at debug.Test.<init>(Test.java:4) at debug.Test.main(Test.java:7)
          JVM并沒有把異常定位在Test()構(gòu)造方法中,而是在debug.Test.<init>。

            當(dāng)我們看到了這兩個方法以后,我們再來詳細(xì)討論這兩個“內(nèi)置初始化方法”(我并不喜歡生造一些

            非標(biāo)準(zhǔn)的術(shù)語,但我確實不知道如何規(guī)范地稱呼他們)。

            內(nèi)置初始化方法是JVM在內(nèi)部專門用于初始化的特有方法,而不是提供給程序員調(diào)用的方法,事實上“<>”這樣的語法在源程序中你連編譯都無法通過。這就說明,初始化是由JVM控制而不是讓程序員來控制的。

          類初始化方法:<clinit>

            我沒有從任何地方了解到<clinit>的cl是不是class的簡寫,但這個方法確實是用來對“類”進(jìn)行初

            始化的。換句話說它是用來初始化static上下文的。

            在類裝載(load)時,JVM會調(diào)用內(nèi)置的<clinit>方法對類成員和靜態(tài)初始化塊進(jìn)行初始化調(diào)用。它們的順序按照源文件的原文順序。

            我們稍微增加兩行static語句:

          package debug;
          public class Test {
            static int x = 0;
            static String s = "123";
            static {
              String s1 = "456";
              if(1==1)
              throw new RuntimeException();
            }
            public static void main(String[] args) {
              new Test();
            }
          }
          

            然后進(jìn)行反編譯:

          javap -c debug.Test
          Compiled from "Test.java"
          public class debug.Test extends java.lang.Object{
          static int x;
          static java.lang.String s;
          public debug.Test();
            Code:
             0:   aload_0
             1:   invokespecial   #1; //Method java/lang/Object."":()V
             4:   return
          public static void main(java.lang.String[]);
            Code:
             0:   new     #2; //class debug/Test
             3:   dup
             4:   invokespecial   #3; //Method "":()V
             7:   pop
             8:   return
          static {};
            Code:
             0:   iconst_0
             1:   putstatic       #4; //Field x:I
             4:   ldc     #5; //String 123
             6:   putstatic       #6; //Field s:Ljava/lang/String;
             9:   ldc     #7; //String 456
             11:  astore_0
             12:  new     #8; //class java/lang/RuntimeException
             15:  dup
             16:  invokespecial   #9; //Method java/lang/RuntimeException."":()V
             19:  athrow
          我們可以看到,類初始化正是按照源文件中定義的原文順序進(jìn)行。先是聲明
            static  int x;
            static  java.lang.String s;

            然后對int x和String s進(jìn)行賦值:

             0:   iconst_0
             1:   putstatic       #4; //Field x:I
             4:   ldc     #5; //String 123
             6:   putstatic       #6; //Field s:Ljava/lang/String;
          

            執(zhí)行初始化塊的String s1 = "456";生成一個RuntimeException拋

             9:   ldc     #7; //String 456
             11:  astore_0
             12:  new     #8; //class java/lang/RuntimeException
             15:  dup
             16:  invokespecial   #9; //Method java/lang/RuntimeException."":()V
             19:  athrow
          

            要明白的是,"<clinit>"方法不僅是類初始化方法,而且也是接口初始化方法。并不是所以接口

            的屬性都是內(nèi)聯(lián)的,只有直接賦常量值的接口常量才會內(nèi)聯(lián)。而

            [public static final] double d = Math.random()*100;

            這樣的表達(dá)式是需要計算的,在接口中就要由"<clinit>"方法來初始化。

          下面我們再來看看實例初始化方法"<init>"

            "<init>"用于對象創(chuàng)建時對對象進(jìn)行初始化,當(dāng)在HEAP中創(chuàng)建對象時,一旦在HEAP分配了空間。最先就會調(diào)用"<init>"方法。這個方法包括實例變量的賦值(聲明不在其中)和初始化塊,以及構(gòu)造方法調(diào)用。如果有多個重載的構(gòu)造方法,每個構(gòu)造方法都會有一個對應(yīng)的"<init>"方法。構(gòu)造方法隱式或顯示調(diào)用父類的構(gòu)造方法前,總是先執(zhí)行實例變量初始化和初始化塊.同樣,實例變量和初始化塊的順序也是按源文件的原文順序執(zhí)行,構(gòu)造方法中的代碼在最后執(zhí)行:


          package debug;
          public class Test {
            int x = 0;
            String s = "123";
            {
              String s1 = "456";
              //if(1==1)
              //throw new RuntimeException();
            }
            public Test(){
              String ss = "789";
            }
            public static void main(String[] args) {
              new Test();
            }
          }
          javap -c debug.Test的結(jié)果:
          Compiled from "Test.java"
          public class debug.Test extends java.lang.Object{
          int x;
          java.lang.String s;
          public debug.Test();
            Code:
             0:   aload_0
             1:   invokespecial   #1; //Method java/lang/Object."":()V
             4:   aload_0
             5:   iconst_0
             6:   putfield        #2; //Field x:I
             9:   aload_0
             10:  ldc     #3; //String 123
             12:  putfield        #4; //Field s:Ljava/lang/String;
             15:  ldc     #5; //String 456
             17:  astore_1
             18:  ldc     #6; //String 789
             20:  astore_1
             21:  return
          public static void main(java.lang.String[]);
            Code:
             0:   new     #7; //class debug/Test
             3:   dup
             4:   invokespecial   #8; //Method "":()V
             7:   pop
             8:   return
          }
          

            如果在同一個類中,一個構(gòu)造方法調(diào)用了另一個構(gòu)造方法,那么對應(yīng)的"<init>"方法就會調(diào)用另一

            個"<init>",但是實例變量和初始化塊會被忽略,否則它們就會被多次執(zhí)行。

          package debug;
          public class Test {
            String s1 = rt("s1");
            String s2 = "s2";
            
            public Test(){
              s1 = "s1";
            }
            public Test(String s){
              this();
              if(1==1) throw new Runtime();
            }
            String rt(String s){
              return s;
            }
            public static void main(String[] args) {
              new Test("");
            }
          }
          

            反編譯的結(jié)果:

          Compiled from "Test.java"
          public class debug.Test extends java.lang.Object{
          java.lang.String s1;
          java.lang.String s2;
          public debug.Test();
            Code:
             0:   aload_0
             1:   invokespecial   #1; //Method java/lang/Object."":()V
             4:   aload_0
             5:   aload_0
             6:   ldc     #2; //String s1
             8:   invokevirtual   #3; //Method rt:(Ljava/lang/String;)Ljava/lang/String;
             11:  putfield        #4; //Field s1:Ljava/lang/String;
             14:  aload_0
             15:  ldc     #5; //String s2
             17:  putfield        #6; //Field s2:Ljava/lang/String;
             20:  aload_0
             21:  ldc     #2; //String s1
             23:  putfield        #4; //Field s1:Ljava/lang/String;
             26:  return
          public debug.Test(java.lang.String);
            Code:
             0:   aload_0
             1:   invokespecial   #7; //Method "":()V
             4:   new     #8; //class java/lang/RuntimeException
             7:   dup
             8:   invokespecial   #9; //Method java/lang/RuntimeException."":()V
             11:  athrow
          java.lang.String rt(java.lang.String);
            Code:
             0:   aload_1
             1:   areturn
          public static void main(java.lang.String[]);
            Code:
             0:   new     #10; //class debug/Test
             3:   dup
             4:   ldc     #11; //String
             6:   invokespecial   #12; //Method "":(Ljava/lang/String;)V
             9:   pop
             10:  return
          }
          

            我們看到,由于Test(String s)調(diào)用了Test();所以"<init>":(Ljava/lang/String;)V不再對

            實例變量和初始化塊進(jìn)次初始化:

          public debug.Test(java.lang.String);
            Code:
             0:   aload_0
             1:   invokespecial   #7; //Method "":()V
             4:   new     #8; //class java/lang/RuntimeException
             7:   dup
             8:   invokespecial   #9; //Method java/lang/RuntimeException."":()V
             11:  athrow
          

            而如果兩個構(gòu)造方法是相互獨立的,則每個構(gòu)造方法調(diào)用前都會執(zhí)行實例變量和初始化塊的調(diào)用:

          package debug;
          public class Test {
            String s1 = rt("s1");
            String s2 = "s2";
            {
              String s3 = "s3";
            }
            public Test() {
              s1 = "s1";
            }
            public Test(String s) {
              if (1 == 1) 
                throw new RuntimeException();
            }
            String rt(String s) {
              return s;
            }
            public static void main(String[] args) {
              new Test("");
            }
          }
          

            反編譯的結(jié)果:

          Compiled from "Test.java"
          public class debug.Test extends java.lang.Object{
          java.lang.String s1;
          java.lang.String s2;
          public debug.Test();
            Code:
             0:   aload_0
             1:   invokespecial   #1; //Method java/lang/Object."":()V
             4:   aload_0
             5:   aload_0
             6:   ldc     #2; //String s1
             8:   invokevirtual   #3; //Method rt:(Ljava/lang/String;)Ljava/lang/String;
             11:  putfield        #4; //Field s1:Ljava/lang/String;
             14:  aload_0
             15:  ldc     #5; //String s2
             17:  putfield        #6; //Field s2:Ljava/lang/String;
             20:  ldc     #7; //String s3
             22:  astore_1
             23:  aload_0
             24:  ldc     #2; //String s1
             26:  putfield        #4; //Field s1:Ljava/lang/String;
             29:  return
          public debug.Test(java.lang.String);
            Code:
             0:   aload_0
             1:   invokespecial   #1; //Method java/lang/Object."":()V
             4:   aload_0
             5:   aload_0
             6:   ldc     #2; //String s1
             8:   invokevirtual   #3; //Method rt:(Ljava/lang/String;)Ljava/lang/String;
             11:  putfield        #4; //Field s1:Ljava/lang/String;
             14:  aload_0
             15:  ldc     #5; //String s2
             17:  putfield        #6; //Field s2:Ljava/lang/String;
             20:  ldc     #7; //String s3
             22:  astore_2
             23:  new     #8; //class java/lang/RuntimeException
             26:  dup
             27:  invokespecial   #9; //Method java/lang/RuntimeException."":()V
             30:  athrow
          java.lang.String rt(java.lang.String);
            Code:
             0:   aload_1
             1:   areturn
          public static void main(java.lang.String[]);
            Code:
             0:   new     #10; //class debug/Test
             3:   dup
             4:   ldc     #11; //String
             6:   invokespecial   #12; //Method "":(Ljava/lang/String;)V
             9:   pop
             10:  return
          }
          

            明白了上面這些知識,我們來做一個小測試吧:

          public class Test2 extends Test1{
           {
            System.out.print("1");
           }
           Test2(){
            System.out.print("2");
           }
           static{
            System.out.print("3");
           }
           {
            System.out.print("4");
           }
           public static void main(String[] args) {
            new Test2();
           }
          }
          class Test1 {
           Test1(){
            System.out.print("5"); 
           }
           static{
            System.out.print("6");
           }
          }
          

            試試看能清楚打印的順序嗎?如果沒有new Test2()將打印什么?


          作者:axman 專欄:http://blog.csdn.net/axman/
          posted @ 2006-11-05 14:43 Stefanie 閱讀(385) | 評論 (0)編輯 收藏
          主站蜘蛛池模板: 台南县| 丹江口市| 新乡市| 杭锦旗| 西林县| 忻城县| 屏东市| 阆中市| 宜黄县| 临城县| 呼图壁县| 平潭县| 望谟县| 峨边| 扶余县| 温州市| 临邑县| 柳林县| 中阳县| 靖州| 密山市| 涪陵区| 乌什县| 天水市| 陵川县| 正宁县| 永安市| 奎屯市| 沙湾县| 威海市| 武城县| 辽阳市| 乐清市| 香格里拉县| 邳州市| 赤城县| 石首市| 峨边| 和龙市| 清丰县| 琼中|