??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲综合欧美色五月俺也去,亚洲一区二区精品视频,日本中文一区二区三区亚洲http://www.tkk7.com/yydy1983/category/35723.html<a target="_blank"><img src="http://www.doudou.com/images/top_03.jpg" border="0" /></a> &nbsp &nbsp <a target="_blank"><img src="http://www.doudou.com/images/gamenew1_23.gif" width="151" height="62" border="0" /></a><br>zh-cnWed, 17 Dec 2008 19:08:42 GMTWed, 17 Dec 2008 19:08:42 GMT602.5 使用正则表达式进行替?/title><link>http://www.tkk7.com/yydy1983/articles/246997.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Wed, 17 Dec 2008 17:01:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/246997.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/246997.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/246997.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/246997.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/246997.html</trackback:ping><description><![CDATA[<p><strong>2.5  使用正则表达式进行替?/strong> <br /> <br /> 在上一节中Q介l了用于匚w一个String中的模式和用于从一个子模式l中(g)索数据的正则表达式。用regexQ还可以用新的值替代匹配的模式。完成此操作的一U方法是使用MatchercȝreplaceAllҎ(gu)Q它?yu)返回一个字W串Q将所有匹配的子串替换为给定的字符丌Ӏؓ(f)了说明此Ҏ(gu)Q查找一个文件内出现的所有repetition单词q用单词duplication来替换它们:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String data = getStringData();<br /> Pattern repPattern = Pattern.compile("(<a href="file://s)(repetition)(%5B//s;//">\\s)(repetition)([\\s;\\</a>.,])");<br /> Matcher repMatcher = repPattern.matcher(data);<br /> String newData = repMatcher.replaceAll("$1duplication$3"); </pre> </td> </tr> </tbody> </table> <p>Z查找单词Q需要捕获它前后的空?或标点符?。需要注意的是,如果此单词出现在data字符串的开_(d)那么上述的代码不?x)匹配它Q因为已假定它的前后存在I白W。除了单词repetition被替换外Q我们希望文本中的其他内容与原始文本保持一_(d)包括单词周围的空白字W。这里的元W号($)昄不表C币。它表示对从regex模式中捕L(fng)l?和组3的逆向引用Q包含最初匹配的I白或标点符受这P与它们对应的值将插入到替换文本中?/p> <p>Stringc?在JDK 1.4或更高的版本?有一个replaceAllҎ(gu)Q其工作机制cM于Matcher中的replaceAllҎ(gu)。这使得它可以很方便地替换一个与模式匚w的子Ԍ(x)<br /> </p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String data = getStringData();<br /> String result =<br /> data.replaceAll("(<a href="file://s)(repetition)(%5B//s;//">\\s)(repetition)([\\s;\\</a>.,])", "$1duplication$3"); </pre> </td> </tr> </tbody> </table> <p>replaceAllҎ(gu)q回一个新的字W串Q其中所有匹配的部分已被新值替换。但是,使用Matcher仍有很多优点Q因为相对于字符串它有更大的灉|性?/p> <p>可以使用Matcher的find循环用新gơ替换每个匹配的部分。这样你能够更好地控制替换q程。比如,可以在每ơ匹配的q程中应用其他逻辑Q甚xơ可以替换不同的倹{这qCStringBufferQStringBuffer用于保存更新的文本,q且一旦调用appendReplacementҎ(gu)QMatcherp加更新后的文本到~存中。在处理每个匚wq执行替换后Q需要用appendTailҎ(gu)最后一ơ匹配后的剩余字W串攄在输出缓存中。图2-1说明了子串匹配和q两U方法之间的关系?br /> </p> <table class="ln" cellspacing="0" bordercolordark="#ffffff" align="center" bgcolor="#ddddd" bordercolorlight="#999999" border="1"> <tbody> <tr> <td bgcolor="#ffffff"><a target="_blank"><img class="fit-image" onmousewheel="javascript:return big(this)" style="zoom: 120%" height="179" alt="" src="http://new.51cto.com/files/uploadimg/20071108/134652727.gif" width="486" onload="javascript:if(this.width />498)this.style.width=498;" border=0></a><a target="_blank"></a></td> </tr> <tr> <td class="it" align="center" bgcolor="#dddddd">?-1  MatchercȝappendҎ(gu) </td> </tr> </tbody> </table> Matcher有一个相应的append指针。指针最初从零开始,随着每次调用appendReplacement向前Ud。这U设计是Z在一个find循环内用它。每ơ匹配后Q调用appendReplacementҎ(gu)QMatcher指针所在的上一个位|到匚w之前指针所在的位置之间的内容,x更改的文本合q到StringBuffer中。然后,Matcher替换当前匚w的文本ƈ替换后的内Ҏ(gu)|在StringBuffer中。接下来QMatcherappend指针Ud到当前匹配结之后的W一个字W,然后重复此过E直C再生匹配。在扑ֈ所有匹配之后很可能剩下一个未匚w的部分。ؓ(f)了将q部分文本添加到输出StringBuffer中,使用appendTailҎ(gu)?br /> 现在使用q些Ҏ(gu)前面的替换例子重写Z个@环。但是这一ơ对于每个匹配,用一个随机选择的同义词(repetition、duplication、copying、reiteration、recurrence或redundancy)来替代单词repetitionQ? <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>StringBuffer result = new StringBuffer();<br /> String[] wordChoices = new String[]<br /> {"repetition", "duplication", "copying",<br /> "reiteration", "recurrence", "redundancy"};<br /> Random rand = new Random();<br /> String data = getStringData();<br /> Pattern repPattern = Pattern.compile("(<a href="file://s)(repetition)(%5B//s;//">\\s)(repetition)([\\s;\\</a>.,])");<br /> Matcher repMatcher = repPattern.matcher(data);<br /> while (repMatcher.find()) {<br /> // pick a word at random<br /> int wordIndex = rand.nextInt(wordChoices.length);<br /> String replacement = "$1" + wordChoices[wordIndex] + "$3";<br /> repMatcher.appendReplacement(result, replacement);<br /> }<br /> repMatcher.appendTail(result);<br /> System.out.println(result); </pre> </td> </tr> </tbody> </table> <br /> 可以按需求改写find循环中的逻辑来对每个匚wq行所需的处理。此外,q可以用前面讨的Matcher的方法:(x)group、start和end。可以用这些技术的l合有选择CҎ(gu)删除一个文件中每部分匹配的文本? <img src ="http://www.tkk7.com/yydy1983/aggbug/246997.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-12-18 01:01 <a href="http://www.tkk7.com/yydy1983/articles/246997.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2.4 使用Regex捕获l?/title><link>http://www.tkk7.com/yydy1983/articles/245894.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Fri, 12 Dec 2008 03:38:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/245894.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/245894.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/245894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/245894.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/245894.html</trackback:ping><description><![CDATA[<p><strong>2.4  使用Regex捕获l?<br /> </strong> <br /> 在上一节中Q介l了如何使用正则表达式在一个文件中q行搜烦(ch)以便(g)索它内部所有的URL。可以用Matchercȝfind、start和endҎ(gu)来检索匹配的URL字符丌Ӏ有时有必要q一步处理子串匹配的l果Q或是查N加的子模式。例如,Ҏ(gu)个特定区域的URL不进行处理。ؓ(f)了实现此目的Q一U强制性的Ҏ(gu)是用另一个Pattern和Matcher对象Q代码如下:(x)</p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>// assume urlMatcher instance as in the previous example<br /> while (urlMatcher.find()) {<br /> int startIndex = urlMatcher.start();<br /> int endIndex = urlMatcher.end();<br /> String currentMatch = data.substring(startIndex, endIndex);<br /> // the brute force approach, using a new pattern!<br /> Pattern restricted = Pattern.compile(".*(abc|cbs|nbc)\\.com.*");<br /> Matcher restrictMatcher = restricted.matcher(currentMatch);<br /> if (!restrictMatcher.matches()) {<br /> System.out.println(currentMatch);<br /> }<br /> }<br /> </pre> </td> </tr> </tbody> </table> 在捕L(fng)URL中匹配域名ƈ不是一个非帔R效的Ҏ(gu)。由于已l用findҎ(gu)完成了提取URL的困隑ַ作,不应该仅仅ؓ(f)了获得结果的一部分而编写另一个regexQƈ且也不必q样做。正则表辑ּ允许模式分解成子序列。用圆括号Q将以后要用到的模式部分括v来,q样Q我们就可以忽略其余部分单独dq些部分的倹{重写URL模式以域名可以与URL的其他部分相分离Q?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String urlPattern =<br /> "(http|https|ftp)://([a-zA-Z0-9-\\.]+)[/\\w\\.\\-\\+\\?%=&;:,#]*";</pre> </td> </tr> </tbody> </table> 当在模式中存在用括号括v来的l时Q可以分别检索每个组的匹配倹{从最左边的组开始编?Q然后依ơ对每对括号相对应的l进行编受在上面的模式中Q第一l是协议(如http)Q第二组是域名。ؓ(f)了在匚w的字W串中访问组Q可以用Matcher的groupҎ(gu)。下面的代码CZ从每个URL中检索域名ƈ昄它们的|(x)</p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String data = getStringData(); // load the document<br /> String urlString =<br /> "(http|https|ftp)://([a-zA-Z0-9-\\.]+)[/\\w\\.\\-\\+\\?%=&;:,#]*";<br /> Pattern urlPattern = Pattern.compile(urlString);<br /> Matcher urlMatcher = urlPattern.matcher(data);<br /> // print out the domain from each URL<br /> while (urlMatcher.find()) {<br /> String domain = urlMatcher.group(2); // 2nd group is the domain<br /> System.out.println(domain);<br /> }<br /> </pre> </td> </tr> </tbody> </table> </p> <p>保存每个匚w的组以便可以随后引用它们。在一个模式内引用一个以前的匚wl称为逆向引用(backreference)。ؓ(f)了对W三个组q行逆向引用Q在模式中包括\3卛_。这会(x)只匹配一个与以前的组相匹配的严格重复的数据。ؓ(f)了说明此问题Q考虑一个在文本文g中常见的错误—?一个句子中意外地重复出现某个常用的单词Q如“the”?#8220;of”?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>" The the water molecules are made of of hydrogen and oxygen."</pre> </td> </tr> </tbody> </table> </p> <p>下面~写一个模式来扑և文g中存在的q些问题。该模式捕L(fng)一个单词,后跟一些空白符Q而其后又跟着匚wW一个单词的重复模式Q?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String wordPattern = "<a href="file://s(of%7Cor%7Cthe%7Cto)//s+//1%5B//s//">\\s(of|or|the|to)\\s+\\1[\\s\\</a>.,;]";<br /> </pre> </td> </tr> </tbody> </table> 该模式匹配情况如下:(x)一个空白字W、特D的单词列表中的一个单词、更多的I白、再ơ重复的相同的单?使用\1逆向引用)以及(qing)I白W或标点W号。这U匹配应不区分大写Q以便能够捕获到“The the”以及(qing)cM的变型。如以下的代码段所C,该模式不区分大小写,能在一个字W串中查N复出现的模式Q?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String data = getStringData();<br /> String patternStr = "<a href="file://s(of%7Cor%7Cthe%7Cto)//s+//1%5B//s//">\\s(of|or|the|to)\\s+\\1[\\s\\</a>.,;]";<br /> Pattern wordPattern =<br /> Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);<br /> Matcher wordMatcher = wordPattern.matcher(data);<br /> while (wordMatcher.find()) {<br /> int start = wordMatcher.start();<br /> String word = wordMatcher.group(1);<br /> // print the index location of the repeated word<br /> System.out.println("Repeated " + word + " starting at " + start);<br /> }<br /> </pre> </td> </tr> </tbody> </table> </p> <p>有一U简便和强大的匹配文件中文本的方法,该方法允怋用多个正则表辑ּ来处理文Ӟ本章后面?#8220;使用Scannerc进行语法分?#8221;一节将?x)讲解此?gu)。若想了解用内|烦(ch)引进行更为复杂的文本搜烦(ch)的解x法,请参考第3章中“使用Luceneq行搜烦(ch)”一节的内容?/p> <img src ="http://www.tkk7.com/yydy1983/aggbug/245894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-12-12 11:38 <a href="http://www.tkk7.com/yydy1983/articles/245894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>2.1 使用正则表达式来搜烦(ch)文本http://www.tkk7.com/yydy1983/articles/244067.html♂游泳的?/dc:creator>♂游泳的?/author>Wed, 03 Dec 2008 01:34:00 GMThttp://www.tkk7.com/yydy1983/articles/244067.htmlhttp://www.tkk7.com/yydy1983/comments/244067.htmlhttp://www.tkk7.com/yydy1983/articles/244067.html#Feedback0http://www.tkk7.com/yydy1983/comments/commentRss/244067.htmlhttp://www.tkk7.com/yydy1983/services/trackbacks/244067.html很长旉以来QUnix理用户使用Z正则表达式的命o(h)或程序,如grep、perl、sed和awk。由于这是一个非常强大的搜烦(ch)和操U字W串的手D,Java 1.4向核心APId了java.util.regexE序包。当?dng)Java是与q_无关的,q些正则表达式可以运行在Mpȝ上,而不仅仅是Unix。JDK中包含RegexE序包已有一D|_(d)但是我仍发现很多Java~程人员从未使用q它。Regex模式是一U有价值的基础工具Q可以用于很多类型的文本处理Q如匚w、搜索、提取、替换和分析l构化内宏V?

在Java中,通过使用适当命名的Patterncd以容易地定String是否匚w某种模式。模式可以像匚w某个特定的String值那L(fng)单,也可以很复杂Q需要采用分l和字符c,如空白、数字、字母或控制W。由于它们是Java字符串ƈ且基于Unicode(l一字符~码)Q正则表辑ּ也适用于国际化的应用程序?/p>

正则式是最单的能准匹配一个给定String的模式。换句话_(d)模式与所要匹配的文本是等L(fng)。静态的Pattern.matchesҎ(gu)用于比较一个String是否匚w一个给定模式?以下的代码将(g)查变量data中的值是否与单词“Java”相匹配:(x)

String data = getStringData(); // populate the String somehow
boolean result = Pattern.matches("Java", data); // is it "Java"?

对于直接匚w字符串和单的模式而言Q你很可能不?x)用正则表辑ּQ因实际上就是低效率版本?Java".equals(data)。Regex的真正强大之处体现在使用包括字符cd量词(*??)的更复杂的模式上。目前已有很多优U的有x则表辑ּ模式的书c,因此q里只讨论模式的一些基本特性ƈ重点讨论Java的regexcdҎ(gu)。ؓ(f)了快速了解这些特性,q里l出一些在正则表达式中使用的特D字W,其中每一个均代表一cdW,在regex术语中它UCؓ(f)字符c:(x)

\d   数字 
\D  非数?
\w  单字字符(0–9QA–ZQa–zQ_ )
\W  非单字字W?
\s   I白(I格W、换行符、回车键、制表符)
\S   非空?
[ ]  由方括号内的一个字W列表创建的自定义字W类
.    匚wM单个字符(除了换行W?

大多数字W在一个模式表辑ּ中代表它们自己,但是一些字W有其特D含义。上面用的反斜?转义字符)是一个例子。下面的字符用于控制一个子模式应用到匹配过E的ơ数。这些特D字W的处理方式不同于其他字W:(x)

?   重复前面的子模式零次或一?
*   重复前面的子模式零次或多?br /> +   重复前面的子模式一ơ或多次

下面的正则表辑ּ可以匚wM对先辈的U呼Q如father、great-great-grandmother或great-great-great-grandfather。正如下面的CZ所C,通过使用括弧中的子表辑ּ可以创徏更复杂的正则表达式:(x)

((great–)*grand)?(mother|father)

接下来这个模式表辑ּ会(x)匚w一个以一个数字开头后跟零个或多个非空白字W的L字符?例如它将匚w“3”?#8220;5x”?#8220;56abcd9”Q而不匚w“8 5”?#8220;hello”)Q?/p>

\d\S*  

要}慎用regex反斜杠字W,因ؓ(f)在Java中它也是String文字转义字符。如果用一个String文字来保存正则表辑ּQ将需要通过使用两个反斜杠来转义反斜杠本w。例如:(x)

String digitNonSpacePattern = "\\d\\S*";
String data = getStringData();
boolean isMatch = Pattern.matches(digitNonSpacePattern, data);

此外Q模式匹配也内置于StringcLw。在StringcM有一个新的简便方法:(x)matches。可以如下重写以上的代码Q?/p>

boolean isMatch = getStringData().matches("\\d\\S*"); 

Pattern.matchesҎ(gu)和String的matchesҎ(gu)都适合一ơ性用,但是若重复用它们的效率较低。通过使用静态的Pattern.compileҎ(gu)创徏一个Pattern实例可以得到一个更高效的用于执行多ơ匹配的~译版本的模式。Pattern对象可以和java.util.regex.Matchercd同工作。ؓ(f)了执行复杂的匚wQ需要创建Matcher(匚w?。Matcher一个模式表辑ּl定C个特定的字符Ԍ以便执行更高U的匚w操作。以下的代码D늼译了一个匹配仅由单个字W组成的模式Q?/p>

String data = getStringData();
Pattern namePattern = Pattern.compile("\\w+");
// get a Matcher to apply the pattern to the data
Matcher nameMatcher = namePattern.matcher(data);
boolean isMatch = nameMatcher.matches();

要记住matchesҎ(gu)会(x)Ҏ(gu)个输入字W串和模式进行匹配。如果希望检查字W串是否仅以模式开_(d)则可以用lookingAtҎ(gu)Q?

boolean startsWith = nameMatcher.lookingAt(); 

在以下几个小节中会(x)讨论其他一些匹配技术,包括查找匚w一个模式的子串以及(qing)执行文本替换?



]]>
1.10 ?=”不{于?equals?/title><link>http://www.tkk7.com/yydy1983/articles/java.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Wed, 26 Nov 2008 00:55:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/java.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/242711.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/java.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/242711.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/242711.html</trackback:ping><description><![CDATA[<p><strong>1.10  “==”不等?#8220;.equals”</strong></p> <p>q里丑և一个Java~程E序员经常碰到的问题。例如现在是凌晨3点,在你喝完W?杯咖啡后Q你设法扑ֈ正确的逻辑来解军_杂的~程问题。到目前Q你几乎不能思考String和Object引用Q因Z已经昏昏Ʋ睡了。然后糟p的事情发生?#8230;…不,q不是Java溢出Q而是如下所C?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String name = getName();<br /> if (name == "Sleepy") // oops!<br /> {<br /> doSomething();<br /> }<br /> </pre> </td> </tr> </tbody> </table> </p> <p>你快速编译ƈ试代码后,代码g正常q行。终于到下班回家休息的时候了Q然而,一D|间后Q应用程序测试发C一个间歇性错误,q跟t到此错误的来源恰好是这D代码?/p> <p>“怎么?x)这P”你可能会(x)愤怒地_(d)“前几天我q试验过cM的String比较Qƈ且能够正运行!”。但是,你需要首先重温一下Java对象引用的概c(din)一个对象变量是一个指向存储在堆内?heap memory)中实际对象的引用(指针)。当为另一个变量分配一个变量时Q事实上分配的是引用而不是实际的对象(如图1-1所C?Q?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String a, b, c, d;<br /> a = "123";<br /> b = a;<br /> c = new String("123");<br /> d = "WCJ";<br /> </pre> </td> </tr> </tbody> </table> </p> <table class="ln" cellspacing="0" bordercolordark="#ffffff" align="center" bgcolor="#ddddd" bordercolorlight="#999999" border="1"> <tbody> <tr> <td bgcolor="#ffffff"><a target="_blank"><img class="fit-image" onmousewheel="javascript:return big(this)" style="zoom: 70%" height="545" alt="" src="http://new.51cto.com/files/uploadimg/20071108/112525487.gif" width="441" onload="javascript:if(this.width />498)this.style.width=498;" border=0></a><a target="_blank"></a></td> </tr> <tr> <td class="it" align="center" bgcolor="#dddddd">?1-1  对象引用</td> </tr> </tbody> </table> <p>Java中,“==”q算W用来比较两个引用以查看它们是否指向同一个内存对象。而对于String实例Q运行时状态会(x)可能地保L两个h相同字符信息的String字面值指向同一个内部对象。此q程UCؓ(f)ȝ(interning)Q但是它q不有助于每个String的比较。一个原因是垃圾攉器线E删除了ȝ|另一个原因是String所在的位置可能被一个由String构造函数创建的新实例占用。如果是q样Q?#8220;==”Lq回false?br /> 可以设计equalsҎ(gu)来比较两个对象的状?state)或每个对象的内容。对你自qc,必须重写此方法来使它正确操作。但是如果用equalsҎ(gu)QString实例L能够正确地比较。假定所有的String值是ȝ的,下面的代码段说明了此问题Q?</p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>String name1, name2, name3;<br /> name1 = "123"; <p>name2 = name1;<br /> if (name1 == name2) {}         // true<br /> if (name1.equals(name2)) {}    // true</p> <p>name2 = "123";<br /> if (name1 == name2) {}         // usually true<br /> if (name1.equals(name2)) {}    // true</p> <p>name3 = new String("123");<br /> if (name1 == name3) {}         // false<br /> if (name1.equals(name3)) {}    // true<br /> </p> </pre> </td> </tr> </tbody> </table> </p> <p><br /> <strong>注意Q?/strong></p> <p>L使用.equals来比较两个String|管使用“==”q算W看D够正操作。对于大多数应用E序而言Q即使它能正运行,?#8220;==”代码事实上是错误的,而只有equals是正的。因此告诉所有你的开发同行支持String?#8220;equals(q等)”权吧(q很可能是本书中最差的双关?Q?</p> <img src ="http://www.tkk7.com/yydy1983/aggbug/242711.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-11-26 08:55 <a href="http://www.tkk7.com/yydy1983/articles/java.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1.9 创徏一个匿名的c?/title><link>http://www.tkk7.com/yydy1983/articles/241727.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Thu, 20 Nov 2008 09:50:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/241727.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/241727.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/241727.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/241727.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/241727.html</trackback:ping><description><![CDATA[<p><strong>1.9  创徏一个匿名的c?</strong></p> <p><strong>Java1.1+</strong></p> <p>当进行Java开发时Q有旉要实C个仅包含1~2个方法的接口Qƈ且每个方法只?~2行代码。在AWT和Swing开发中l常?x)出现这U情况,例如当一个displaylg需要一个事件回调方?如一个按钮的ActionListener)时。如果用普通的cL实现此操作,最l会(x)得到很多仅在单个位置上用的型cR其实,Java允许定义内部c,而且可以在GUI架构外用内部类?/p> <p>内部c?inner class)是指在另一个类内部定义的一个类。可以将内部cd义ؓ(f)一个类的成员,如下例所C:(x)</p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public class Linker {<br /> public class LinkedNode {<br /> LinkedNode prev, next;<br /> Object contents;<br /> } <p>public Linker() {<br /> LinkedNode first = new LinkedNode();<br /> LinkedNode second = new LinkedNode();<br /> first.next = second;<br /> first.contents = "This is the first item";<br /> second.prev = first;<br /> second.contents = "This is the second item";<br /> }<br /> } </p> </pre> </td> </tr> </tbody> </table> <p>q是一个在Java中实现的单链表。LinkedNodecLLinkercȝ内部cR尽此cd含在LinkercMQ仍可以从其他类讉K它,因ؓ(f)它定义为公有的(public)。通过使用new Linker.LinkedNode()Q可以从其他cd建它的一个实例。源自核心API的Map.Entrycd是这样一个类Q当在一个映表中检?#8220;??#8221;表项的集合时Qjava.util.MapcM(x)用到此类?/p> <p>此外Q还可以定义一个局限于一个方法的内部cR这U类型的cd在定义它的方法内是可见的。如果要实现一个接口ƈ且希望在Ҏ(gu)内不止一ơ地使用局部类Q那么很可能q样做,如下面这个实例所C:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public class Happiness {<br /> interface Smiler { public void smile(); } <p>public static void main(String[] args)<br /> {<br /> class Happy implements Smiler {<br /> private String more = "";<br /> public void smile() {<br /> System.out.println(":-)" + more);<br /> }<br /> public void happier() {<br /> more += ")";<br /> }<br /> }</p> <p>Happy h1 = new Happy();<br /> h1.smile();<br /> Happy h2 = new Happy();<br /> h2.happier();<br /> h2.smile();<br /> }<br /> } </p> </pre> </td> </tr> </tbody> </table> <br /> 局部内部类的名UCؓ(f)Happy(我喜Ƣ把它看作内部者的c?。它不能从其他Q何类或方法中讉K。用这个局部类是ؓ(f)了实现Smiler接口(它是在Happiness内部定义?。对于很多情况而言Q甚至不需要ؓ(f)一个局部内部类命名—?它可以保持ؓ(f)匿名的。对于实C?~2个方法的接口而言匿名c非常有用,其是当需要创Z个仅使用一ơ的实例的时候。通常情况下不能直接实例化一个接口。例如,不能调用Runnable接口的构造函?q是由Thread使用的接?。下面的做法是非法的Q? <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>Runnable runner = new Runnable(); // not allowed! </pre> </td> </tr> </tbody> </table> <br /> 但是QJava实允许创徏一个用于实现接口的匿名局部类的实例。可以用一U特D的语法来创Z个接口的实例Q? <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>Runnable runner = new Runnable() {<br /> public void run() {<br /> for (int i=0; i<10000000; i++) {<br /> countSheep();<br /> }<br /> }<br /> };</pre> </td> </tr> </tbody> </table> <br /> 此代码创Z一个局部匿名类Q实例化该类qؓ(f)runner变量分配新的实例。需要确保你的类定义(外层花括号之间的代码)实现了接口的所有方法。此外,q可以按照这U方式创建子cR下面的代码实例化Object的一个匿名子cdƈ它分配l一个变量:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>Object timePrinter = new Object() {<br /> public String toString() {<br /> return String.valueOf(System.currentTimeMillis());<br /> }<br /> };<br /> System.out.println(timePrinter); </pre> </td> </tr> </tbody> </table> <br /> 匿名cLJava开发h员常用的一个有用工兗无Z旉要一ơ性地实现一个接?或子c?Q都可以考虑使用q些cR但最好将它们用于仅有一C个方法的型接口?br /> </p> <img src ="http://www.tkk7.com/yydy1983/aggbug/241727.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-11-20 17:50 <a href="http://www.tkk7.com/yydy1983/articles/241727.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1.8 亚毫U的线E休?/title><link>http://www.tkk7.com/yydy1983/articles/241327.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Wed, 19 Nov 2008 05:03:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/241327.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/241327.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/241327.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/241327.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/241327.html</trackback:ping><description><![CDATA[<p><strong>1.8  亚毫U的线E休?/strong></p> <p><font face="楷体_GB2312">Java1.1+</font></p> <p>正如上一节中所讨论的,Java 5在SystemcMd了一个nanoTimeҎ(gu)来确保时间度量能够适应更快的系l。即使在早期版本的Java中,U程可以h于1毫秒的休眠时间。回想一下Java的线E机制有一个sleepҎ(gu)Q该Ҏ(gu)采用一个int参数来表CZ毫秒计量的休眠时间。此外还有一个sleepҎ(gu)Q它接受一个毫U参数和一个以U秒计量的时间参数。如果将毫秒旉设ؓ(f)Ӟ那么U程会(x)休眠指定的纳U?ns)数?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public class MyThread extends Thread {<br /> public void run() {<br /> try {<br /> sleep(10);          // sleep for 10 milliseconds<br /> sleep(0, 10000);    // sleep for 0.01 milliseconds (10000 ns)<br /> } catch (InterruptedException e) {<br /> e.printStackTrace();<br /> }<br /> }<br /> }<br /> </pre> </td> </tr> </tbody> </table> 像前面介绍的nanoTimeҎ(gu)一P该方法存在同L(fng)问题。由于操作系l特性、机器处理速度和系l负载的不同Q实际的休眠旉可能与期望的不同?/p> <img src ="http://www.tkk7.com/yydy1983/aggbug/241327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-11-19 13:03 <a href="http://www.tkk7.com/yydy1983/articles/241327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1.7 以纳U的时间计:(x)使用System.nanoTimehttp://www.tkk7.com/yydy1983/articles/241172.html♂游泳的?/dc:creator>♂游泳的?/author>Tue, 18 Nov 2008 08:57:00 GMThttp://www.tkk7.com/yydy1983/articles/241172.htmlhttp://www.tkk7.com/yydy1983/comments/241172.htmlhttp://www.tkk7.com/yydy1983/articles/241172.html#Feedback0http://www.tkk7.com/yydy1983/comments/commentRss/241172.htmlhttp://www.tkk7.com/yydy1983/services/trackbacks/241172.html1.7  以纳U的时间计:(x)使用System.nanoTime 

Java5+

摩尔定律是一U众所周知的现象,卌机中的晶体数量和它的处理速度随时间呈指数规律增长。作Z童半g公司(Fairchild Semiconductor)的研发领ghQ戈?#8226;摩尔?965q提Zq一伟大发现。迄今ؓ(f)止,它仍有效?br /> 与Java首次出现的时候相比,当前计算机的速度要快得多Q对于很多应用程序而言以毫U计时已不再能够满要求。你可能使用qjava.lang.Systemc,利用currentTimeMillisҎ(gu)来获得一个方法调用或一D代码的定时信息。此Ҏ(gu)可以用来度量执行某操作所p的时间。但是,在运速度更快的计机上操作花费的旉可能q小?毫秒Q于是可以在一个for循环中执行此操作上百ơ或上千ơ,然后除以循环ơ数来计此操作的单位时间。考虑下面的示例:(x)

long startTime = System.currentTimeMillis();
for (int i=0; i<1000; i++) {
performOperation(); // something we want to measure
}
long endTime = System.currentTimeMillis();
long totalTimeInMillis = endTime - startTime;
// because the count was 1000, it's easy to get the unit time
long unitTimeInMicros = totalTimeInMillis;

q种一U很单的q算Q因Z用了for循环1000ơ。但是如果要度量亚微U该如何实现呢?

for(int i=0; i<1000000; i++) { performOperation(); }
如果从hcȝ角度来看Q可怜的for循环不得不不厌其烦(ch)地百万次的频J@环!此外Q只有在重复执行操作没有副作用的情况下用for循环来计时间才是有用的。如果操作是调用java.util.Collections.sortҎ(gu)Q那么将很难计算出排序过E花费的旉。在Java 5中,SystemcL一个新的nanoTimeҎ(gu)Q它能返回一个纳U精度的计数器。尽不能将它用于度量绝Ҏ(gu)_(d)但是它能够很好地度量旉差别?/p>

List myList = initializeList();  // initialize the List somehow
long startTime = System.nanoTime();
Collections.sort(myList);         // measuring the sort time
long endTime = System.nanoTime();
long differenceInNanoseconds = endTime - startTime;

遗憾的是Q运行上面的代码时无法保证实际上获得的是U秒U的度量。但是用更快的机器和良好的JRE实现Q对于测试目的而言它是一U有用的度量Ҏ(gu)。可以在JDK 5文档中找到更多有xҎ(gu)的信息。鉴于操作系l特性、机器处理速度和系l负载的不同Q得到的由nanoTimeҎ(gu)q回的值可能会(x)有很大的变化。随着旉的推UL问题应该?x)有所改善Q摩?dng)定律基本上能保证这一炏V?/p>

参考资料:(x)

惌了解摩尔的原始论文,请参看Gordon E. Moore, Cramming More Components onto Integrated Circuits, Electronics, Vol. 38, No. 8 (April 19, 1965)。此外,q可以在|上获得该论文,参看本书的网站http:// wickedcooljava.com以获得URL?/p>

]]>
1.6 要决断:(x)使用Java断言http://www.tkk7.com/yydy1983/articles/240957.html♂游泳的?/dc:creator>♂游泳的?/author>Mon, 17 Nov 2008 06:29:00 GMThttp://www.tkk7.com/yydy1983/articles/240957.htmlhttp://www.tkk7.com/yydy1983/comments/240957.htmlhttp://www.tkk7.com/yydy1983/articles/240957.html#Feedback0http://www.tkk7.com/yydy1983/comments/commentRss/240957.htmlhttp://www.tkk7.com/yydy1983/services/trackbacks/240957.html1.6  要决断:(x)使用Java断言 

Java5+

“~程人员L正确的—?是编译器和解释器造成的错误?#8221;我确信你认同q种说法。作为编Eh员,l常要对变量的值做出假讑ƈ且基于此~写代码。尽非怸愿意承认可能在设计或实现上有错误Q但有时变量和参数却没有获得期望的倹{?/p>

当设计和~写代码Ӟ只有在最初的假设仍然成立的情况下代码才能正确q行。如果没有Q何有兌些假讄声明Q那么阅M码的M?甚至你自?都不清楚它们的含义是什么。从而导致今后的改动可能?x)违反这些假讑ƈ引入难以查找的错误。通常Q在注释中说明假设能使以后修改代码的人避免出错?/p>

使用注释来说明假设是一个好的开始。但是当出现q反假设的情冉|Q程序有时会(x)l箋q行像未出CQ何问题一栗一些情况下Q开发h员能够马上看到结果,q且可以U正出现的问题。但在另一些情况下Q存在一个潜伏的错误Ӟ可能?x)对应用E序的其他部分造成负面影响Q对于分布式pȝ而言Q则可能?x)对完全不同的另一个应用程序造成负面影响Q跟t这L(fng)问题非常困难?/p>

Java 1.4在语a中添加了断言Ҏ(gu)来化测试和调试Q加强文档编制ƈ提高ZJava的可l护性。可以用一个布?yu)(dng)表辑ּ来创Z个断aQ以便测试有关系l的当前状态所假定的某些情c(din)如果断ap|Q运行库?x)抛Z个AssertionError。下面给Z个很单的断言Q?/p>

String name = "Brian";
assert name != null;

q里Q可以确定在lname分配了?#8220;Brian”后它的值将不会(x)为空。如果它的gؓ(f)I,则出C某种严重的错误!此断a是当时在E序中对变量的值所做的假定的声明。ؓ(f)如此单的例子做这U声明看似可W和多余。但是,当多个方法会(x)影响一个对象的状态时Q这U方法是有效的。在下面的示例中Q示例了q样一个断aQ即在向新员工分配Q何Q务之前必dl指z了一名管理h员?/p>

Employee worker =
new Employee("John", "Smith", 100000, "Developer");
assignOffice(worker);
setUpVoiceMail(worker);
moreAdministrivia(worker);
assert worker.getSupervisor() != null : "Supervisor cannot be null";
assignTasks(worker);

通常Q在Ҏ(gu)个对象执行关键操作时?x)需要对它创建断a。这有助于增Z码的健壮性,比如如果在程序中出现了某U错误,可以更方便地调试E序。这样做要比E序在某处执行失败造成不良后果来发现错误要好得多。当知道E序p|是由于它q反了假设而引L(fng)时候,跟踪p|的原因要单得多。在q个代码样例中,使用了assert选项来返回更有用的信息。没有此选项Ӟ除了行号之外无法得到有xa的标识信息?

在某些版本的~译器上Q当~译源代码时需要用一个命令选项来设|编译器的源兼容性模?取决于编译器的版本,?.4?.5)?/p>

javac -source 1.5 MyClass.java

现在强制断言p|q观察会(x)出现什么情况:(x)

public class AssertBad {
public static void main(String[] args) {
int total = 20;
int itemCount = 0;
assert itemCount > 0;
int average = total / itemCount;
}
}


默认情况下,q行时环境不支持断言Q必M用ea(允许断言)命o(h)选项来启动JRE。上面的代码?x)引起以下的l果Q?/p>

C:\projects\wcj1> java -ea AssertBad
Exception in thread "main" java.lang.AssertionError
at AssertBad.main(AssertBad.java:12)


要记住断a是用来对那些不应该出现的情况q行实际?#8220;健全性检?#8221;Q因此不应该使用它们来替代常规的错误(g)查?/p>

警告Q?/strong>
不要让断a语句更改代码中的状?倹{否则当最l关闭断aӞ代码的行为方式将不同于启用断a时代码的行ؓ(f)。例如,不要创徏如下的断aQ?/p>

assert (++i > 10); // BAD: i changes only with assertions enabled!

通常Q在整个开发阶D都?x)启用断a。一旦完全测试了pȝq将它移送到产品环境Ӟ则希望禁用断aQ因样做?x)略微改善性能。但是不要改动代码来完成此操作,q且也不要删除断a。不怎样Qؓ(f)了编制文档的目的Q断a也应保留在代码中。这P当以后更改代码时Q会(x)提醒E序员要保持所有假N是有效的Qƈ且这也是可测试的?br />



]]>
1.5 使用多个参数Q编写VarargҎ(gu)http://www.tkk7.com/yydy1983/articles/240701.html♂游泳的?/dc:creator>♂游泳的?/author>Sat, 15 Nov 2008 09:42:00 GMThttp://www.tkk7.com/yydy1983/articles/240701.htmlhttp://www.tkk7.com/yydy1983/comments/240701.htmlhttp://www.tkk7.com/yydy1983/articles/240701.html#Feedback0http://www.tkk7.com/yydy1983/comments/commentRss/240701.htmlhttp://www.tkk7.com/yydy1983/services/trackbacks/240701.html1.5  使用多个参数Q编写VarargҎ(gu)

Java5+

Java~程人员常常需要ؓ(f)Ҏ(gu)定义一个包含多个值的参数。这时可以采用List或数l的形式Q如下例所C?br />

public int add(int[] list) {
int sum = 0;
for (int i=0; i < list.length; i++) {
sum += list[i];
}
return sum;
}


也可以将它实Cؓ(f)几个重蝲的方法,每个Ҏ(gu)接受不同数量的int参数。这样做有时可以令方法更Ҏ(gu)使用Q因用代码不需要首先创Z个数l?/p>

public int add(int a, int b) {
return a + b;
}

public int add(int a, int b, int c) {
return a + b + c;
}

public int add(int a, int b, int c, int d) {
return a + b + c + d;
}


如果只有量|q对于调用代码更为方便,因ؓ(f)现在可以使用add(12,14,16)来代替add(new int[] {12,14,16})。但是,~写cMq样的方法存在问题,需要ؓ(f)每种可能的参数组合编写不同版本的Ҏ(gu)。如果希望在Ҏ(gu)的用方式上h最大的灉|性则与其创徏一个庞大的h上千个方法的c,不如寚w载的Ҏ(gu)接受的参数数量进行很的限制?/p>

在Java 5中,可以~写一个方法以使它允许可变数量的参数ƈ让编译器完成列表包装到一个数l中的操作。虽然内部仍是处理数l,但此时的~译器已隐藏了细节。以下的代码使用可变参数(vararg)重写了addҎ(gu)?

public int add(int... list) {
int sum = 0;
for (int item : list) {
sum += item;
}
return sum;
}

注意Q那些奇怪的圆点正是可变参数的实际语法!q且Q由于这U改动要用到Java 5Q我们也可以机使用Java 5增强的for循环语法。一旦按照这U方式编写了Ҏ(gu)Q可以用实际数量的参数来调用它Q此外,q可以传递一个作为参数的数组(但不允许是List或Collection对象)Q?

add(1,3,5,7,9,11,13,15,17,19,21,23,25);
add(new int[] {12,14,16});
需要注意的是当定义一个参数列表时该语法只能用一ơ,q且它必L最后一V以下的代码不能正常q行Q因为可变参C是最后一:(x)

public void badMethod(int... data, String comment) { } // wrong!
必须此代码改写成以下Ş式:(x)

public void goodMethod(String comment, int... data) { }
在一些情况下Q在Ҏ(gu)定义中用可变参数可以Ҏ(gu)更简ѝ这在参数列表包含字?编?值的情况下尤其如此,如上面的CZ中给出的int倹{?/p>

]]>
1.4 常用的泛型:(x)使用泛型参数来编写方?/title><link>http://www.tkk7.com/yydy1983/articles/239780.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Tue, 11 Nov 2008 01:06:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/239780.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/239780.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/239780.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/239780.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/239780.html</trackback:ping><description><![CDATA[<p><strong>1.4  常用的泛型:(x)使用泛型参数来编写方?/strong> </p> <p><font face="楷体_GB2312">Java5+</font></p> <p>前面的小节介l了泛型可以化Java代码q代码能够防范ClassCastException错误。除了作为JDK的一部分来用泛型之外,q可以编写你自己的泛型。当对类型相同的对象q行操作时泛型是很有用的Q但是对象的具体cd直到对类实例化时才能知道。这U方式非帔R合于包含关联项目的集合或涉?qing)查扄cR?/p> <p>下面~写一个用泛型参数的Ҏ(gu)。回想一下前面是怎样使用ArrayListcȝ—?只在构造ArrayList时才指定它用哪些对象类型。注意,在定义类时ƈ不知道其cdQƈ且不能将java.lang.Object作ؓ(f)cd使用Q因为最后将遇到cM以前的类型强制{换问题。当定义泛型Ӟ必须使用一U特D的语言来代表类型。当声明cd时要完成此操作。在下面的示例中Q?lt;T>表示一U类用的cdQ?/p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre> public class RandomSelection<T> { }</pre> </td> </tr> </tbody> </table> </p> <p>q里Q类型指C符的尖括号看v来类似HTML语法Q但实际上和HTML没有关系Q它们也不表C小于或大于Q尖括号在一个泛型的cd与一个类型相l合的情况下使用Q正如前面的ArrayList<Integer>那样。尽直到调用构造函数时才知道真实的cdQ但我们可以在方法定义中使用替换cd。假定定义了一个叫做RandomSelection的类Q该cM用另一个类的某个类型,暂时该cdUCؓ(f)T。但是,此类的名字仍是RandomSelection。另外,每次可以对多个类型执行这U操作,正如java.util.Map的定义所C的那样。在q种情况下,在类名之后用一个由逗号分隔的标识符列表卛_?</p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public class MyGeneric<T,U,V> { }<br /> </pre> </td> </tr> </tbody> </table> </p> <p>上面定义的MyGenericcL?qing)到三个cdQ它们分别称为T、U和V。下面编写一个方法来扩展RandomSelectionc,该方法将一个项目添加到一个由内部理的泛?cd为T)的ArrayList中:(x)</p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public class RandomSelection<T> {<br /> private ArrayList<T> list; <p>public RandomSelection() {<br /> list = new ArrayList<T>();<br /> }</p> <p>public void add(T element) {<br /> list.add(element);<br /> }<br /> }<br /> </p> </pre> </td> </tr> </tbody> </table> </p> <p>注意Q实际上q不是处理一个叫作T的类。T代表当某人创建RandomSelection的一个实例时使用的Q意类。Java规范允许使用L标识W,但是一般是使用单个大写字母来和普通的cdq行区别。既然已l定义addҎ(gu)接受一个类型T参数Q则只能使用在构造RandomSelection实例旉用的相同的类型来调用此方法。以下的代码是非法的q会(x)产生一个编译错误:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>RandomSelection<String> rs = new RandomSelection<String>();<br /> rs.add(new Date()); // illegal for a RandomSelection<String></pre> </td> </tr> </tbody> </table> <br /> 如果希望一个方法返回一个泛型类型,可以方法签名的q回cd设ؓ(f)TQ正如下面的定义所C:(x)<br /> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>import java.util.Random;<br /> public class RandomSelection<T> {<br /> private java.util.Random random = new Random();<br /> // ..... earlier methods omitted <p>public T getRandomElement() {<br /> int index = random.nextInt(list.size());<br /> return list.get(index);<br /> }<br /> }</p> </pre> </td> </tr> </tbody> </table> <br /> getRandomElementҎ(gu)q回一个类型TQ即与在cd明中定义的类型相同。通过构造一个类型实例,现在可以使用刚才定义的RandomSelectionc:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>RandomSelection<Integer> selector = new RandomSelection<Integer>();<br /> selector.add(2);<br /> selector.add(3);<br /> selector.add(5);<br /> selector.add(7);<br /> selector.add(11);<br /> Integer choice = selector.getRandomElement();<br /> System.out.println(choice);</pre> </td> </tr> </tbody> </table> <br /> l一个整型变量choice赋值是安全的,因ؓ(f)selector的getRandomElementҎ(gu)q回的L一个Integer。情늡实如此,因ؓ(f)是用Integer作ؓ(f)泛型cd来构造的selector实例。Add和getRandomElementҎ(gu)的定义具有和构造函数的定义相同的类型,q且~译器将?x)强制执行此U束。尝试在构造函C以一个不同的cd来用RandomSelectionc,q次使用前面定义的Fruit enumc:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>RandomSelection<Fruit> fruitSelector = new RandomSelection<Fruit>();<br /> fruitSelector.add(Fruit.APPLE);<br /> fruitSelector.add(Fruit.ORANGE);<br /> fruitSelector.add(Fruit.GRAPEFRUIT);<br /> fruitSelector.add(Fruit.BANANA);<br /> fruitSelector.add(Fruit.DURIAN);<br /> Fruit fruitChoice = fruitSelector.getRandomElement();<br /> System.out.println(fruitChoice);</pre> </td> </tr> </tbody> </table> <br /> 可以看出Q能够直接用来自getRandomElementҎ(gu)的Fruitq回|正如前面对待Integer那样。如果你惌一个类与某U类?直到构造该cL才知道具体的cd)的对象协同操作以?qing)希望编译器严格执行cd限制Q那么你可以定义自己的泛型。这样做的主要优点体现在它的安全和便利性上。若想了解有x型的更多信息Q请查阅|址http:// java.sun.com/j2se/1.5.0/docs/guide/language/generics.html上的Generics Tutorial(泛型指南) 和Java 5文档?</p> <img src ="http://www.tkk7.com/yydy1983/aggbug/239780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-11-11 09:06 <a href="http://www.tkk7.com/yydy1983/articles/239780.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1.3 执行安全存放Q用类型安全映?/title><link>http://www.tkk7.com/yydy1983/articles/238273.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Mon, 03 Nov 2008 01:10:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/238273.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/238273.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/238273.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/238273.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/238273.html</trackback:ping><description><![CDATA[<p><strong>1.3  执行安全存放Q用类型安全映?/strong></p> <p><font face="楷体_GB2312">Java5+</font></p> <p>正如前面讨论for循环时看到的那样Q用泛型有助于化代码ƈ降低出错概率。for循环?x)假定ArrayList仅包含I(xin)nteger对象Q因为ArrayList严格地被定义为由Integer对象l成。因而当从列表检索项目时可以避免从Object到Integer的强制类型{换?/p> <p>Java 5Ҏ(gu)心API做出了很多利用泛型的更改。查看相x档你?x)发现已重新定义了很多类以允怋用泛型。如果愿意的话,仍可以按照以前的方式构造和使用q些c,例如使用new ArrayList()。这样做的原因是Z兼容性,以便仍可以在旧版本的~译器下q行代码。当?dng)q样?x)失L型提供的cd(g)查带来的便利性和安全性?/p> <p>一个得到很好修订的cLjava.util.Map (和HashMap)。我们知道,映射操作像查表一P每个值都存储在一个唯一的键标下。在早期的Java版本中,当在映射表中攄表项Ӟ它们是作为Object存攄。当从映表中检索表Ҏ(gu)Q它被作为标准的Object引用来对待,卌强制转换成正的子类以便能够识别为它的实际类型。这与List中存在的危险相同。要么对象不正确Q要么出现ClassCastException异常Q这L(fng)情况太常见了?/p> <p>假定有一个用于维护员工数据的EmployeecR下面给Z些用HashMap的典型代码:(x) </p> <p> <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>Employee brian = new Employee();<br /> brian.setName("Brian", "Eubanks");<br /> brian.setSalary(100000.00);<br /> brian.setTitle("Boss"); <p>HashMap employees = new HashMap();<br /> employees.put("Brian", brian);</p> <p>Employee newHire = (Employee) employees.get("Brian");<br /> newHire.setHireDate(new Date());<br /> </p> </pre> </td> </tr> </tbody> </table> </p> <p>在检索项目时Q最大的危险位于强制cd转换的过E中。用Java 5Q不用强制类型{换也可完成此操作Q只要用正的cd来实例化Map。可以对键和值的cddU束。在下面的示例中Q只允许String键和Employee|(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>Employee brian = new Employee();<br /> brian.setName("Brian", "Eubanks");<br /> brian.setSalary(100000.00);<br /> brian.setTitle("Boss"); <p>HashMap<String,Employee> employees = new HashMap<String,Employee>();<br /> employees.put("Brian", brian);</p> <p>// no cast is necessary here<br /> Employee newHire = employees.get("Brian");<br /> newHire.setHireDate(new Date());</p> </pre> </td> </tr> </tbody> </table> <br /> 通过使用cd安全映射Q当从映表中检索表Ҏ(gu)可以避免ClassCastException错误。这样做使代码更加稳定ƈ且降低对映射内容的敏感性。但如果代码必须q行在早期版本的Java上,那么处于不利的情况q且需要暂时l执行强制类型{换。但可以采用下一节中的方法,创徏自己的泛型类?/p> <img src ="http://www.tkk7.com/yydy1983/aggbug/238273.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-11-03 09:10 <a href="http://www.tkk7.com/yydy1983/articles/238273.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>1.2 计数Q用枚?/title><link>http://www.tkk7.com/yydy1983/articles/221618.html</link><dc:creator>♂游泳的?/dc:creator><author>♂游泳的?/author><pubDate>Wed, 13 Aug 2008 02:06:00 GMT</pubDate><guid>http://www.tkk7.com/yydy1983/articles/221618.html</guid><wfw:comment>http://www.tkk7.com/yydy1983/comments/221618.html</wfw:comment><comments>http://www.tkk7.com/yydy1983/articles/221618.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/yydy1983/comments/commentRss/221618.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/yydy1983/services/trackbacks/221618.html</trackback:ping><description><![CDATA[<p><strong>1.2  计数Q用枚?/strong> </p> <p><font face="楷体_GB2312">Java5+</font></p> <p>大多数应用程序需要记录一个值的有限集—?卛_用程序中表示一l选择或状态的帔R。一U常见的Java~程惯例是用static int变量来表C些倹{然后让E序通过比较q些值和其他变量的值来做出军_。尽核心Java API本n也采用这U惯例,但它很可能导致严重的问题Q下面是一个有x果信息的CZ。该CZl出了用int变量来表C枚举数据时?x)出现的一些问题? <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public class FruitConstants {<br /> // this is not such a good practice<br /> public static final int APPLE = 1;<br /> public static final int ORANGE = 2;<br /> public static final int GRAPEFRUIT = 3;<br /> public static final int BANANA = 4;<br /> public static final int DURIAN = 5;<br /> public static final int CITRUS = 6;<br /> public static final int SWEET = 7;<br /> public static final int SMELLY = 8;<br /> public static final int UNKNOWN = 9; <p>public static int getCategory(int fruit) {<br /> switch(fruit) {<br /> case APPLE: case BANANA:<br /> return SWEET;<br /> case ORANGE: case GRAPEFRUIT:<br /> return CITRUS;<br /> case DURIAN:<br /> return SMELLY;<br /> }<br /> return UNKNOWN;<br /> }<br /> }</p> </pre> </td> </tr> </tbody> </table> 其中Q来自东南亚的水果榴?Durian)具备“Sweet”?#8220;Smelly”Q但是这里的水果只能q回一个特点,也就是说Q所有的值只能是对应单一的D不是对应多个倹{另外一个主要的问题是Q何int值都可以传递给getCategoryҎ(gu)Q无论它是否代表一个有效的水果。这可能Dl微的错误,因ؓ(f)~译器不兛_是调用getCategory(SWEET)q是调用getCategory(42)。ƈ且如果整型常量的值发生了变化QgetCategory(3)昄的将不再是正的信息Q?br /> 另一个问题是使用水果和类别的int值ƈ无区别—?它们都只是普通的int倹{通过单地类别常量置于一个不同的cM可以部分地解x果和cd分离的问题,但是它们仍只是intD不是类型安?typesafe)的,也就是没能将getCategory的参数限制到一个固定的值集合?br /> 在Java 5中,有一个优雅的解决Ҏ(gu)Q可以像在C语言中那样创建枚丄型。这是一个新Ҏ(gu),它创Z个类Q该cd含一个所有它允许的实例清单。除了enum内定义的实例外,不允许其他的实例。下面看一些enum的示例:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>enum Fruit {APPLE, ORANGE, GRAPEFRUIT, BANANA, DURIAN}<br /> enum FruitCategory {SWEET, CITRUS, SMELLY, UNKNOWN}<br /> enum Dessert {PIE, CAKE, ICECREAM, BROWNIE}</pre> </td> </tr> </tbody> </table> <br /> 以上每个例子均定义了一l不同的枚D元素(选择)。这样做的好处是不会(x)Fruitg其他cd的相混合或相h。对待每个enum好像它是一个不同的cM栗不能将FruitCategory作ؓ(f)一个参C递给一个期望Dessert的值方法,也不能传递一个int倹{下面扩展Fruit enum以包含最初的FruitConstantscd有的功能Q? <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public enum Fruit {<br /> APPLE, ORANGE, GRAPEFRUIT, BANANA, DURIAN; <p>public static FruitCategory getCategory(Fruit fruit) {<br /> switch(fruit) {<br /> case APPLE: case BANANA:<br /> return FruitCategory.SWEET;<br /> case ORANGE: case GRAPEFRUIT:<br /> return FruitCategory.CITRUS;<br /> case DURIAN:<br /> return FruitCategory.SMELLY;<br /> }<br /> return FruitCategory.UNKNOWN;<br /> }<br /> }</p> </pre> </td> </tr> </tbody> </table> <br /> 可以看出一个enmu也可以像一个类那样定义Ҏ(gu)。现在的getCategoryҎ(gu)采用Fruit作ؓ(f)参数Qƈ且只允许使用enum中定义的倹{接下来q个代码D将引v~译错误Q而不?x)出现调用最初的未受保护的getCategoryҎ(gu)时出现的q行时异常:(x) <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>Fruit.getCategory(Dessert.PIE); // compile error<br /> Fruit.getCategory(10); // compile error</pre> </td> </tr> </tbody> </table> <br /> 如果每种水果理它自qcd会(x)更好Q因此ؓ(f)了完善Fruitc,删除getCategory的水果参数ƈ使该Ҏ(gu)为每个enum状态返回不同的倹{通过创徏一个适用于所有值的抽象的getCategoryҎ(gu)q对每个enum以不同的方式重写它,可以完成此操作。它非常cM于ؓ(f)每个枚D值编写一个不同的子类Qƈ让每个这L(fng)子类重写抽象的方法? <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public enum Fruit {<br /> APPLE<br /> { FruitCategory getCategory() {return FruitCategory.SWEET;} },<br /> ORANGE<br /> { FruitCategory getCategory() {return FruitCategory.CITRUS;} },<br /> GRAPEFRUIT<br /> { FruitCategory getCategory() {return FruitCategory.CITRUS;} },<br /> BANANA<br /> { FruitCategory getCategory() {return FruitCategory.SWEET;} },<br /> DURIAN<br /> { FruitCategory getCategory() {return FruitCategory.SMELLY;} }; <p>abstract FruitCategory getCategory();<br /> }</p> </pre> </td> </tr> </tbody> </table> <br /> 一旦创Z个类DL(fng)enumQ就可以像对待其他对象那h对待APPLE?使用静态的Fruit.APPLE引用)Qƈ且可以调用它的getCategoryҎ(gu)来得到它的相应类别。现在可以ؓ(f)上面的类d一个mainҎ(gu)来说明如何用新的Fruit enumQ? <table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"> <tbody> <tr> <td class="code" bgcolor="#e6e6e6"> <pre>public static void main(String[] args) {<br /> Fruit a = Fruit.APPLE;<br /> // toString() returns "APPLE"<br /> System.out.println ("The toString() for a: " + a);<br /> // getCategory() returns "SWEET"<br /> System.out.println ("a.getCategory() is: " + a.getCategory());<br /> for (Fruit f : Fruit.values()) {<br /> System.out.println ("Fruit is: " + f);<br /> }<br /> }</pre> </td> </tr> </tbody> </table> <br /> 正如代码中所C的那样Q可以用valuesҎ(gu)来P代enum内的所有倹{enum的toStringҎ(gu)会(x)q回一个StringQ它h和值相同的名字。用enum而不是int来表C状态,可以使代码具有更好的可读性和更强的防错性。它明确地定义了一个特D的枚D状态的所有值ƈ可以防止有h使用不正的倹{?/p> <img src ="http://www.tkk7.com/yydy1983/aggbug/221618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/yydy1983/" target="_blank">♂游泳的?/a> 2008-08-13 10:06 <a href="http://www.tkk7.com/yydy1983/articles/221618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Wicked Cool Java中文?1.1 在Java中没有forQ用增强的for循环http://www.tkk7.com/yydy1983/articles/221616.html♂游泳的?/dc:creator>♂游泳的?/author>Wed, 13 Aug 2008 02:05:00 GMThttp://www.tkk7.com/yydy1983/articles/221616.htmlhttp://www.tkk7.com/yydy1983/comments/221616.htmlhttp://www.tkk7.com/yydy1983/articles/221616.html#Feedback0http://www.tkk7.com/yydy1983/comments/commentRss/221616.htmlhttp://www.tkk7.com/yydy1983/services/trackbacks/221616.html1.1  在Java中没有forQ用增强的for循环 

Java5+

在一些编E语a中,通过列表或数l可以非常方便地q行遍历Q通过一个@环即可逐个遍历ƈ该赋g个局部变量从而实现自动@环。我曄告诉q一个同事我认ؓ(f)Java中的“for”循环功能是不完全的,因ؓ(f)它没?#8220;for-each”。我的朋友也是一个有l验的Java开发h员,他的回答?#8220;你疯了吗Q,在Java中当然有forQ?#8221;在此之后很长一D|间里他ؓ(f)此而不断地嘲笑我,q定期地提醒我在Java中存在for(Z防止我遗忘此? 。但是我有一个好消息要告诉他和所有Java开发h员:(x)目前在Java中有了真正的forQ?/p>

考虑q样一U情况,你希望对一个整型对象集?如java.util.ArrayList)中的所有数值求和。你很可能编写过cM于下面这L(fng)代码Q?/p>
ArrayList theList = new ArrayList();
theList.add(new Integer(2));
theList.add(new Integer(3));
theList.add(new Integer(5));
theList.add(new Integer(7));
int sum = 0;
// The old way to iterate
for (Iterator iter = theList.iterator(); iter.hasNext(); ) {
Integer x = (Integer) iter.next();
sum = sum + x.intValue();
}
System.out.println("The sum is " + sum);

q段代码多麻?ch)啊Q难道编译器不应该知道你正在q行q代?毕竟q是一个for循环Q不是吗Q而在Java 5中,增强的for循环现已支持集合对象。因此不再需要用P代器。在下面的修订的代码中,一个for循环通过列表q行q代q显C出每个|(x)

ArrayList<Integer> theList = new ArrayList<Integer>();
theList.add(2);
theList.add(3);
theList.add(5);
theList.add(7);
int sum = 0;
// new Java 5 iteration syntax
for (Integer item : theList) {
sum = sum + item;
}
System.out.println("The sum is " + sum);

for循环定义了一个叫做item的局部变量,在每ơP代过E中Q它?yu)得到列表中的下一个倹{除了完的for循环语法外,此代码在以下两个斚w也不同于q去的Java代码?/p>

使用了泛?/strong>

上面带有括L(fng)语法是Java 5新增加的泛型Ҏ(gu)。泛型允ؓ(f)一些具体类型的对象定义c,但是直到创徏该类的一个实例时才能知道具体的类型。编译器会(x)执行cd(g)查。在q个CZ中,ArrayList是一个特D的c,对于addҎ(gu)它只接受整数(q只从它的Iterator的nextҎ(gu)中返回整?。这意味着当从列表中检索对象时不需要强制类型{换,可以立即它们作为Integer实例来对待。不使用泛型Ӟ仍可以用新的for循环语法Q但需要将Object强制转换成Integer。在1.4节中我们更详细Cl泛型?

整型对象到整型数值的自动转换

在Java 5中,可以Integer对象作ؓ(f)int来对待。编译器自动执行从int到Integer对象的{?反之亦然)Q此q程UCؓ(f)自动装箱(autoboxing)。当循环中得C个Integer对象Ӟ可以它与一个int值相加而不需要执行显式的转换?br /> 新的for语言也适用于数l:(x)

int[] theList = new int[] {2,3,5,7};
int sum = 0;
for (int x : theList) {
sum = sum + x;
}
System.out.println("The sum is " + sum);
q种新的语法的确使代码变得更加易d紧凑。但q不能完全放弃P代器Q至暂时是q样Q因有很多开发h员没有将他们的JDK升到版??br />



]]>
վ֩ģ壺 һ߹ۿƷ| AVþWWW| 鶹ƷƵ| ޾Ʒҹvaþ| רһvavר | ˳ɵӰվþ| ؼƬѸƵ| þAV뾫Ʒɫҹ| վ߹ۿ| 99ƷƵ| ޾Ʒ΢ľƷ| ޸Ļ| þ99޸ۿҳ| ƷƵѹۿ| ٸƵѹۿ| þԭavapp | Ƶ߹ۿ| ۺľƷ| ޾Ʒվ߹ۿ޹| 19žžڵվ| һþƵ| ޻ɫƵ| ޾Ʒtvþþþþþþ| ձѵӰһ| ³³ƵѲ| ۺ޹һҳ| ˮƵwwwƵ| þþƷަvDz| ޾ƷAAƬ߹ۿ | Ʒպһ| 7723ձ| þþþƷƵѹۿ | Ļ߹ۿպ| Ʒ_˳߸| ûվɫƵֱ| Ƶ߲| վ18ѹۿ| 뾫Ʒþþþ | Ƶѹۿ| 2022ĻƵ| Ůվ91ɫ|