??xml version="1.0" encoding="utf-8" standalone="yes"?>99se视频在线观看,国产二区在线播放,欧美激情wwwhttp://www.aygfsteel.com/Duffblog/category/9507.html前进一步,看看Q需要前q更大一步才可以?/description>zh-cnWed, 28 Feb 2007 03:56:57 GMTWed, 28 Feb 2007 03:56:57 GMT60术表达式的计算Q{Q?/title><link>http://www.aygfsteel.com/Duffblog/articles/87811.html</link><dc:creator>q球?/dc:creator><author>q球?/author><pubDate>Thu, 14 Dec 2006 12:46:00 GMT</pubDate><guid>http://www.aygfsteel.com/Duffblog/articles/87811.html</guid><wfw:comment>http://www.aygfsteel.com/Duffblog/comments/87811.html</wfw:comment><comments>http://www.aygfsteel.com/Duffblog/articles/87811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Duffblog/comments/commentRss/87811.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Duffblog/services/trackbacks/87811.html</trackback:ping><description><![CDATA[ 在计机中进行算术表辑ּ的计是通过栈来实现的。这一节首先讨论算术表辑ּ的两U表C方法,即中~表示法和后缀表示法,接着讨论后缀表达式求值的法Q最后讨Z~表达式{换ؓ后缀表达式的法?br />1. 术表达式的两种表示<br />通常书写的算术表辑ּ是由操作?又叫q算对象或运量)和运符以及改变q算ơ序的圆括号q接而成的式子。操作数可以是常量、变量和函数Q同时还可以是表辑ּ。运符包括单目q算W和双目q算W两c,单目q算W只要求一个操作数Qƈ被放在该操作数的前面Q双目运符要求有两个操作数Qƈ被放在这两个操作数的中间。单目运符为取正?’和取负?’,双目q算W有加??减??乘?’和除?’等。ؓ了简便v见,在我们的讨论中只考虑双目q算W?br />如对于一个算术表辑ּ2+5*6Q乘法运符?’的两个操作数是它两边的5?Q对于加法运符?’的两个操作敎ͼ一个是它前面的2Q另一个是它后面的 5*6的结果即30。我们把双目q算W出现在两个操作C间的q种习惯表示叫做术表达式的中缀表示Q这U算术表辑ּ被称Z~术表达式或中缀表达式?br />中缀表达式的计算比较复杂Q它必须遵守以下三条规则Q?br />(1) 先计括号内Q后计算括号外;<br />(2) 在无括号或同层括号内Q先q行乘除q算Q后q行加减q算Q即乘除q算的优先高于加减q算的优先Q?br />(3) 同一优先U运,从左向右依次q行?br />从这三条规则可以看出Q在中缀表达式的计算q程中,既要考虑括号的作用,又要考虑q算W的优先U,q要考虑q算W出现的先后ơ序。因此,各运符实际的运次序往往同它们在表达式中出现的先后次序是不一致的Q是不可预测的。当然凭直观判别一个中~表达式中哪个q算W最先算Q哪个次之,……,哪个最后算q不困难Q但通过计算机处理就比较困难了,因ؓ计算机只能一个字W一个字W地扫描Q要惛_到哪一个运符先算Q就必须Ҏ个中~表达式扫描一遍,一个中~表达式中有多个q算W,原则上就得扫描多遍才能计算完毕Q这样就太浪Ҏ间了Q显然是不可取的?br />那么Q能否把中缀术表达式{换成另一UŞ式的术表达式,使计简单化? 回答是肯定的。L兰科学家卢卡谢维?Lukasiewicz)很早提Z术表达式的另一U表C,卛_~表示Q又U逆L兰式Q其定义是把q算W放在两个运对象的后面。采用后~表示的算术表辑ּ被称为后~术表达式或后缀表达式。在后缀表达式中Q不存在括号Q也不存在优先的差别,计算q程完全按照q算W出现的先后ơ序q行Q整个计过E仅需一遍扫描便可完成,昄比中~表达式的计算要简单得多。例如,对于后缀表达?2! 4!-!5!/Q其中?’字W表C成分之间的I格Q因减法q算W在前,除法q算W在后,所以应先做减法Q后做除法;减法的两个操作数是它前面?2?4Q其中第一个数12是被减数Q第二个?是减敎ͼ除法的两个操作数是它前面?2?的差(?)?Q其?是被除数Q?是除数?br />中缀术表达式{换成对应的后~术表达式的规则是:把每个运符都移到它的两个运对象的后面Q然后删除掉所有的括号卛_?br />例如Q对于下列各中缀表达式:<br />(1) 3/5+6<br />(2) 16-9*(4+3)<br />(3) 2*(x+y)/(1-x)<br />(4) (25+x)*(a*(a+b)+b)<br />对应的后~表达式分别ؓQ?br />(1) 3!5!/!6!+<br />(2) 16!9!4!3!+!*!-<br />(3) 2!x!y!+!*!1!x!-!/<br />(4) 25!x!+!a!a!b!+!*!b!+!*<br /><br />2. 后缀表达式求值的法<br />后缀表达式的求值比较简单,扫描一遍即可完成。它需要用一个栈Q假定用S表示Q其元素cd应ؓ操作数的cdQ假定ؓ点型floatQ用此栈存储后缀表达式中的操作数、计过E中的中间结果以及最后结果。假定一个后~术表达式以字符’@’作为结束符Qƈ且以一个字W串的方式提供。后~表达式求值算法的基本思\是:把包含后~术表达式的字符串定义ؓ一个输入字W串对象,每次从中d一个字W(I格作ؓ数据之间的分隔符Q不会被作ؓ字符dQ时Q若它是q算W,则表明它的两个操作数已经在栈S中,其中栈顶元素符的后一个操作数Q栈元素的下一个元素ؓq算W的前一个操作数Q把它们弹出后进行相应运即可,然后把运结果再压入栈S中;否则Q读入的字符必ؓ操作数的最高位数字Q应把它重新送回输入中Q然后把下一个数据作为QҎ输入Qƈ把它压入到栈S中。依ơ扫描每一个字W(对于点数只需扫描它的最高位q一ơ输入整个QҎQƈq行上述处理Q直到遇到结束符’@’ؓ止,表明后缀表达式计完毕,最l结果保存在栈中Qƈ且栈中仅存这一个|把它弹出q回卛_。具体算法描qCؓQ?br /><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: rgb(230,230,230) 0% 50%; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial"><div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="COLOR: rgb(0,0,255)">float</span><span style="COLOR: rgb(0,0,0)"> Compute(</span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)"> str)<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 计算由str字符串所表示的后~表达式的|<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 表达式要?@'字符l束?/span><span style="COLOR: rgb(0,128,0)"><br /><img id="_67_926_Open_Image" onclick="this.style.display='none'; document.getElementById('_67_926_Open_Text').style.display='none'; document.getElementById('_67_926_Closed_Image').style.display='inline'; document.getElementById('_67_926_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_67_926_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_67_926_Closed_Text').style.display='none'; document.getElementById('_67_926_Open_Image').style.display='inline'; document.getElementById('_67_926_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_67_926_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_67_926_Open_Text"><span style="COLOR: rgb(0,0,0)">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />Stack S; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 用S栈存储操作数和中间计结?/span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">InitStack(S); </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 初始化栈</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">istrstream ins(str); </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 把str定义入字W串对象ins</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,0)"> ch; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 用于输入字符</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">float</span><span style="COLOR: rgb(0,0,0)"> x; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 用于输入点?/span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">ins</span><span style="COLOR: rgb(0,0,0)">>></span><span style="COLOR: rgb(0,0,0)">ch; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 从ins对?即str字符?中顺序读入一个字W?/span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,0)">(ch</span><span style="COLOR: rgb(0,0,0)">!=</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">@</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">)<br /><img id="_254_726_Open_Image" onclick="this.style.display='none'; document.getElementById('_254_726_Open_Text').style.display='none'; document.getElementById('_254_726_Closed_Image').style.display='inline'; document.getElementById('_254_726_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_254_726_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_254_726_Closed_Text').style.display='none'; document.getElementById('_254_726_Open_Image').style.display='inline'; document.getElementById('_254_726_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="_254_726_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_254_726_Open_Text"><span style="COLOR: rgb(0,0,0)">{ </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 扫描每一个字Wƈq行相应处理</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">switch</span><span style="COLOR: rgb(0,0,0)">(ch)<br /><img id="_285_648_Open_Image" onclick="this.style.display='none'; document.getElementById('_285_648_Open_Text').style.display='none'; document.getElementById('_285_648_Closed_Image').style.display='inline'; document.getElementById('_285_648_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_285_648_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_285_648_Closed_Text').style.display='none'; document.getElementById('_285_648_Open_Image').style.display='inline'; document.getElementById('_285_648_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="_285_648_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_285_648_Open_Text"><span style="COLOR: rgb(0,0,0)">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">case</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">:<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />x</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">Pop(S)</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">Pop(S); <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">break</span><span style="COLOR: rgb(0,0,0)">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">case</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">-</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">:<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />x</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">Pop(S); </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> Pop(S)弹出减数</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">x</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">Pop(S)</span><span style="COLOR: rgb(0,0,0)">-</span><span style="COLOR: rgb(0,0,0)">x; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> Pop(S)弹出的是被减?/span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">break</span><span style="COLOR: rgb(0,0,0)">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">case</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">:<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />x</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">Pop(S)</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">Pop(S);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">break</span><span style="COLOR: rgb(0,0,0)">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">case</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">/</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">:<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />x</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">Pop(S); </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> Pop(S)弹出除数</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(x</span><span style="COLOR: rgb(0,0,0)">!=</span><span style="COLOR: rgb(0,0,0)">0.0</span><span style="COLOR: rgb(0,0,0)">)<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />x</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">Pop(S)</span><span style="COLOR: rgb(0,0,0)">/</span><span style="COLOR: rgb(0,0,0)">x; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> Pop(S)弹出的是被除?/span><span style="COLOR: rgb(0,128,0)"><br /><img id="_505_551_Open_Image" onclick="this.style.display='none'; document.getElementById('_505_551_Open_Text').style.display='none'; document.getElementById('_505_551_Closed_Image').style.display='inline'; document.getElementById('_505_551_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_505_551_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_505_551_Closed_Text').style.display='none'; document.getElementById('_505_551_Open_Image').style.display='inline'; document.getElementById('_505_551_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">else</span><span style="COLOR: rgb(0,0,0)"> </span><span id="_505_551_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_505_551_Open_Text"><span style="COLOR: rgb(0,0,0)">{ </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 除数?时终止运?/span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">cerr</span><span style="COLOR: rgb(0,0,0)"><<</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">Divide by 0!</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)"><</span><span style="COLOR: rgb(0,0,0)"> exit(</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: rgb(0,0,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">break</span><span style="COLOR: rgb(0,0,0)">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">default</span><span style="COLOR: rgb(0,0,0)">: </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> d的必Z个QҎ的最高位数字</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">ins.putback(ch); </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 把它重新回送到输入中</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">ins</span><span style="COLOR: rgb(0,0,0)">>></span><span style="COLOR: rgb(0,0,0)">x; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 从字W串输入中d一个QҎ</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">}</span></span><span style="COLOR: rgb(0,0,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />Push(S,x); </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 把读入的一个QҎ或进行相应运?br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 的结果压入到S栈中</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">ins</span><span style="COLOR: rgb(0,0,0)">>></span><span style="COLOR: rgb(0,0,0)">ch; </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 输入下一个字W,以便q行下一轮@环处?/span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">}</span></span><span style="COLOR: rgb(0,0,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(</span><span style="COLOR: rgb(0,0,0)">!</span><span style="COLOR: rgb(0,0,0)">StackEmpty(S)) <br /><img id="_748_865_Open_Image" onclick="this.style.display='none'; document.getElementById('_748_865_Open_Text').style.display='none'; document.getElementById('_748_865_Closed_Image').style.display='inline'; document.getElementById('_748_865_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_748_865_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_748_865_Closed_Text').style.display='none'; document.getElementById('_748_865_Open_Image').style.display='inline'; document.getElementById('_748_865_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span id="_748_865_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_748_865_Open_Text"><span style="COLOR: rgb(0,0,0)">{ </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 若栈中仅有一个元素,则它是后~表达式的|否则为出?/span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">x</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">Pop(S);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(StackEmpty(S)) <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> x; <br /><img id="_825_863_Open_Image" onclick="this.style.display='none'; document.getElementById('_825_863_Open_Text').style.display='none'; document.getElementById('_825_863_Closed_Image').style.display='inline'; document.getElementById('_825_863_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_825_863_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_825_863_Closed_Text').style.display='none'; document.getElementById('_825_863_Open_Image').style.display='inline'; document.getElementById('_825_863_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">else</span><span style="COLOR: rgb(0,0,0)"> </span><span id="_825_863_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_825_863_Open_Text"><span style="COLOR: rgb(0,0,0)">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />cerr</span><span style="COLOR: rgb(0,0,0)"><<</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">expression error!</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)"><</span><span style="COLOR: rgb(0,0,0)"> exit(</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: rgb(0,0,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: rgb(0,0,0)"><br /><img id="_872_924_Open_Image" onclick="this.style.display='none'; document.getElementById('_872_924_Open_Text').style.display='none'; document.getElementById('_872_924_Closed_Image').style.display='inline'; document.getElementById('_872_924_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_872_924_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_872_924_Closed_Text').style.display='none'; document.getElementById('_872_924_Open_Image').style.display='inline'; document.getElementById('_872_924_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,255)">else</span><span style="COLOR: rgb(0,0,0)"> </span><span id="_872_924_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">...</span><span id="_872_924_Open_Text"><span style="COLOR: rgb(0,0,0)">{ </span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)"> 若最后栈为空Q则l止q行</span><span style="COLOR: rgb(0,128,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="COLOR: rgb(0,0,0)">cerr</span><span style="COLOR: rgb(0,0,0)"><<</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">Stack is empty!</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)"><</span><span style="COLOR: rgb(0,0,0)"> exit(</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />}</span></span><span style="COLOR: rgb(0,0,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="COLOR: rgb(0,0,0)"><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span></div></div>此算法的q行旉主要花在while循环上,它从头到扫描后~表达式中的每一个数据(每个操作数或q算W均Z个数据)Q若后缀表达式由n个数据组成,则此法的时间复杂度为O(n)。此法在运行时所占用的时空间主要取决于栈S的大,昄Q它的最大深度不会超q表辑ּ中操作数的个敎ͼ因ؓ操作数的个数与运符Q假定把’@’也看作Z个特D运符Q即l束q算W)的个数相{,所以此法的空间复杂度也同样ؓO(n)?br />假定一个字W串a为:<br />char a[30]="12 3 20 4 / * 8 - 6 * +@";<br />对应的中~术表达式ؓ12+(3*(20/4)-8)*6@Q则使用如下语句调用上述函数得到的输出结果ؓ54?br />cout< 在进行这个后~术表达式求值的q程中,从第四个操作数入栈开始,每处理一个操作数或运符后,栈S中保存的操作数和中间l果的情况如?-4所C?br /><br /> <br /><a style="COLOR: rgb(127,127,255)" target="_blank"><img alt="" src="http://www.cstudyhome.com/wenzhang06/uploadpic/200391117511780556.jpg" onload="if(this.width>screen.width/2)this.style.width=screen.width/2;" border="0" /></a><br /> <br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1423390</p><img src ="http://www.aygfsteel.com/Duffblog/aggbug/87811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Duffblog/" target="_blank">q球?/a> 2006-12-14 20:46 <a href="http://www.aygfsteel.com/Duffblog/articles/87811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>术表达式(转)http://www.aygfsteel.com/Duffblog/articles/87810.htmlq球?/dc:creator>q球?/author>Thu, 14 Dec 2006 12:44:00 GMThttp://www.aygfsteel.com/Duffblog/articles/87810.htmlhttp://www.aygfsteel.com/Duffblog/comments/87810.htmlhttp://www.aygfsteel.com/Duffblog/articles/87810.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/87810.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/87810.html把运符攑֜参与q算的两个操作数中间的算术表辑ּUCؓ中缀表达式。例如:2+3*4 - 6/9
术表达式中包含了算术运符和算术量(帔R、变量、函?Q而运符之间又存在着优先U,不能单地q行从左到右q算Q编译程序在求值时Q不能简单从左到双,必须先算q算U别高的Q再运别低的,同一U运才从左到右。在计算Zq行中缀表达式求Dȝ。而后~表达式求D方便Q无考虑q算W的优先U及圆括P?
   
    二、算术表辑ּ的后~表示

把运符攑֜参与q算的两个操作数后面的算术表辑ּUCؓ后缀表达式?br />例如Q对于下列各中缀表达式:
(1)3/5+8
(2)18-9*(4+3)
对应的后~表达式ؓQ?br />(1)3 5 / 8 +
(2)18 9 4 3 + * -
转换规则:把每个运符都移到它的两个操作数的后?然后删除掉所有的括号卛_.

    ?表达式的计算Q?/p>

׃后缀表达式中没有括号Q不需判别优先U,计算严格从左向右q行Q故计算一个后~表达式要比计机一个中~表达式简单得多?

  中~表达式{换ؓ后缀表达式的法思想Q?br />  ·当读到数字直接送至输出队列?br />  ·当读到运符tӞ
     a.栈中所有优先高于或等于t的运符弹出Q送到输出队列中;
     b.tq栈
  ·d左括hL它压入栈中
  ·dxhQ将靠近栈顶的第一个左括号上面的运符全部依次弹出Q送至输出队列后,再丢弃左括号?/p>

    中缀表达式全部读完后Q若栈中仍有q算W,其送到输出队列?/p>


   q用后缀表达式进行计的具体做法Q?br />  ·建立一个栈S
  ·从左到右d~表达式,d数字将它{换ؓ数值压入栈S中,dq算W则从栈中依ơ弹Z个数分别到Y和XQ然后以"X q算W?Y"的Ş式计机出结果,再压加栈S?br />  ·如果后缀表达式未dQ就重复上面q程Q最后输出栈的数值则为结?/p>

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=619852



]]>
Java正则表达式详??-----入门知识?/title><link>http://www.aygfsteel.com/Duffblog/articles/87626.html</link><dc:creator>q球?/dc:creator><author>q球?/author><pubDate>Thu, 14 Dec 2006 01:45:00 GMT</pubDate><guid>http://www.aygfsteel.com/Duffblog/articles/87626.html</guid><wfw:comment>http://www.aygfsteel.com/Duffblog/comments/87626.html</wfw:comment><comments>http://www.aygfsteel.com/Duffblog/articles/87626.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Duffblog/comments/commentRss/87626.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Duffblog/services/trackbacks/87626.html</trackback:ping><description><![CDATA[ <table width="620" align="center"> <tbody> <tr> <td class="a14">如果你曾l用qPerl或Q何其他内建正则表辑ּ支持的语aQ你一定知道用正则表达式处理文本和匚w模式是多么简单。如果你不熟悉这个术语,那么“正则表辑ּ”(Regular ExpressionQ就是一个字W构成的Ԍ它定义了一个用来搜索匹配字W串的模式?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">许多语言Q包括Perl、PHP、Python、JavaScript和JScriptQ都支持用正则表辑ּ处理文本Q一些文本编辑器用正则表辑ּ实现高“搜?替换”功能。那么Java又怎样呢?本文写作Ӟ一个包含了用正则表辑ּq行文本处理的Java规范需求(Specification RequestQ已l得到认可,你可以期待在JDK的下一版本中看到它?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">然而,如果现在需要用正则表辑ּQ又该怎么办呢Q你可以从Apache.org下蝲源代码开攄Jakarta-ORO库。本文接下来的内容先要地介绍正则表达式的入门知识Q然后以Jakarta-ORO APIZ介绍如何使用正则表达式?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b> <font size="4">一、正则表辑ּ基础知识</font> </b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">我们先从单的开始。假设你要搜索一个包含字W“cat”的字符Ԍ搜烦用的正则表达式就是“cat”。如果搜索对大小写不敏感Q单词“catalog”、“Catherine”、“sophisticated”都可以匚w。也是_ </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/j43nu4ndo6z8.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>1.1 句点W号</b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">假设你在玩英文拼字游戏,惌扑և三个字母的单词,而且q些单词必须以“t”字母开_以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内宏V要构造出q个正则表达式,你可以用一个通配W——句点符号?”。这P完整的表辑ּ是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,q匹配“t#n”、“tpn”甚至“t n”,q有其他许多无意义的l合。这是因为句点符号匹配所有字W,包括I格、Tab字符甚至换行W: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/9i9f280hrzkz.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>1.2 ҎL?/b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">Z解决句点W号匚w范围q于q泛q一问题Q你可以在方括号Q“[]”)里面指定看来有意义的字符。此Ӟ只有Ҏ号里面指定的字符才参与匹配。也是_正则表达式“t[aeio]n”只匚w“tan”、“Ten”、“tin”和“ton”。但“Toon”不匚wQ因为在Ҏ号之内你只能匚w单个字符Q?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/t1e74w8itp99.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>1.3 “或”符?/b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">如果除了上面匚w的所有单词之外,你还惌匚w“toon”,那么Q你可以使用“|”操作符。“|”操作符的基本意义就是“或”运。要匚w“toon”,使用“t(a|e|i|o|oo)n”正则表辑ּ。这里不能用方扩号Q因为方括号只允许匹配单个字W;q里必须使用圆括号?)”。圆括号q可以用来分l,具体请参见后面介l?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/i1fus8ynpz96.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>1.4 表示匚wơ数的符?/b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">表一昄了表C匹配次数的W号Q这些符L来确定紧靠该W号左边的符号出现的ơ数Q?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/8k41sc2nzdy7.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">假设我们要在文本文g中搜索美国的C会安全L。这个号码的格式?99-99-9999。用来匹配它的正则表辑ּ如图一所C。在正则表达式中Q连字符Q?”)有着Ҏ的意义,它表CZ个范_比如??。因此,匚wC会安全L中的q字W号Ӟ它的前面要加上一个{义字W“\”?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/d0461e0196rw.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">图一Q匹配所?23-12-1234形式的社会安全号?/p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">假设q行搜烦的时候,你希望连字符号可以出玎ͼ也可以不出现——即Q?99-99-9999?99999999都属于正的格式。这Ӟ你可以在q字W号后面加上“?”数量限定符P如图二所C: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/4s8b1dwh8778.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">图二Q匹配所?23-12-1234?23121234形式的社会安全号?/p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">下面我们再来看另外一个例子。美国汽车牌照的一U格式是四个数字加上二个字母。它的正则表辑ּ前面是数字部分“[0-9]{4}”,再加上字母部分“[A-Z]{2}”。图三显CZ完整的正则表辑ּ?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/8uvnyokp8pix.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">图三Q匹配典型的国汽R牌照LQ如8836KV</p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">1.5 “否”符?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">“^”符L为“否”符受如果用在方括号内,“^”表CZ惌匚w的字W。例如,囑֛的正则表辑ּ匚w所有单词,但以“X”字母开头的单词除外?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/47z03c6v2q6z.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">囑֛Q匹配所有单词,但“X”开头的除外</p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">1.6 圆括号和I白W号 </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">假设要从格式为“June 26, 1951”的生日日期中提取出月䆾部分Q用来匹配该日期的正则表辑ּ可以如图五所C: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/2w4mut5a8vjn.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">图五Q匹配所有Moth DD,YYYY格式的日?/p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">新出现的“\s”符hI白W号Q匹配所有的I白字符Q包括Tab字符。如果字W串正确匚wQ接下来如何提取出月份部分呢Q只需在月份周围加上一个圆括号创徏一个组Q然后用ORO APIQ本文后面详l讨论)提取出它的倹{修改后的正则表辑ּ如图六所C: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/c677z4111jo2.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">囑օQ匹配所有Month DD,YYYY格式的日期,定义月䆾gؓW一个组</p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>1.7 其它W号</b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">为简便v见,你可以用一些ؓ常见正则表达式创建的快捷W号。如表二所C: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">表二Q常用符?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/32xa8u62viqw.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">例如Q在前面C会安全L的例子中Q所有出现“[0-9]”的地方我们都可以用“\d”。修改后的正则表辑ּ如图七所C: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/4k2mcvrp04b7.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">图七Q匹配所?23-12-1234格式的社会安全号?/p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b> <font size="4">二、Jakarta-ORO?/font> </b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">有许多源代码开攄正则表达式库可供JavaE序员用,而且它们中的许多支持Perl 5兼容的正则表辑ּ语法。我在这里选用的是Jakarta-ORO正则表达式库Q它是最全面的正则表辑ּAPI之一Q而且它与Perl 5正则表达式完全兼宏V另外,它也是优化得最好的API之一?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">Jakarta-ORO库以前叫做OROMatcherQDaniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下蝲它?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">我首先将要介l用Jakarta-ORO库时你必d建和讉K的对象,然后介绍如何使用Jakarta-ORO API?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>?PatternCompiler对象</b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">首先Q创Z个Perl5Compilercȝ实例Qƈ把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实玎ͼ允许你把正则表达式编译成用来匚w的Pattern对象?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/x4z3923ca13a.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>?Pattern对象</b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">要把正则表达式编译成Pattern对象Q调用compiler对象的compile()ҎQƈ在调用参C指定正则表达式。例如,你可以按照下面这U方式编译正则表辑ּ“t[aeio]n”: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/2fd26rskmll5.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">默认情况下,~译器创Z个大写敏感的模式(patternQ。因此,上面代码~译得到的模式只匚w“tin”、“tan”?“ten”和“ton”,但不匚w“Tin”和“taN”。要创徏一个大写不敏感的模式Q你应该在调用编译器的时候指定一个额外的参数Q?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/l56lk1spu66k.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">创徏好Pattern对象之后Q你可以通过PatternMatchercȝ该Pattern对象q行模式匚w?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>?PatternMatcher对象</b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">PatternMatcher对象ҎPattern对象和字W串q行匚w查。你要实例化一个Perl5Matchercdƈ把结果赋值给PatternMatcher接口。Perl5MatchercLPatternMatcher接口的一个实玎ͼ它根据Perl 5正则表达式语法进行模式匹配: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/an6co93nb236.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">使用PatternMatcher对象Q你可以用多个方法进行匹配操作,q些Ҏ的第一个参数都是需要根据正则表辑ּq行匚w的字W串Q?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">· boolean matches(String input, Pattern pattern)Q当输入字符串和正则表达式要_匚w时用。换句话_正则表达式必d整地描述输入字符丌Ӏ?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">· boolean matchesPrefix(String input, Pattern pattern)Q当正则表达式匹配输入字W串起始部分时用?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">· boolean contains(String input, Pattern pattern)Q当正则表达式要匚w输入字符串的一部分时用(卻I它必L一个子Ԍ?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">另外Q在上面三个Ҏ调用中,你还可以用PatternMatcherInput对象作ؓ参数替代String对象Q这Ӟ你可以从字符串中最后一ơ匹配的位置开始l进行匹配。当字符串可能有多个子串匚wl定的正则表辑ּӞ用PatternMatcherInput对象作ؓ参数很有用了。用PatternMatcherInput对象作ؓ参数替代StringӞ上述三个Ҏ的语法如下: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">· boolean matches(PatternMatcherInput input, Pattern pattern) </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">· boolean matchesPrefix(PatternMatcherInput input, Pattern pattern) </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">· boolean contains(PatternMatcherInput input, Pattern pattern) </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b> <font size="4">三、应用实?/font> </b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">下面我们来看看Jakarta-ORO库的一些应用实例?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>3.1 日志文g处理</b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">dQ分析一个Web服务器日志文Ӟ定每一个用戯在网站上的时间。在典型的BEA WebLogic日志文g中,日志记录的格式如下: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/242u5d50m3fr.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">分析q个日志记录Q可以发玎ͼ要从q个日志文g提取的内Ҏ两项QIP地址和页面访问时间。你可以用分l符P圆括P从日志记录提取出IP地址和时间标记?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">首先我们来看看IP地址。IP地址?个字节构成,每一个字节的值在0?55之间Q各个字节通过一个句点分隔。因此,IP地址中的每一个字节有臛_一个、最多三个数字。图八显CZ为IP地址~写的正则表辑ּQ?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/21g3c5o3k67u.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">囑օQ匹配IP地址</p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">IP地址中的句点字符必须q行转义处理Q前面加上“\”)Q因为IP地址中的句点h它本来的含义Q而不是采用正则表辑ּ语法中的Ҏ含义。句点在正则表达式中的特D含义本文前面已l介l?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">日志记录的时间部分由一Ҏ括号包围。你可以按照如下思\提取出方括号里面的所有内容:首先搜烦起始Ҏ号字W(“[”)Q提取出所有不过l束Ҏ号字W(“]”)的内容,向前L直至扑ֈl束Ҏ号字W。图九显CZq部分的正则表达式?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/cg2u2j7n0mpg.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">图九Q匹配至一个字W,直至扑ֈ“]?/p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">现在Q把上述两个正则表达式加上分l符P圆括P后合q成单个表达式,q样可以从日志记录提取出IP地址和时间。注意,Z匚w? -”(但不提取它)Q正则表辑ּ中间加入了“\s-\s-\s”。完整的正则表达式如囑֍所C?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/157qqoq9ve8w.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">囑֍Q匹配IP地址和时间标?/p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">现在正则表达式已l编写完毕,接下来可以编写用正则表辑ּ库的Java代码了?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">Z用Jakarta-ORO库,首先创徏正则表达式字W串和待分析的日志记录字W串Q?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/759353ra1907.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">q里使用的正则表辑ּ与图十的正则表达式差不多完全相同Q但有一点例外:在Java中,你必d每一个向前的斜杠Q“\”)q行转义处理。图十不是Java的表CŞ式,所以我们要在每个“\”前面加上一个“\”以免出现编译错误。遗憄是,转义处理q程很容易出现错误,所以应该小心}慎。你可以首先输入未经转义处理的正则表辑ּQ然后从左到右依ơ把每一个“\”替换成“\\”。如果要复检Q你可以试着把它输出到屏q上?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">初始化字W串之后Q实例化PatternCompiler对象Q用PatternCompiler~译正则表达式创Z个Pattern对象Q?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/4o3y3mdkct2x.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">现在Q创建PatternMatcher对象Q调用PatternMatcher接口的contain()Ҏ查匹配情况: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/75jn387mn42x.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">接下来,利用PatternMatcher接口q回的MatchResult对象Q输出匹配的l。由于logEntry字符串包含匹配的内容Q你可以看到cd下面的输出: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/vgpi8nu05ivw.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>3.2 HTML处理实例一</b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">下面一个Q务是分析HTML面内FONT标记的所有属性。HTML面内典型的FONT标记如下所C: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <font face="Arial, Serif" color="red" size="+2"> </font> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/606h60377ssy.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">E序按照如下Ş式,输出每一个FONT标记的属性: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/brf9m2df9ieo.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">在这U情况下Q我你用两个正则表辑ּ。第一个如囑֍一所C,它从字体标记提取出?face="Arial, Serif" size="+2" color="red"”?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/ru4fdvu24otu.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">囑֍一Q匹配FONT标记的所有属?/p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">W二个正则表辑ּ如图十二所C,它把各个属性分割成名字-值对?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/7jng3h91d45k.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">囑֍二:匚w单个属性,q把它分割成名字-值对</p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">分割l果为: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/7jjzyu7lfs84.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">现在我们来看看完成这个Q务的Java代码。首先创Z个正则表辑ּ字符Ԍ用Perl5Compiler把它们编译成Pattern对象。编译正则表辑ּ的时候,指定Perl5Compiler.CASE_INSENSITIVE_MASK选项Q得匹配操作不区分大小写?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">接下来,创徏一个执行匹配操作的Perl5Matcher对象?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/5cf25vch72r5.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">假设有一个Stringcd的变量htmlQ它代表了HTML文g中的一行内宏V如果html字符串包含FONT标记Q匹配器返回true。此Ӟ你可以用匚w器对象返回的MatchResult对象获得W一个组Q它包含了FONT的所有属性: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/6z605d16f9gp.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">接下来创Z个PatternMatcherInput对象。这个对象允怽从最后一ơ匹配的位置开始l进行匹配操作,因此Q它很适合于提取FONT标记内属性的名字-值对。创建PatternMatcherInput对象Q以参数形式传入待匹配的字符丌Ӏ然后,用匹配器实例提取出每一个FONT的属性。这通过指定PatternMatcherInput对象Q而不是字W串对象Qؓ参数Q反复地调用PatternMatcher对象的contains()Ҏ完成。PatternMatcherInput对象之中的每一ơP代将把它内部的指针向前移动,下一ơ检将从前一ơ匹配位|的后面开始?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">本例的输出结果如下: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/308i497h04uz.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>3.3 HTML处理实例?/b> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">下面我们来看看另一个处理HTML的例子。这一ơ,我们假定Web服务器从widgets.acme.comUd了newserver.acme.com。现在你要修改一些页面中的链接: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/17341kb8z3di.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">执行q个搜烦的正则表辑ּ如图十三所C: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center"> <img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/88277rk37770.gif" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <p align="center">囑֍三:匚w修改前的链接</p> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">如果能够匚wq个正则表达式,你可以用下面的内Ҏ换图十三的链接: </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <a > </a> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/s82f65t25m75.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">注意#字符的后面加上了$1。Perl正则表达式语法用$1?2{表C已l匹配且提取出来的组。图十三的表辑ּ把所有作Z个组匚w和提取出来的内容附加到链接的后面?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">现在Q返回Java。就象前面我们所做的那样Q你必须创徏试字符Ԍ创徏把正则表辑ּ~译到Pattern对象所必需的对象,以及创徏一个PatternMatcher对象Q?img style="WIDTH: 500px; CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/qg1rzozee4bf.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /></td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">接下来,用com.oroinc.text.regex包Utilcȝsubstitute()静态方法进行替换,输出l果字符Ԍ </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/o3m76k1jdp62.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">Util.substitute()Ҏ的语法如下: </td> </tr> </tbody> </table> <table height="17" width="620" align="center"> <tbody> <tr> <td class="a14" height="13"> <img style="CURSOR: pointer" onclick="javascript:window.open(this.src);" alt="" src="http://edu.yesky.com/imagelist/05/10/v9z05f24f3tc.jpg" onload="javascript:if(this.width>500)this.style.width=500;" border="0" /> </td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14">q个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象Q它军_了替换操作如何进行。本例用的是Perl5Substitution对象Q它能够q行Perl5风格的替换。第四个参数是想要进行替换操作的字符Ԍ最后一个参数允许指定是否替换模式的所有匹配子ԌUtil.SUBSTITUTE_ALLQ,或只替换指定的次数?</td> </tr> </tbody> </table> <table width="620" align="center"> <tbody> <tr> <td class="a14"> <b>【结束语?/b>在这文章中Q我Z介绍了正则表辑ּ的强大功能。只要正运用,正则表达式能够在字符串提取和文本修改中v到很大的作用。另外,我还介绍了如何在JavaE序中通过Jakarta-ORO库利用正则表辑ּ。至于最l采用老式的字W串处理方式Q用StringTokenizerQcharAtQ和substringQ,q是采用正则表达式,q就有待你自己决定了?br /><br />Q?1q写的,紧参考!Q?/td> </tr> </tbody> </table> <img src ="http://www.aygfsteel.com/Duffblog/aggbug/87626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Duffblog/" target="_blank">q球?/a> 2006-12-14 09:45 <a href="http://www.aygfsteel.com/Duffblog/articles/87626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 虚礼机的一些配|?/title><link>http://www.aygfsteel.com/Duffblog/articles/76033.html</link><dc:creator>q球?/dc:creator><author>q球?/author><pubDate>Wed, 18 Oct 2006 14:40:00 GMT</pubDate><guid>http://www.aygfsteel.com/Duffblog/articles/76033.html</guid><wfw:comment>http://www.aygfsteel.com/Duffblog/comments/76033.html</wfw:comment><comments>http://www.aygfsteel.com/Duffblog/articles/76033.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Duffblog/comments/commentRss/76033.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Duffblog/services/trackbacks/76033.html</trackback:ping><description><![CDATA[1.讄MaxPermSize<br />MaxPermSize 可以讄为最大堆分配 (mx) 的一半。尝试设|?.XX:MaxPermSize=256m,但是,也有|到和MX一L.可以试一?<br />2.Heap Size<br />你的ERROR不是OUTOFMEMEROY,所以HEAP的大应该可?-Xms512m -Xmx512m 可以试一?但是最q?月底有h发表意见说设成相同的比太?会导致GCq行旉q短,D效率下降.<br />3.HeapFreeRatio<br />q项讄对你的问题有没有帮助不太清楚,做一个比较反差的试,-XX:MinHeapFreeRatio=10,-XX:MaxHeapFreeRatio=20,看看区别,最l设|?<br />-XX:MinHeapFreeRatio=30,-XX:MaxHeapFreeRatio=70<br />4.NewRatio<br />有可能是young generation 的大过?Dpermanent generation大小不够,所以调整NewRatio有可能有?<br />-XX:NewRatio=4<br /><img src ="http://www.aygfsteel.com/Duffblog/aggbug/76033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Duffblog/" target="_blank">q球?/a> 2006-10-18 22:40 <a href="http://www.aygfsteel.com/Duffblog/articles/76033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Spring用JDBC 调用ORACLE存储q程的结果集http://www.aygfsteel.com/Duffblog/articles/72713.htmlq球?/dc:creator>q球?/author>Fri, 29 Sep 2006 00:56:00 GMThttp://www.aygfsteel.com/Duffblog/articles/72713.htmlhttp://www.aygfsteel.com/Duffblog/comments/72713.htmlhttp://www.aygfsteel.com/Duffblog/articles/72713.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/72713.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/72713.html public class LoadStoredProcedure extends StoredProcedure {

 
 private Map inParam;
 
 public MktLoadStoredProcedure(String storedProcedureName) {
  DataSource ds = (DataSource)SpringContextUtils.getInstance().getBean("dataSource");
  setDataSource(ds);
  setSql(storedProcedureName);
 }
 
 public RowMapper RouteRowMapper = new RowMapper(){
  public Object mapRow(ResultSet rs,int rowNum) throws SQLException{
   BidRouteInfo route = new BidRouteInfo();
   route.setBidHeaderId(rs.getString("BID_HEADER_ID"));
   route.setBidRouteInfoId(rs.getString("BID_ROUTE_INFO_ID"));
   route.setCreatedByUser(rs.getString("CREATED_BY_USER"));
   route.setCreatedDtmLoc(rs.getDate("CREATED_DTM_LOC"));
   route.setCreatedOffice(rs.getString("CREATED_OFFICE"));
   route.setCreatedTimeZone(rs.getString("CREATED_TIME_ZONE"));
   route.setDestCode(rs.getString("DEST_CODE"));
   route.setDestName(rs.getString("DEST_NAME"));
   route.setPodCode(rs.getString("POD_CODE"));
   route.setPodDestMode(rs.getString("POD_DEST_MODE"));
   route.setPodName(rs.getString("POD_NAME"));
   route.setPolCode(rs.getString("POL_CODE"));
   route.setPolName(rs.getString("POL_NAME"));
   route.setPorCode(rs.getString("POR_CODE"));
   route.setPorName(rs.getString("POR_NAME"));
   route.setPorPolMode(rs.getString("POR_POL_MODE"));
   route.setPorState(rs.getString("POR_STATE"));
   route.setPrincipalGroupCode(rs.getString("PRINCIPAL_GROUP_CODE"));
   route.setRecordVersion(rs.getLong("RECORD_VERSION"));
   route.setSeqNo(rs.getLong("SEQ_NO"));
   route.setServiceType(rs.getString("SERVICE_TYPE"));
   route.setStateCode(rs.getString("STATE_CODE"));
   route.setUpdatedByUser(rs.getString("UPDATED_BY_USER"));
   route.setUpdatedDtmLoc(rs.getDate("UPDATED_DTM_LOC"));
   route.setUpdatedOffice(rs.getString("UPDATED_OFFICE"));
   route.setUpdatedTimeZone(rs.getString("UPDATED_TIME_ZONE"));
   route.setRowStatus(BaseObject.ROWSTATUS_UNCHANGED);
   return route;
  }
 };
 
 public RowMapper FreightRowMapper = new RowMapper(){
  public Object mapRow(ResultSet rs,int rowNum) throws SQLException{
   BidFreightDetail freight = new BidFreightDetail();
   freight.setBidRouteInfoId(rs.getString("BID_ROUTE_INFO_ID"));
   freight.setBgColor(rs.getString("BG_COLOR"));
   freight.setBidFreightDetailId(rs.getString("BID_FREIGHT_DETAIL_ID"));
   freight.setChargeCode(rs.getString("CHARGE_CODE"));
   freight.setContainerType(rs.getString("CONTAINER_TYPE"));
   freight.setCreatedByUser(rs.getString("CREATED_BY_USER"));
   freight.setCreatedDtmLoc(rs.getDate("CREATED_DTM_LOC"));
   freight.setCreatedOffice(rs.getString("CREATED_OFFICE"));
   freight.setCreatedTimeZone(rs.getString("CREATED_TIME_ZONE"));
   freight.setPrincipalGroupCode(rs.getString("PRINCIPAL_GROUP_CODE"));
   freight.setRate(rs.getBigDecimal("RATE"));
   freight.setRecordVersion(rs.getLong("RECORD_VERSION"));
   freight.setUpdatedByUser(rs.getString("UPDATED_BY_USER"));
   freight.setUpdatedDtmLoc(rs.getDate("UPDATED_DTM_LOC"));
   freight.setUpdatedOffice(rs.getString("UPDATED_OFFICE"));
   freight.setUpdatedTimeZone(rs.getString("UPDATED_TIME_ZONE"));
   freight.setRowStatus(BaseObject.ROWSTATUS_UNCHANGED);
   return freight;
  }
 };
 //spring版本?.2更新?.0-rc3
// private RowMapperResultReader callback = new RowMapperResultReader(rowMapper){
//  public void processRow(ResultSet rs) throws SQLException{
//   int count = rs.getMetaData().getColumnCount();
//   String[] header = new String[count];
//   for(int i=0;i<count;i++){
//    header[i] = rs.getMetaData().getColumnName(i+1);
//   }
//   do{
//     HashMap<String,String> row = new HashMap<String,String>();
//     for(int i=0;i<count;i++){
//      row.put(header[i],rs.getString(i+1));
//     }
//     rsList.add(row);
//   }while(rs.next());
//  }
// };
 
// private RowMapperResultSetExtractor callback = new RowMapperResultSetExtractor(RouteRowMapper){
//  public List extractData(ResultSet rs) throws SQLException{
//   int count = rs.getMetaData().getColumnCount();
//   String[] header = new String[count];
//   for(int i=0;i<count;i++){
//    header[i] = rs.getMetaData().getColumnName(i+1);
//   }
//   while(rs.next()){
//     HashMap<String,String> row = new HashMap<String,String>();
//     for(int i=0;i<count;i++){
//      row.put(header[i],rs.getString(i+1));
//     }
//     rsList.add(row);
//   }
//   return rsList;
//  }
// };
 
 public Map execute(){
  compile();
  if(inParam == null){
   return execute();
  }
  return execute(this.inParam);
 }

 public void setOutParameter(String column,int type,RowMapper rowMapper){
  declareParameter(new SqlOutParameter(column,type,rowMapper));
 }
 
 public void setParameter(String column,int type){
  declareParameter(new SqlParameter(column,type));
 }
 public void setInParam(Map inParam){
  this.inParam = inParam;
 }
}

调用Q?br />
   LoadStoredProcedure sp = new LoadStoredProcedure("SP_MKT_LOAD_TEST");
  sp.setParameter("V_BID_HEADER_ID", Types.VARCHAR);
  sp.setOutParameter("ROUTECURSOR", OracleTypes.CURSOR,sp.RouteRowMapper);
  sp.setOutParameter("FRIGHTCURSOR", OracleTypes.CURSOR,sp.FreightRowMapper);
  
  Map<String,String> mapValue = new HashMap<String,String>(1);
  mapValue.put("V_BID_HEADER_ID", bidHeaderId);
  sp.setInParam(mapValue);
  Map map = sp.execute();

List freightDetails = (List)map.get("FRIGHTCURSOR");
  List routeInfos = (List)map.get("ROUTECURSOR");
具体参考:

http://www.springframework.org/docs/reference/jdbc.html



]]>
Java AWT ClipboardQJava剪脓板)的用法?/title><link>http://www.aygfsteel.com/Duffblog/articles/71842.html</link><dc:creator>q球?/dc:creator><author>q球?/author><pubDate>Mon, 25 Sep 2006 14:45:00 GMT</pubDate><guid>http://www.aygfsteel.com/Duffblog/articles/71842.html</guid><wfw:comment>http://www.aygfsteel.com/Duffblog/comments/71842.html</wfw:comment><comments>http://www.aygfsteel.com/Duffblog/articles/71842.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/Duffblog/comments/commentRss/71842.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/Duffblog/services/trackbacks/71842.html</trackback:ping><description><![CDATA[Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();<br />  int excelRowCount = 0;<br />  try{<br />   CommonCursor.setCursorBusy();<br />   String value = (String) (clipboard.getContents(this).getTransferData(DataFlavor.stringFlavor)); <br />   if(value.indexOf("\t") == 0)<br />    value = value.replaceFirst("\t", " \t");<br />   while(value.indexOf("\t\t") >= 0){<br />    value = value.replace("\t\t", "\t \t");<br />   }<br />   value = value.replace("\n\t", "\n \t");<br />         StringTokenizer st1 = new StringTokenizer(value, "\n");<br />         excelRowCount = st1.countTokens();<br />         if(excelRowCount == 0)return;<br />         List<BidRouteInfo> pastedRouteInfos = new LinkedList<BidRouteInfo>();<br />         Date d = new Date();<br />         for (int i = 0; st1.hasMoreTokens(); i++) {<br />             BidRouteInfo routeInfo = new BidRouteInfo();<br />             routeInfo.setBidRouteInfoId(UUID.randomUUID().toString());<br />             routeInfo.setSeqNo(getMaxSequenceNo()+1);<br />             routeInfo.setRowStatus(BaseObject.ROWSTATUS_ADDED);<br />             bidHeader.addBidRouteInfo(routeInfo);<br />             pastedRouteInfos.add(routeInfo);<br />             String rowstring = st1.nextToken();<br />             StringTokenizer st2 = new StringTokenizer(rowstring, "\t");<br />             for (int j = 0; st2.hasMoreTokens(); j++) {<br />              String cellStr = (String) st2.nextToken();<br />              cellStr = cellStr.trim();<br />              cellStr = cellStr.toUpperCase();<br />              //W?列是隐藏?ȝ功能必须在有FixColumnHeader的情况下生效)<br />              switch( j ){<br />               case BidRouteFreightMode.POR_NAME-1:<br />                routeInfo.setPorName(cellStr);<br />                break;<br />               case BidRouteFreightMode.POR_STATE-1:<br />                routeInfo.setPorState(cellStr);<br />                break;<br />               case BidRouteFreightMode.POL_MODE-1:<br />                routeInfo.setPorPolMode(cellStr);<br />                break;<br />               case BidRouteFreightMode.POL_NAME-1:<br />                routeInfo.setPolName(cellStr);<br />                break;<br />               case BidRouteFreightMode.POD_NAME-1:<br />                routeInfo.setPodName(cellStr);<br />                break;<br />               case BidRouteFreightMode.DEST_NAME-1:<br />                routeInfo.setDestName(cellStr);<br />                break; <br />               case BidRouteFreightMode.STATE-1:<br />                routeInfo.setStateCode(cellStr);<br />                break;<br />               case BidRouteFreightMode.POD_MODE-1:<br />                routeInfo.setPodDestMode(cellStr);<br />                break; <br />              }<br />             }<br />            }<br /><img src ="http://www.aygfsteel.com/Duffblog/aggbug/71842.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/Duffblog/" target="_blank">q球?/a> 2006-09-25 22:45 <a href="http://www.aygfsteel.com/Duffblog/articles/71842.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>咖啡Q还是E些好http://www.aygfsteel.com/Duffblog/articles/59589.htmlq球?/dc:creator>q球?/author>Sat, 22 Jul 2006 14:28:00 GMThttp://www.aygfsteel.com/Duffblog/articles/59589.htmlhttp://www.aygfsteel.com/Duffblog/comments/59589.htmlhttp://www.aygfsteel.com/Duffblog/articles/59589.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/59589.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/59589.html 好久没有l大家写点什么了Q由于最q特别忙Q希望不要介意!

 

    今天Q来谈喝咖啡吗?当然不是Q我们要看看咖啡到底该怎么喝,正如?/span> J2EE 一栗?/span>

 

太浓了吧

否則怎会苦的说不

每次都一个h在自问自{?/span>

我们的爱到底q在?/span>

 

    W一ơ,听到q段台词Q您呢?听过没有Q这可是我偶像唱的(张学友新专辑Q《他在那里》中的,咖啡Q徏议听听,很不错。他的歌是流行,但又非流行)?/span>

Java Q我来谈如何品她Q可不是一件简单的事情Q因为我喝的也不多,你呢Q但我在用心d。我们学技术,可不要陷入一个怪圈Q唯技术论Q这L话你可就错了。无Z么技术,都是ZhcL务的Q我们的目标是更好的生活Q自然咖啡也不了。所以,我们对待 Java 的态度一定要有理性,比如Q蔡孔R先生 (http://www.oreilly.com.tw/sleepless/index.htm ) 都谦虚的_他的 Java 功底?/span> Lots of API 。所以,心态要攑^和,可不要有宗教式的仰慕Q本Z是很喜欢 Java 的)?/span>

初次接触 Java Q大家一定会?/span> Java 中大量的术语Q新名词吓了一大蟩。打开 The Source for Java Technology Q?/span> http://java.sun.com Q?/span> , 点击q入 http://java.sun.com/j2se/ Q?/span> Java 2 出来了,q可是热气腾腄Q很够味。下载一?/span> JavaTM 2 Platform, Standard Edition (J2SETM) Q网址 http://java.sun.com/j2se/downloads.html 。安装在一个没有空格的目录下。比如,?/span> E:\j2sdk1.4.x 下。安装完后,您现在所需要的做的是三g事情。第一Q设|环境变量, set JAVA_HOME = E:\j2sdk1.4.x Q其ơ再设一个环境变量, set classpath = .; Q最后还需 set path = %JAVA_HOME%\bin 。这样就完成?/span> J2SE 的安装。安装完后,大家可以?/span> E:\j2sdk1.4.0\demo q行 J2SE 带的 Demos 看看。哈哈,好漂亮?/span> E:\j2sdk1.4.0\demo\jfc\Java2D Q这个例子您看过没有Q特别好看。好是M慕。我自己也想写这么漂亮的E序。怎么办?Q?Q?/span>

http://java.sun.com/docs/books/tutorial/ , q个地方可是您的切入炏V我英文不怎么P怎么办?其实技术领域的英文Q你刚开始看的时候会有这LxQ但旉长了Q只要你可以坚持Q慢慢的你就会发玎ͼ原来英文表达技术内늉别脓切,不相信,你就看吧。。。:Q?/font>

当然Q做什么东襉K得有工具。木匠有自己的一套工兗?/span> Brood Q我们也得有自己的一些好工具。个为,q三件宝贝缺一不可。第一Ӟ Java 2 SDK, Standard Edition, Documentation Q?/span> http://java.sun.com/j2se/1.4.1/docs/index.html 。这是您的圣经Q可要经常看看,不会的、会的,要经常参考,q可使你的功力大增,可要坚持哦,不要因ؓ是一时的热情。第二gQ就是,?/span> Thinking in Java 》, http://64.78.49.204/TIJ3.zip 有最新版Q第三版Q下载,其中讲述?/span> J2SE 1.4.0 。其中,W二版的中文译Q由侯捷译的,一定不要错q!Q, http://www.china-pub.com/computers/common/info.asp?id=7241 Q如果说W一件宝贝是圣经Q那么这本就是玄学。这可是大家能修炼到的高境界的入门读物,一定比漫画书好看。那么,W三件是什么呢Q那是你自己,一定要多思考、多l、多写程序。你可以d一切,但除了你自己?/span>

刚开始工L选择Q这个因异。我喜欢用大家伙Q比?/span> JBuilder ?/span> Together ?/span> Eclipse ?/span> JDeveloper ?/span> …? 。当Ӟ你可以用 JCreator Q也Z错的。大的工具可以加快你的功效,但前提是你对 Java 本n有良好的操控能力?/span>

哦,L一下?/font>

 

已经淡了?/span>

多放些糖也很难有变化

不如喝完q杯各自回?/span>

別坐在对面欣賞我的掙?/span>

 

其实Q甜咖啡也挺不错的。看你喜不喜Ƣ喝了。在q里说几句题外话Q那是计算机图书。其实,书,无论写得好与坏,都值得一看。但前提是你不会被他l误对{(如果Q你W一ơ把我骗了,你就是很卑鄙Q如果再ơ被你骗Q说明我很无耻!Q)Q这句话不是我说的)每本书都能反映作者的某种思想。所以多看书Q还是不错的。这个时候肯定有Z问,看完后,隔上一D|间又忘得差不多了。其实这个很正常Q关键看你是否坚持?/span>

好了Q?/span> J2SE p到这里。有了相当的功底后,我们来啃另一快大矛_Q?/span> J2EE ?/span>

J2EE Q现在可以说Q是一个自己wh抬高的绝佳途径。但看到那么多概念,术语Q名词,了Q还是不学得好。我x们都有这U想法。其实换一U角度,来看Q不?/span> VB,Delphi 上手快。但有一点, J2EE 的体pȝ别清晰。由?/span> http://www.jcp.org , 操控?/span> Java 的命脉,所以你一定要知道q个地方。好了,首先?/span> http://java.sun.com/j2ee/download.html Q?/span> 下蝲一?/span> Sun 的参考实现版?/span> JavaTM 2 Platform, Enterprise Edition (J2EETM) 。安装完后,你可以参考安装目?/span> \doc 中配|相应的参数。好了,然后Q去 http://java.sun.com/j2ee/tutorial/1_3-fcs/ 看看Q当Ӟ事务都是盔R的。学 J2SE 中类似的q程在这里也可以拿过来。首先,l你 3 件宝刀。第一Ӟ http://jcp.org/en/jsr/stage?listBy=final 下蝲 J2EE Specification Q这个规范可要经常看。这是您的老师Q什么时候都是。第二g宝贝您可一定不要错q, http://www2.theserverside.com/resources/index.jsp q里很不错。第三gQ可以去 http://java.sun.com/blueprints/ 看看 Petstore Q至于其源代码是否值得研究Q个Z值得Q有q么多时_不如ȝI?/span> JBoss Q)。或者说Q换一U角度,您可以去 http://otn.oracle.com/sample_code/tutorials/fbs/fbstoc.htm 看看Q看完后Q你应该不会骂我的?/span>

{您有了一定的 J2EE 功底后,你可以开始走向更高的地方Q首先看D台词先?/span>

 

一场失敗的爱情像个W话

热得时后心ؕ如麻

冷了以后看见自己够傻

人怎么会如此容易无法自?/span>

 

其实Q在 J2EE 中,重要的不是各个技术本w( EJB, ?/span> COM 好学Q!Q您认ؓ呢?Q,重要的是 J2EE 设计模式的合理运用。那么,其中Q有三个东西值得您去x。一个,在这个过E中Q一定要?/span> J2EE 的体pȝ构弄得很清楚。二个, EJB 技术,q可是含金量很大的地斏V第三,一定要x常见?/span> Java Open Source 。。。这个都不知道的话,说明您还没有?/span> J2EE 有很好的认识。其中,有一些较好的资源Q?/span> http://gceclub.sun.com.cn/experttalk/oct15.html q可是一的 Caffee!!! http://www2.theserverside.com/home/index.jsp 高手一定要ȝ地方?/span>

慢慢的,您要形成善于、喜Ƣ关注业界动态的习惯Q!q种沉淀可是无h的。没有时间、精力的付出Q你对业界是不会有很好的、很q认识?/font>

一句话Q学?/span> J2EE Q一定要有宏观的把握Q具体技术的深入l节需要我们在N中慢慢领悟,q也不是看几本书所能掌握的Q贵在坚持,但一定要注意Ҏ?/span>

 

一场无味的爱情像个谎话

甜的时后只相信它

苦了以后每一句都可?/span>

人怎么会如此容易了无牽?/span>

 

有了前面q些东东Q我们可以开始研I某一?/span> J2EE 应用服务器。比如, JBoss, WebLogic 。首先学会熟l用,慢慢的深入到具体的细节,比如 JMX 技术。因 J2EE 应用服务器集成、实C规范中的所有技术,所以这些是很不错的思\?/span>

 

Web Services 技术,可以?/span> J2EE q_生来有q种N Web Services 的能力。ؓ什么这么说呢? Web Services 技术,要是没有 XML 技术ؓ先遣部队Q我?/span> Web Services 业不会有今天。微软也不会?/span> Web Services UC为, XML Web Services 技术?/span> XML 技术对数据提供了便利?/span> Java 对^台提供了便利。其l合的结果可惌知。即使没有“孤独求败”那么厉宻I我想也会有“不败孤独”那么好。有些公司很会做技术,有些公司很会做市场。但大家的眼光是雪亮的,我们也没有必要说什么技术是万能的,没有万能的技术,关键看应用,是否能很好的解决实际问题?/span>

 

说白了, Web Services 中其实没多少C西,但这U体pȝ构需要您有很好的把握Q然后深入技术细则?/span>

 

q些Q都是我的个点,希望看完后,有不对的地方Q批评指正!Q?/font>

 

也欢q访问我的个Z栏。(也欢q大家写信和我交,交个朋友也可以!Q?/font>

 

http://www.csdn.net/develop/author/netauthor/worldheart/

 

您开始喝咖啡没有Q要不,l你来一杯,不要噎到了,要慢慢品Q。。。。?/font>



]]>
JAVA内存泄漏——内存泄漏原因和内存泄漏工?zt)http://www.aygfsteel.com/Duffblog/articles/50044.htmlq球?/dc:creator>q球?/author>Fri, 02 Jun 2006 11:17:00 GMThttp://www.aygfsteel.com/Duffblog/articles/50044.htmlhttp://www.aygfsteel.com/Duffblog/comments/50044.htmlhttp://www.aygfsteel.com/Duffblog/articles/50044.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/50044.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/50044.html摘要
  虽然Java虚拟?JVM)及其垃圾攉?garbage collectorQGC)负责理大多数的内存dQJava软gE序中还是有可能出现内存泄漏。实际上Q这在大型项目中是一个常见的问题。避免内存泄 漏的W一步是要弄清楚它是如何发生的。本文介l了~写Java代码的一些常见的内存泄漏陷阱Q以及编写不泄漏代码的一些最佛_c一旦发生了内存泄漏Q要 指出造成泄漏的代码是非常困难的。因此本文还介绍了一U新工具Q用来诊断泄漏ƈ指出Ҏ原因。该工具的开销非常,因此可以使用它来L处于生中的pȝ 的内存泄漏?/p>

垃圾攉器的作用

  虽然垃圾攉器处理了大多数内存管理问题,从而ɾ~程人员的生zd得更? 松了Q但是编Eh员还是可能犯错而导致出现内存问题。简单地_GC循环地跟t所有来自“根”对象(堆栈对象、静态对象、JNI句柄指向的对象,诸如? c)的引用,q将所有它所能到辄对象标记为活动的。程序只可以操纵q些对象Q其他的对象都被删除了。因为GC使程序不可能到达已被删除的对象,q么做就 是安全的?/p>

  虽然内存理可以说是自动化的Q但是这q不能ɾ~程人员免受思考内存管理问题之苦。例如,分配Q以及释放)内存M 有开销Q虽然这U开销对编Eh员来说是不可见的。创Z太多对象的程序将会比完成同样的功能而创建的对象却比较少的程序更慢一些(在其他条件相同的情况 下)?/p>

  而且Q与本文更ؓ密切相关的是Q如果忘记“释䏀先前分配的内存Q就可能造成内存泄漏。如果程序保留对永远不再使用的对 象的引用Q这些对象将会占用ƈ耗尽内存Q这是因动化的垃圾收集器无法证明q些对象不再用。正如我们先前所说的Q如果存在一个对对象的引用,对象? 被定义ؓzd的,因此不能删除。ؓ了确保能回收对象占用的内存,~程人员必须保该对象不能到达。这通常是通过对象字D设|ؓnull或者从集合 (collection)中移除对象而完成的。但是,注意Q当局部变量不再用时Q没有必要将其显式地讄为null。对q些变量的引用将随着Ҏ的退? 而自动清除?/p>

  概括地说Q这是内存托管语言中的内存泄漏产生的主要原因:保留下来却永q不再用的对象引用?/p>

典型泄漏

  既然我们知道了在Java中确实有可能发生内存泄漏Q就让我们来看一些典型的内存泄漏及其原因?/p>

全局集合

  在大的应用程序中有某U全局的数据储存库是很常见的,例如一个JNDI树或一个会话表。在q些情况下,必须注意理储存库的大小。必L某种机制从储存库中移除不再需要的数据?/p>

  q可能有多种ҎQ但是最常见的一U是周期性运行的某种清除d。该d验证储存库中的数据QƈU除M不再需要的数据?/p>

  另一U管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零Ӟ该元素就可以从集合中U除了?/p>

~存

  ~存是一U数据结构,用于快速查扑ַl执行的操作的结果。因此,如果一个操作执行v来很慢,对于常用的输入数据,可以将操作的结果缓存,q在下次调用该操作时使用~存的数据?/p>

  ~存通常都是以动态方式实现的Q其中新的结果是在执行时d到缓存中的。典型的法是:

查结果是否在~存中,如果在,p回结果?
如果l果不在~存中,p行计?
计出来的l果d到缓存中Q以便以后对该操作的调用可以使用?
  该算法的问题Q或者说是潜在的内存泄漏Q出在最后一步。如果调用该操作时有相当多的不同输入Q就有相当多的l果存储在缓存中。很明显q不是正的Ҏ?/p>

  Z预防q种h潜在破坏性的设计Q程序必ȝ保对于缓存所使用的内存容量有一个上限。因此,更好的算法是Q?/p>

查结果是否在~存中,如果在,p回结果?
如果l果不在~存中,p行计?
如果~存所占的I间q大Q就U除~存最久的l果?
计出来的l果d到缓存中Q以便以后对该操作的调用可以使用?
  通过始终U除~存最久的l果Q我们实际上q行了这L假设Q在来Q比L存最久的数据Q最q输入的数据更有可能用到。这通常是一个不错的假设?/p>

  新算法将保~存的容量处于预定义的内存范围之内。确切的范围可能很难计算Q因为缓存中的对象在不断变化Q而且它们的引用包|万象。ؓ~存讄正确的大是一w常复杂的dQ需要将所使用的内存容量与索数据的速度加以q?/p>

  解决q个问题的另一U方法是使用java.lang.ref.SoftReferencec跟t缓存中的对象。这U方法保证这些引用能够被U除Q如果虚拟机的内存用而需要更多堆的话?/p>

ClassLoader

   Java ClassLoaderl构的用ؓ内存泄漏提供了许多可乘之机。正是该l构本n的复杂性ClassLoader在内存泄漏方面存在如此多的问题? ClassLoader的特别之处在于它不仅涉及“常规”的对象引用Q还涉及元对象引用,比如Q字Dc方法和cR这意味着只要有对字段、方法、类? ClassLoader的对象的引用QClassLoader׃ȝ在JVM中。因为ClassLoader本n可以兌许多cd光态字D,所以就? 许多内存被泄漏了?/p>

定泄漏的位|?/p>

  通常发生内存泄漏的第一个迹象是Q在应用E序中出C OutOfMemoryError。这通常发生在您最不愿意它发生的生产环境中Q此时几乎不能进行调试。有可能是因为测试环境运行应用程序的方式与生产系 l不完全相同Q因而导致泄漏只出现在生产中。在q种情况下,需要用一些开销较低的工h监控和查扑ֆ存泄漏。还需要能够无需重启pȝ或修改代码就可以? q些工具q接到正在运行的pȝ上。可能最重要的是Q当q行分析Ӟ需要能够断开工具而保持系l不受干扰?/p>

  虽然 OutOfMemoryError通常都是内存泄漏的信P但是也有可能应用E序实正在使用q么多的内存Q对于后者,或者必d加JVM可用的堆的数 量,或者对应用E序q行某种更改Q它用较的内存。但是,在许多情况下QOutOfMemoryError都是内存泄漏的信受一U查明方法是不间? 地监控GC的活动,定内存使用量是否随着旉增加。如果确实如此,可能发生了内存泄漏?/p>

详细输出

  有许多监控垃圾收集器zd的方法。而其中用最q泛的可能是使用-Xverbose:gc选项启动JVMQƈ观察输出?/p>

[memory ] 10.109-10.235: GC 65536K->16788K (65536K), 126.000 ms
 头后面的|本例中是16788KQ是垃圾攉所使用的堆的容量?/p>

控制?/p>

  查看q箋不断的GC的详l统计信息的输出是非常乏味的。幸好有q方面的工具。JRockit Management Console可以昄堆用量的图C。借助于该图,可以很容易地看出堆用量是否随时间增加?br />
Figure 1. The JRockit Management Console

甚至可以配置该管理控制台Q以便如果发生堆使用量过大的情况Q或Z其他的事ӞQ控制台能够向您发送电子邮件。这明显使内存泄漏的查看变得更容易了?/p>

内存泄漏工?/font>

  q有其他的专门进行内存泄漏检的工具。JRockit Memory Leak Detector可以用来查看内存泄漏Qƈ可以更深入地查出泄漏的根源。这个强大的工具是紧密集成到JRockit JVM中的Q其开销非常,对虚拟机的堆的访问也很容易?/font>

专业工具的优?/font>

   一旦知道确实发生了内存泄漏Q就需要更专业的工h查明Z么会发生泄漏。JVM自己是不会告诉您的。这些专业工具从JVM获得内存pȝ信息的方法基? 上有两种QJVMTI和字节码技?byte code instrumentation)。Java虚拟机工h?Java Virtual Machine Tools InterfaceQJVMTI)及其前nJava虚拟机监视程序接?Java Virtual Machine Profiling InterfaceQJVMPI)是外部工具与JVM通信q从JVM攉信息的标准化接口。字节码技术是指用探器处理字节码以获得工具所需的信息的技 术?/font>

  对于内存泄漏来_q两U技术有两个~点Q这使它 们不太适合用于生环境。首先,它们在内存占用和性能降低斚w的开销不可忽略。有兛_使用量的信息必须以某U方式从JVM导出Qƈ攉到工具中q行处理? q意味着要ؓ工具分配内存。信息的导出也媄响了JVM的性能。例如,当收集信息时Q垃圾收集器运行得比较慢。另外一个缺Ҏ需要始l将工具q在JVM 上。这是不可能的:工兯在一个已l启动的JVM上,q行分析Q断开工具Qƈ保持JVMq行?/font>

   因ؓJRockit Memory Leak Detector是集成到JVM中的Q就没有q两个缺点了。首先,许多处理和分析工作是在JVM内部q行的,所以没有必要{换或重新创徏M数据。处理还 可以背负(piggyback)在垃圾收集器本n上而进行,q意味着提高了速度。其ơ,只要JVM是?Xmanagement选项Q允讔R过q程 JMX接口监控和管理JVMQ启动的QMemory Leak Detector可以与q行中的JVMq行q接或断开。当该工h开Ӟ没有M东西遗留在JVM中,JVM又将以全速运行代码,正如工具q接之前一 栗?/font>

势分析

   让我们深入地研究一下该工具以及它是如何用来跟踪内存泄漏的。在知道发生内存泄漏之后Q第一步是要弄清楚泄漏了什么数?-哪个cȝ对象引v了泄漏? JRockit Memory Leak Detector是通过在每ơ垃圾收集时计算每个cȝ现有对象的数目来实现q一步的。如果特定类的对象数目随旉而增长(“增长率”)Q就可能发生了内? 泄漏?


?. Memory Leak Detector的趋势分析视?/font>

   因ؓ泄漏可能像细一样非常小Q所以趋势分析必运行很长一D|间。在短时间内Q可能会发生一些类的局部增长,而之后它们又会跌落。但是趋势分析的开销 很小Q最大开销也不q是在每ơ垃圾收集时数据包由JRockit发送到Memory Leak DetectorQ。开销不应该成ZQ何系l的问题——即使是一个全速运行的生中的pȝ?/font>

  起初数目会蟩跃不停,但是一D|间之后它们就会稳定下来,q显C出哪些cȝ数目在增ѝ?/font>

扑ևҎ原因

   有时候知道是哪些cȝ对象在泄漏就以说明问题了。这些类可能只用于代码中的非常有限的部分Q对代码q行一ơ快速检查就可以昄出问题所在。遗憑֜是, 很有可能只有q类信息qƈ不够。例如,常见到泄漏出在类java.lang.String的对象上Q但是因为字W串在整个程序中都用,所以这q没有多? 帮助?/font>

  我们想知道的是,另外q有哪些对象与泄漏对象关联? 在本例中是String。ؓ什么泄漏的对象q存在?哪些对象保留了对q些对象的引用?但是能列出的所有保留对String的引用的对象会非常多,以至? 没有什么实际用处。ؓ了限制数据的数量Q可以将数据按类分组Q以便可以看出其他哪些对象的cM泄漏对象(String)兌。例如,String? Hashtable中是很常见的Q因此我们可能会看到与String兌的Hashtable数据对象。由Hashtable数据倒推Q我们最l可? 扑ֈ与这些数据项有关的Hashtable对象以及StringQ如?所C)?


?. 在工具中看到的类型图的示例视?/font>

倒推

   因ؓ我们仍然是以cȝ对象而不是单独的对象来看待对象,所以我们不知道是哪个Hashtable在泄漏。如果我们可以弄清楚pȝ中所有的 Hashtable都有多大Q我们就可以假定最大的Hashtable是正在泄漏的那一个(因ؓ随着旉的流逝它会篏U泄漏而增长得相当大)。因此,一 份有x有Hashtable对象以及它们引用了多数据的列表Q将会帮助我们指出造成泄漏的确切Hashtabl?


?. 界面QHashtable对象以及它们所引用数据的数量的列表

   对对象引用数据数目的计算开销非常大(需要以该对象作为根遍历引用图)Q如果必d许多对象都这么做Q将会花很多旉。如果了解一点Hashtable 的内部实现原理就可以扑ֈ一条捷径。Hashtable的内部有一个Hashtable数据的数组。该数组随着Hashtable中对象数目的增长而增 ѝ因此,为找出最大的HashtableQ我们只需扑և引用Hashtable数据的最大数l。这栯快很多?


?. 界面Q最大的Hashtable数据Ҏl及其大的清单

更进一?/font>

  当找到发生泄漏的Hashtable实例Ӟ我们可以看到其他哪些实例在引用该HashtableQƈ倒推回去看看是哪个Hashtable在泄漏?/font>


?6. q就是工具中的实例图

  例如Q该Hashtable可能是由MyServercd的对象在名ؓactiveSessions的字D中引用的。这U信息通常p以查找源代码以定位问题所在了?


?. 查对象以及它对其他对象的引用

扑և分配位置

   当跟t内存泄漏问题时Q查看对象分配到哪里是很有用的。只知道它们如何与其他对象相兌Q即哪些对象引用了它们)是不够的Q关于它们在何处创徏的信息也 很有用。当然了Q您q不惛_建应用程序的辅助构gQ以打印每次分配的堆栈跟t?stack trace)。您也不想仅仅ؓ了跟t内存泄漏而在q行应用E序时将一个分析程序连接到生环境中?/font>

   借助于JRockit Memory Leak DetectorQ应用程序中的代码可以在分配时进行动态添加,以创建堆栈跟t。这些堆栈跟t可以在工具中进行篏U和分析。只要不启用׃会因该功能而 生成本,q意味着随时可以q行分配跟踪。当h分配跟踪ӞJRockit ~译器动态插入代码以监控分配Q但是只针对所h的特定类。更好的是,在进行数据分析时Q添加的代码全部被移除,代码中没有留下Q何会引v应用E序性能? 低的更改?


?. CZE序执行期间String的分配的堆栈跟踪

l束?/font>

  内存泄漏是难以发现的。本文重点介l了几种避免内存泄漏的最佛_践,包括要始l记住在数据l构中所攄的内容,以及密切监控内存使用量以发现H然的增ѝ?/font>

   我们都已l看CJRockit Memory Leak Detector是如何用于生产中的系l以跟踪内存泄漏的。该工具使用一U三步式的方法来扑և泄漏。首先,q行势分析Q找出是哪个cȝ对象在泄漏。接? 来,看看有哪些其他的cM泄漏的类的对象相兌。最后,q一步研I单个对象,看看它们是如何互相关联的。也有可能对pȝ中所有对象分配进行动态的堆栈? t。这些功能以及该工具紧密集成到JVM中的Ҏ您可以以一U安全而强大的方式跟踪内存泄漏q进行修复?br />

]]>
Apache commons (?http://www.aygfsteel.com/Duffblog/articles/49201.htmlq球?/dc:creator>q球?/author>Wed, 31 May 2006 03:11:00 GMThttp://www.aygfsteel.com/Duffblog/articles/49201.htmlhttp://www.aygfsteel.com/Duffblog/comments/49201.htmlhttp://www.aygfsteel.com/Duffblog/articles/49201.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/49201.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/49201.html阅读全文

]]>
hibernate hql(?http://www.aygfsteel.com/Duffblog/articles/46883.htmlq球?/dc:creator>q球?/author>Thu, 18 May 2006 12:01:00 GMThttp://www.aygfsteel.com/Duffblog/articles/46883.htmlhttp://www.aygfsteel.com/Duffblog/comments/46883.htmlhttp://www.aygfsteel.com/Duffblog/articles/46883.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/46883.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/46883.html HQL: Hibernate查询语言

Hibernate配备了一U非常强大的查询语言Q这U语a看上d像SQL。但是不要被语法l构 上的怼所qhQHQL是非常有意识的被设计为完全面向对象的查询Q它可以理解如ѝ多?和关联之cȝ概念?

W?5 章 HQL: Hibernate查询语言

Hibernate配备了一U非常强大的查询语言Q这U语a看上d像SQL。但是不要被语法l构 上的怼所qhQHQL是非常有意识的被设计为完全面向对象的查询Q它可以理解如ѝ多?和关联之cȝ概念?

15.1. 大小写敏感性问?/h2>

除了JavacM属性的名称外,查询语句对大写q不敏感?所?

15.2. from子句

Hibernate中最单的查询语句的Ş式如下:

from eg.Cat

该子句简单的q回from Cat

大多数情况下, 你需要指定一?span class="emphasis">别名, 原因是你可能需?在查询语句的其它部分引用?tt class="literal">from Cat as cat

q个语句把别?tt class="literal">from Cat cat

子句中可以同时出现多个类, 其查询结果是产生一个笛卡儿U或产生跨表的连接?

from Formula, Parameter
from Formula as form, Parameter as param

查询语句中别名的开头部分小写被认ؓ是实践中的好习惯Q?q样做与Java变量的命名标准保持了一?(比如Q?tt class="literal">

15.3. 兌(Association)与连?Join)

我们也可以ؓ相关联的实体甚至是对一个集合中的全部元素指定一个别? q时要用关键字from Cat as cat
inner join cat.mate as mate
left outer join cat.kittens as kitten

from Cat as cat left join cat.mate.kittens as kittens
from Formula form full join form.parameter param

受支持的q接cd是从ANSI SQL中借鉴来的?

  • from Cat as cat
    join cat.mate as mate
    left join cat.kittens as kitten

    q有Q一?fetch"q接允许仅仅使用一个选择语句将相关联的对象或一l值的集合随着他们的父对象的初始化而被初始化,q种Ҏ在用到集合 的情况下其有用Q对于关联和集合来说Q它有效的代替了映射文g中的外联?与gq声明(lazy declarationsQ? 查看 W?0.1 ??抓取{略(Fetching strategies) ?/font> 以获得等多的信息?

    from Cat as cat 
    inner join fetch cat.mate
    left join fetch cat.kittens

    一个fetchq接通常不需要被指定别名, 因ؓ相关联的对象不应当被用在 from Document fetch all properties order by name

    from Document doc fetch all properties where lower(doc.name) like '%cats%'

15.4. select子句

select mate
from Cat as cat
inner join cat.mate as mate

该语句将选择select cat.mate from Cat cat

查询语句可以q回gؓMcd的属性,包括q回cd为某U组?Component)的属?

select cat.name from DomesticCat cat
where cat.name like 'fri%'
select cust.name.firstName from Customer as cust

查询语句可以q回多个对象和(或)属性,存放?select mother, offspr, mate.name
from DomesticCat as mother
inner join mother.mate as mate
left outer join mother.kittens as offspr

或存攑֜一?tt class="literal">select new list(mother, offspr, mate.name)
from DomesticCat as mother
inner join mother.mate as mate
left outer join mother.kittens as offspr

也可能直接返回一个实际的cd安全的Java对象,

select new Family(mother, mate, offspr)
from DomesticCat as mother
join mother.mate as mate
left join mother.kittens as offspr

假设c?tt class="literal">select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n
from Cat cat

q种做法在与子句select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
from Cat cat

该查询返回了一?tt class="literal">

15.5. 聚集函数

HQL查询甚至可以q回作用于属性之上的聚集函数的计结?

select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)
from Cat cat

受支持的聚集函数如下Q?

  • select cat.weight + sum(kitten.weight)
    from Cat cat
    join cat.kittens kitten
    group by cat.id, cat.weight

    select firstName||' '||initial||' '||upper(lastName) from Person

    关键?tt class="literal">select distinct cat.name from Cat cat

    select count(distinct cat.name), count(cat) from Cat cat

15.6. 多态查?/h2>

一个如下的查询语句:

from Cat as cat

不仅q回M Java cL接口. 查询会返回承了该类的所有持久化子类 的实例或q回声明了该接口的所有持久化cȝ实例。下面的查询语句q回所有的被持久化的对象:

from java.lang.Object o

接口from Named n, Named m where n.name = m.name

注意Q最后的两个查询需要超q一个的SQL

15.7. where子句

from Cat where name='Fritz'

如果指派了别名,需要用完整的属性名:

from Cat as cat where cat.name='Fritz'

q回名ؓQ属性name{于Q?Fritz'?tt class="literal">select foo
from Foo foo, Bar bar
where foo.startDate = bar.date

返回所有满下面条件的from Cat cat where cat.mate.name is not null

该查询将被翻译成Z个含有表q接Q内q接Q的SQL查询。如果你打算写像q样的查询语?

from Foo foo  
where foo.bar.baz.customer.address.city is not null

在SQL中,你ؓ达此目的需要进行一个四表连接的查询?

from Cat cat, Cat rival where cat.mate = rival.mate

select cat, mate 
from Cat cat, Cat mate
where cat.mate = mate

Ҏ属性(写Q?tt class="literal">from Cat as cat where cat.id = 123

from Cat as cat where cat.mate.id = 69

W二个查询是有效的。此时不需要进行表q接Q?

同样也可以用复合标识符。比?tt class="literal">from bank.Person person
where person.id.country = 'AU'
and person.id.medicareNumber = 123456

from bank.Account account
where account.owner.id.country = 'AU'
and account.owner.id.medicareNumber = 123456

W二个查询也不需要进行表q接?

同样的,Ҏ属?tt class="literal">from Cat cat where cat.class = DomesticCat

你也可以声明一个属性的cd是组件或者复合用L型(以及q件构成的lg{等Q。永q不要尝试用以lgcd来结路径表达式(path-expressionQ?Q与此相反,你应当用组件的一个属性来l尾Q?举例来说Q如?tt class="literal">store.owner.address.city // 正确
store.owner.address // 错误!

一个“Q意”类型有两个Ҏ的属?tt class="literal">from AuditLog log, Payment payment
where log.item.class = 'Payment' and log.item.id = payment.id

注意Q在上面的查询与句中Q?tt class="literal">

15.8. 表达?/h2>

?tt class="literal">

  • 数学q算W?tt class="literal"> from DomesticCat cat where cat.name between 'A' and 'B'

    from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )

    而且否定的格式也可以如下书写Q?

    from DomesticCat cat where cat.name not between 'A' and 'B'
    from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )

    同样, 子句<property name="hibernate.query.substitutions">true 1, false 0</property>

    pȝ该HQL转换为SQL语句Ӟ该设|表明将用字W?from Cat cat where cat.alive = true

    你可以用Ҏ属?tt class="literal">from Cat cat where cat.kittens.size > 0

    from Cat cat where size(cat.kittens) > 0

    对于索引了(有序Q的集合Q你可以使用from Calendar cal where maxelement(cal.holidays) > current date

    from Order order where maxindex(order.items) > 100
    from Order order where minelement(order.items) > 10000

    在传递一个集合的索引集或者是元素?select mother from Cat as mother, Cat as kit
    where kit in elements(foo.kittens)

    select p from NameList list, Person p
    where p.name = some elements(list.names)
    from Cat cat where exists elements(cat.kittens)
    from Player p where 3 > all elements(p.scores)
    from Show show where 'fizard' in indices(show.acts)

    注意Q在Hibernate3U,q些l构变量- from Order order where order.items[0].id = 1234

    select person from Person person, Calendar calendar
    where calendar.holidays['national day'] = person.birthDay
    and person.nationality.calendar = calendar
    select item from Item item, Order order
    where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11
    select item from Item item, Order order
    where order.items[ maxindex(order.items) ] = item and order.id = 11

    ?tt class="literal">select item from Item item, Order order
    where order.items[ size(order.items) - 1 ] = item

    对于一个一对多的关联(one-to-many associationQ或是值的集合中的元素Q?HQL也提供内建的select item, index(item) from Order order
    join order.items item
    where index(item) < 5

    如果底层数据库支持标量的SQL函数Q它们也可以被?

    from DomesticCat cat where upper(cat.name) like 'FRI%'

    如果你还不能Ҏ有的q些׃不疑Q想想下面的查询。如果用SQLQ语句长度会增长多少Q可L会下降多少Q?

    select cust
    from Product prod,
    Store store
    inner join store.customers cust
    where prod.name = 'widget'
    and store.location.name in ( 'Melbourne', 'Sydney' )
    and prod = all elements(cust.currentOrder.lineItems)

    提示: 会像如下的语?

    SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order
    FROM customers cust,
    stores store,
    locations loc,
    store_customers sc,
    product prod
    WHERE prod.name = 'widget'
    AND store.loc_id = loc.id
    AND loc.name IN ( 'Melbourne', 'Sydney' )
    AND sc.store_id = store.id
    AND sc.cust_id = cust.id
    AND prod.id = ALL(
    SELECT item.prod_id
    FROM line_items item, orders o
    WHERE item.order_id = o.id
    AND cust.current_order = o.id
    )

15.9. order by子句

查询q回的列?list)可以按照一个返回的cLlgQcomponents)中的M属性(propertyQ进行排序:

from DomesticCat cat
order by cat.name asc, cat.weight desc, cat.birthdate

可选的

15.10. group by子句

一个返回聚集?aggregate values)的查询可以按照一个返回的cLlgQcomponents)中的M属性(propertyQ进行分l:

select cat.color, sum(cat.weight), count(cat) 
from Cat cat
group by cat.color
select foo.id, avg(name), max(name) 
from Foo foo join foo.names name
group by foo.id

select cat.color, sum(cat.weight), count(cat)
from Cat cat
group by cat.color
having cat.color in (eg.Color.TABBY, eg.Color.BLACK)

如果底层的数据库支持的话(例如不能在MySQL中?QSQL的一般函C聚集函数也可以出??tt class="literal">select cat
from Cat cat
join cat.kittens kitten
group by cat
having avg(kitten.weight) > 100
order by count(kitten) asc, sum(kitten.weight) desc

注意

15.11. 子查?/h2>

对于支持子查询的数据库,Hibernate支持在查询中使用子查询。一个子查询必须被圆括号包围hQ经常是SQL聚集函数的圆括号Q?甚至怺兌的子查询Q引用到外部查询中的别名的子查询Q也是允许的?

from Cat as fatcat 
where fatcat.weight > (
select avg(cat.weight) from DomesticCat cat
)
from DomesticCat as cat 
where cat.name = some (
select name.nickName from Name as name
)
from Cat as cat 
where not exists (
from Cat as mate where mate.mate = cat
)
from DomesticCat as cat 
where cat.name not in (
select name.nickName from Name as name
)

在select列表中包含一个表辑ּ以上的子查询Q你可以使用一个元l构造符Qtuple constructorsQ:

from Cat as cat 
where not ( cat.name, cat.color ) in (
select cat.name, cat.color from DomesticCat cat
)

注意在某些数据库中(不包括Oracle与HSQLQ,你也可以在其他语境中使用元组构造符Q?比如查询用户cd的组件与l合Q?

from Person where name = ('Gavin', 'A', 'King')

该查询等价于更复杂的Q?

from Person where name.first = 'Gavin' and name.initial = 'A' and name.last = 'King')

有两个很好的理由使你不应当作q样的事情:首先Q它不完全适用于各个数据库q_Q其ơ,查询现在依赖于映文件中属性的序?

15.12. HQLCZ

Hibernate查询可以非常的强大与复杂。实际上QHibernate的一个主要卖点就是查询语句的威力。这里有一些例子,它们与我在最q的 一个项目中使用的查询非常相伹{注意你能用到的大多数查询比q些要简单的多!

下面的查询对于某个特定的客户的所有未支付的̎单,在给定给最Mh值的情况下,q回订单的idQ条目的数量和Mh| q回值按照Mh值的l果q行排序。ؓ了决定h|查询使用了当前目录。作{换结果的SQL查询Q用了select order.id, sum(price.amount), count(item)
from Order as order
join order.lineItems as item
join item.product as product,
Catalog as catalog
join catalog.prices as price
where order.paid = false
and order.customer = :customer
and price.product = product
and catalog.effectiveDate < sysdate
and catalog.effectiveDate >= all (
select cat.effectiveDate
from Catalog as cat
where cat.effectiveDate < sysdate
)
group by order
having sum(price.amount) > :minAmount
order by sum(price.amount) desc

q简直是一个怪物Q实际上Q在现实生活中,我ƈ不热衷于子查询,所以我的查询语句看h更像q个Q?

select order.id, sum(price.amount), count(item)
from Order as order
join order.lineItems as item
join item.product as product,
Catalog as catalog
join catalog.prices as price
where order.paid = false
and order.customer = :customer
and price.product = product
and catalog = :currentCatalog
group by order
having sum(price.amount) > :minAmount
order by sum(price.amount) desc

下面一个查询计每一U状态下的支付的数目Q除L有处?tt class="literal">select count(payment), status.name
from Payment as payment
join payment.currentStatus as status
join payment.statusChanges as statusChange
where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
or (
statusChange.timeStamp = (
select max(change.timeStamp)
from PaymentStatusChange change
where change.payment = payment
)
and statusChange.user <> :currentUser
)
group by status.name, status.sortOrder
order by status.sortOrder

如果我把select count(payment), status.name
from Payment as payment
join payment.currentStatus as status
where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUser
group by status.name, status.sortOrder
order by status.sortOrder

下面一个查询用了MS SQL Server?select account, payment
from Account as account
left outer join account.payments as payment
where :currentUser in elements(account.holder.users)
and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
order by account.type.sortOrder, account.accountNumber, payment.dueDate

对于一些数据库Q我们需要弃用(相关的)子选择?

select account, payment
from Account as account
join account.holder.users as user
left outer join account.payments as payment
where :currentUser = user
and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
order by account.type.sortOrder, account.accountNumber, payment.dueDate

15.13. 扚w的UPDATE & DELETE语句

HQL现在支持UPDATE与DELETE语句. 查阅 W?4.3 ?“大扚w更新/删除QBulk update/deleteQ?/font> 以获得更多信息?

15.14. 技?& 窍?/h2>

你可以统计查询结果的数目而不必实际的q回他们Q?

( (Integer) session.iterate("select count(*) from ....").next() ).intValue()

若想Ҏ一个集合的大小来进行排序,可以使用如下的语句:

select usr.id, usr.name
from User as usr
left join usr.messages as msg
group by usr.id, usr.name
order by count(msg)

如果你的数据库支持子选择Q你可以在你的查询的where子句中ؓ选择的大(selection sizeQ指定一个条?

from User usr where size(usr.messages) >= 1

如果你的数据库不支持子选择语句Q用下面的查询Q?

select usr.id, usr.name
from User usr.name
join usr.messages msg
group by usr.id, usr.name
having count(msg) >= 1

因ؓ内连接(inner joinQ的原因Q这个解x案不能返回含有零个信息的select usr.id, usr.name
from User as usr
left join usr.messages as msg
group by usr.id, usr.name
having count(msg) = 0

JavaBean的属性可以被l定C个命名查询(named queryQ的参数上:

Query q = s.createQuery("from foo Foo as foo where foo.name=:name and foo.size=:size");
q.setProperties(fooBean); // fooBean包含ҎgetName()与getSize()
List foos = q.list();

通过接?tt class="literal">Query q = s.createFilter( collection, "" ); // 一个简单的qo?br />q.setMaxResults(PAGE_SIZE);
q.setFirstResult(PAGE_SIZE * pageNumber);
List page = q.list();

通过使用查询qo器(query filterQ可以将集合QCollectionQ的原素分组或排?

Collection orderedCollection = s.filter( collection, "order by this.amount" );
Collection counts = s.filter( collection, "select this.type, count(this) group by this.type" );

不用通过初始化,你就可以知道一个集合(CollectionQ的大小Q?

( (Integer) session.iterate("select count(*) from ....").next() ).intValue();


]]>?Tomcat 上配|虚拟主机(转)http://www.aygfsteel.com/Duffblog/articles/45269.htmlq球?/dc:creator>q球?/author>Tue, 09 May 2006 11:43:00 GMThttp://www.aygfsteel.com/Duffblog/articles/45269.htmlhttp://www.aygfsteel.com/Duffblog/comments/45269.htmlhttp://www.aygfsteel.com/Duffblog/articles/45269.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/45269.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/45269.html Tomcat 支持虚拟L技术,不需要额外的插gQ而且配置单?


一 准备

我们配|两台虚拟主机,假设域名分别?br /> www.sentom1.net
www.sentom2.net
Z试方便Q请在客h?
Win2K:\\WINNT\system32\drivers\etc\hosts
Linux:/etc/hosts
文g中增加下面内容,然后查一下这两个域名是否解析正确?
	192.168.0.1	www.sentom1.net
192.168.0.1 www.sentom2.net

当然Q在生环境中这样做是不行的Q需要的?DNS 上做相应的域名解析?

?Tomcat安装

Tomcat 的安装不在本文的讨论范围Q请参?a target="_blank">q里。请保Tomcat安装正确Q不然请不要l箋q行下面的配|步骤?br />
?tomcat 目录下的 webapps 目录在同一目录复制一份,目录名分?webapps2 Q然后将 webapps 目录改名 ?webapps1 。最?tomcat 的目录结构大致如下:
	tomcat
|--bin
|--common
|--conf
|--logs
|--server
|--shared
......
|--webpapps1
|--webpapps2
|--work

最后,写一个简?html 文g用于试Q文件名?test.html Q文件内容如下:
<HTML>
<HEAD>
<TITLE>试</TITLE>
</HEAD>

<BODY>
<P align="center">你现在访问的?<FONT COLOR="#FF0000">www.sentom1.net</FONT></P>
</BODY>
</HTML>
?test.html 文g分别?tomcat/webapps1/ROOT、tomcat/webapps2/ROOT 目录攄一份,然后? tomcat/webapps2/ROOT/test.html 文g内容中“www.sentom1.net”改为“www.sentom2.net”?br />
xQ前期的准备工作做完了,全是一些体力活?

?配置虚拟L

前面提到了独?IP 和共享的 IP。本文介l的是共享的 IP 模式Q这U模式就是所有的虚拟L都用同一 IP 。目前国?IDC 提供的虚拟主机都是这U模式。这U模式的优点是节U数量有限的 IP Q缺点就是虚拟主 机只能通过域名讉K而不能通过 IP 讉KQ其实也不算是缺点,只对邮gpȝ中用L讉K方式有一点点影响 Q。而另外一U独?IP 模式主要应用在邮件服务中Q这里就不做介绍了?br />
配置 www.sentom1.net 虚拟L

打开 tomcat/conf/server.xml 文gQ将 Host 元素之间的内容全部删掉,然后把下面内容加如到 Host 元素 原来的位|?
    <Host name="www.sentom1.net" debug="0" appBase="webapps1"
unpackWARs="true" autoDeploy="true">

<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="sentom1_access_log." suffix=".txt"
pattern="common" resolveHosts="false"/>

<Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" prefix="sentom1_log." suffix=".txt"
timestamp="true"/>

</Host>
配置 www.sentom2.net 虚拟L

下面内容追加到 Host 元素后面Q注?Host 元素?name 属性和 appBase 属性的值的变化?
    <Host name="www.sentom2.net" debug="0" appBase="webapps2"
unpackWARs="true" autoDeploy="true">

<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="sentom2_access_log." suffix=".txt"
pattern="common" resolveHosts="false"/>

<Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" prefix="sentom2_log." suffix=".txt"
timestamp="true"/>

</Host>
现在可以启动 Tomcat 了,分别讉K
http://www.sentom1.net:8080/test.html
http://www.sentom2.net:8080/test.html
如果讉K得到的页面内容分别是下面的内容,那表明虚拟主机已l配|成功了。否则,h查你的配|过Eƈ 重新按照文档配置?
你现在访问的?www.sentom1.net
你现在访问的?www.sentom2.net

?参?/h3>http://jakarta.apache.org/tomcat/




]]>Java源码分析Q深入探讨Iterator模式http://www.aygfsteel.com/Duffblog/articles/45267.htmlq球?/dc:creator>q球?/author>Tue, 09 May 2006 11:20:00 GMThttp://www.aygfsteel.com/Duffblog/articles/45267.htmlhttp://www.aygfsteel.com/Duffblog/comments/45267.htmlhttp://www.aygfsteel.com/Duffblog/articles/45267.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/45267.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/45267.html正文


java.util包中包含了一pd重要的集合类。本文将从分析源码入手,深入研究一个集合类的内部结构,以及遍历集合的P代模式的源码实现内幕?/p>

下面我们先简单讨Z个根接口CollectionQ然后分析一个抽象类AbstractList和它的对应Iterator接口Qƈ仔细研究q代子模式的实现原理?/p>

本文讨论的源代码版本是JDK 1.4.2Q因为JDK 1.5在java.util中用了很多泛型代码Qؓ了简化问题,所以我们还是讨?.4版本的代码?/p>

集合cȝҎ口Collection


Collection接口是所有集合类的根cd。它的一个主要的接口Ҏ是:

    boolean add(Object c)

add()Ҏ添加一个新元素。注意这个方法会q回一个booleanQ但是返回g是表C添加成功与否。仔l阅读doc可以看到Q? Collection规定Q如果一个集合拒l添加这个元素,无论M原因Q都必须抛出异常。这个返回DC的意义是add()Ҏ执行后,集合的内Ҏ? 改变了(是元素有无数量Q位|等变化Q,q是由具体类实现的。即Q如果方法出错,M抛出异常Q返回g仅表CҎ执行后这个Collection? 内容有无变化?/p>

cM的还有:

    boolean addAll(Collection c);
boolean remove(Object o);
boolean removeAll(Collection c);
boolean remainAll(Collection c);

Object[] toArray()Ҏ很简单,把集合{换成数组q回。Object[] toArray(Object[] a)Ҏ有点复杂了Q首先,q回的Object[]仍然是把集合的所有元素变成的数组Q但是类型和参数a的类型是相同的,比如执行Q?/p>
    String[] o = (String[])c.toArray(new String[0]);

得到的o实际cd是String[]?/p>

其次Q如果参数a的大装不下集合的所有元素,q回的将是一个新的数l。如果参数a的大能装下集合的所有元素,则返回的q是aQ但a的内容用集合的元素来填充。尤其要注意的是Q如果a的大比集合元素的个数还多,a后面的部分全部被|ؓnull?/p>

最后一个最重要的方法是iterator()Q返回一个IteratorQP代子Q,用于遍历集合的所有元素?/p>

用Iterator模式实现遍历集合


Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合cM抽象出来Q从而避免向客户端暴露集合的内部l构?/p>

例如Q如果没有用IteratorQ遍历一个数l的Ҏ是用烦引:

    for(int i=0; i<array.size(); i++) { ... get(i) ... }

而访问一个链表(LinkedListQ又必须使用while循环Q?/p>
    while((e=e.next())!=null) { ... e.data() ... }

以上两种Ҏ客户端都必须事先知道集合的内部结构,讉K代码和集合本w是紧耦合Q无法将讉K逻辑从集合类和客L代码中分d来,每一U集合对应一U遍历方法,客户端代码无法复用?/p>

更恐怖的是,如果以后需要把ArrayList更换为LinkedListQ则原来的客L代码必须全部重写?/p>

决以上问题,Iterator模式L用同一U逻辑来遍历集合:

    for(Iterator it = c.iterater(); it.hasNext(); ) { ... }

奥秘在于客户端自w不l护遍历集合?指针"Q所有的内部状态(如当前元素位|,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂Ҏ生成Q因此,它知道如何遍历整个集合?/p>

客户端从不直接和集合cL交道Q它L控制IteratorQ向它发?向前"Q?向后"Q?取当前元?的命令,可以间接遍历整个集合?/p>

首先看看java.util.Iterator接口的定义:

    public interface Iterator {
boolean hasNext();
Object next();
void remove();
}

依赖前两个方法就能完成遍历,典型的代码如下:

    for(Iterator it = c.iterator(); it.hasNext(); ) {
Object o = it.next();
// 对o的操?..
}

在JDK1.5中,q对上面的代码在语法上作了简化:

    // Type是具体的cdQ如String?br />    for(Type t : c) {
// 对t的操?..
}

每一U集合类q回的Iterator具体cd可能不同QArray可能q回ArrayIteratorQSet可能q回SetIteratorQ? Tree可能q回TreeIteratorQ但是它们都实现了Iterator接口Q因此,客户端不兛_到底是哪UIteratorQ它只需要获得这? Iterator接口卛_Q这是面向对象的威力?/p>

Iterator源码剖析


让我们来看看AbstracyList如何创徏Iterator。首先AbstractList定义了一个内部类Qinner classQ:

    private class Itr implements Iterator {
...
}

而iterator()Ҏ的定义是Q?/p>
    public Iterator iterator() {
return new Itr();
}

因此客户端不知道它通过Iterator it = a.iterator();所获得的Iterator的真正类型?/p>

现在我们兛_的是q个x为private的ItrcL如何实现遍历AbstractList的:

    private class Itr implements Iterator {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
}

ItrcM?个int变量Q还有一个隐含的AbstractList的引用)来实现遍历,cursor是下一ơnext()调用时元素的位置Q第一ơ调用next()返回烦引ؓ0的元素。lastRet记录上一ơ游标所在位|,因此它L比cursor??/p>

变量cursor和集合的元素个数军_hasNext()Q?/p>
    public boolean hasNext() {
return cursor != size();
}

Ҏnext()q回的是索引为cursor的元素,然后修改cursor和lastRet的|

    public Object next() {
checkForComodification();
try {
Object next = get(cursor);
lastRet = cursor++;
return next;
} catch(IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}

expectedModCount表示期待的modCount|用来判断在遍历过E中集合是否被修改过。AbstractList包含一? modCount变量Q它的初始值是0Q当集合每被修改一ơ时Q调用addQremove{方法)QmodCount?。因此,modCount如果? 变,表示集合内容未被修改?/p>

Itr初始化时用expectedModCount记录集合的modCount变量Q此后在必要的地方它会检modCount的|

    final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}

如果modCount与一开始记录在expectedModeCount中的g{,说明集合内容被修改过Q此时会抛出ConcurrentModificationException?/p>

q个ConcurrentModificationException是RuntimeExceptionQ不要在客户端捕获它。如果发生此异常Q说明程序代码的~写有问题,应该仔细查代码而不是在catch中忽略它?/p>

但是调用Iterator自n的remove()Ҏ删除当前元素是完全没有问题的Q因为在q个Ҏ中会自动同步expectedModCount和modCount的|

    public void remove() {
...
AbstractList.this.remove(lastRet);
...
// 在调用了集合的remove()Ҏ之后重新讄了expectedModCountQ?br /> expectedModCount = modCount;
...
}

要确保遍历过E顺利完成,必须保证遍历q程中不更改集合的内容(Iterator的remove()Ҏ除外Q,因此Q确保遍历可靠的原则是只在一个线E中使用q个集合Q或者在多线E中寚w历代码进行同步?/p>

最后给个完整的CZQ?/p>
    Collection c = new ArrayList();
c.add("abc");
c.add("xyz");
for(Iterator it = c.iterator(); it.hasNext(); ) {
String s = (String)it.next();
System.out.println(s);
}

如果你把W一行代码的ArrayList换成LinkedList或VectorQ剩下的代码不用改动一行就能编译,而且功能不变Q这是针对抽象~程的原则:对具体类的依赖性最?/p>

/**********************************************************************

q个是比较满意的答案了?br />



]]>
异常Qjava.util.ConcurrentModificationExceptionhttp://www.aygfsteel.com/Duffblog/articles/45266.htmlq球?/dc:creator>q球?/author>Tue, 09 May 2006 11:19:00 GMThttp://www.aygfsteel.com/Duffblog/articles/45266.htmlhttp://www.aygfsteel.com/Duffblog/comments/45266.htmlhttp://www.aygfsteel.com/Duffblog/articles/45266.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/45266.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/45266.html
/*********************************************************************************

在Map或者Collection的时候,不要用它们的API直接修改集合的内容,如果要修改可以用Iterator的remove()ҎQ例如:

    public void setReparation( Reparation reparation ) {
        for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations为Collection
            Reparation repa = (Reparation)it.next();
            if (repa.getId() == reparation.getId()){
                this.reparations.remove(repa);
                this.reparations.add(reparation);
            }
        }
   }

如上写会在运行期报ConcurrentModificationExceptionQ可以如下修改:

    public void setReparation( Reparation reparation ) {
        boolean flag = false;
        for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations为Collection
            Reparation repa = (Reparation)it.next();
            if (repa.getId() == reparation.getId()){
                it.remove();
                flag = true;
                break;
            }
        }
        if(flag){
          this.reparations.add(reparation);
        }
    }

具体可以参考:http://gceclub.sun.com.cn/yuanchuang/week-14/iterator.html

*******************************************************************************/


深入探讨Iterator模式Q见下一?/h4>




]]>
?Eclipse Workbench 之外使用 Eclipse GUIQ第 1 部分: 单独使用 JFace ?SWThttp://www.aygfsteel.com/Duffblog/articles/43415.htmlq球?/dc:creator>q球?/author>Wed, 26 Apr 2006 13:26:00 GMThttp://www.aygfsteel.com/Duffblog/articles/43415.htmlhttp://www.aygfsteel.com/Duffblog/comments/43415.htmlhttp://www.aygfsteel.com/Duffblog/articles/43415.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/43415.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/43415.html阅读全文

]]>
JavadFile的问?http://www.aygfsteel.com/Duffblog/articles/39254.htmlq球?/dc:creator>q球?/author>Tue, 04 Apr 2006 13:17:00 GMThttp://www.aygfsteel.com/Duffblog/articles/39254.htmlhttp://www.aygfsteel.com/Duffblog/comments/39254.htmlhttp://www.aygfsteel.com/Duffblog/articles/39254.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/39254.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/39254.html我想要读取某一个\径下,文g最后修改的旉大于我给定的所有的文g.
比如是E:\file
我想要等C部分的file,x文g最后修改的旉大于我给定的
我目前的做法?
查看所有的File,一一比对,得到我想要的File
//read path
Vector needReadFile = new Vector();
Date fileDate = new Date();
File[] files = new File(readFilePath).listFiles();
if (files == null) {
continue;
}
for (int x = 0; x < files.length; x++) {
File tempFile = files[x];
Date fileDate = new Date(tempFile.
lastModified());
if (fileDate.compare(lastModifyDate) == 1 ) {
needReadFile.add(readFilePath + File.separator +
tempFile.getName());
}
} //end for(int i = 0 ; i< files.length ; i++)

虽然q样做是可以辑ֈ,当我的File很多的时?效率很差?br />
效率好一点的ҎQ?br />
看看listFiles()和listFiles(FileFilter filter) 的源代码

public File[] listFiles() {
String[] ss = list();
if (ss == null) return null;
int n = ss.length;
File[] fs = new File[n];
for (int i = 0; i < n; i++) {
fs[i] = new File(this.path, ss[i]);
}
return fs;
}

public File[] listFiles(FileFilter filter) {
String ss[] = list();
if (ss == null) return null;
ArrayList v = new ArrayList();
for (int i = 0 ; i < ss.length ; i++) {
File f = new File(this.path, ss[i]);
if ((filter == null) || filter.accept(f)) {
v.add(f);
}
}
return (File[])(v.toArray(new File[0]));
}

采用W二个方法以?只需要遍历一?而且代码更清?
采用W一个方?你取得列表以后还需要遍历一遍过滤掉不符合条件的.

File[] files = new File(readFilePath).listFiles(new FileFilter(){
public boolean accept(File pathname){
//.判断修改日期,W合条gq回true;否则false;

}});

q里采用匿名c?实现一个FileFilter,你要修改qo的逻辑,只需要修改accept()Ҏ是?当然,你也可以专门写一个类比如

class FileModifyDateFilter implements FileFilter{
private Date baseDate = null;
public FileModifyDateFilter(Date d) {
baseDate = d;
}

public boolean accept(File f) {
if (baseDate == null)
return true;
if (f.lastModified() > baseDate.getTime())
return true;

return false;
}
}


原文来自Q?a >http://www.jdon.com/jive/thread.jsp?forum=16&thread=22478&message=13169392


]]>java源代码分?---jvm.dll装蝲q程http://www.aygfsteel.com/Duffblog/articles/39245.htmlq球?/dc:creator>q球?/author>Tue, 04 Apr 2006 12:32:00 GMThttp://www.aygfsteel.com/Duffblog/articles/39245.htmlhttp://www.aygfsteel.com/Duffblog/comments/39245.htmlhttp://www.aygfsteel.com/Duffblog/articles/39245.html#Feedback0http://www.aygfsteel.com/Duffblog/comments/commentRss/39245.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/39245.htmlhttp://www.matrix.org.cn

摘要:

众所周知java.exe是java class文g的执行程序,但实际上java.exeE序只是一个执行的外壳Q它会装载jvm.dllQwindows下,以下皆以windowsq_ZQ?linux下和solaris下其实类|为:libjvm.soQ,q个动态连接库才是java 虚拟机的实际操作处理所在。本文探Ijava.exeE序是如何查扑֒装蝲jvm.dll 动态库Qƈ调用它进行class文g执行处理?

q?br />众所周知java.exe是java class文g的执行程序,但实际上java.exeE序只是
一个执行的外壳Q它会装载jvm.dllQwindows下,以下皆以windowsq_ZQ?br />linux下和solaris下其实类|为:libjvm.soQ,q个动态连接库才是java
虚拟机的实际操作处理所在。本文探Ijava.exeE序是如何查扑֒装蝲jvm.dll
动态库Qƈ调用它进行class文g执行处理的?br />
源代?/b>
本文分析之代码,《JavaTM 2 SDK, Standard Edition, v1.4.2 fcs
Community Source Release》,可从sun官方|站下蝲Q主要分析的源代码ؓQ?br />j2se\src\share\bin\java.c
j2se\src\windows\bin\java_md.c

java.c是什么东?/b>
‘javaE序’源代码
所谓‘javaE序’,包括jdk中的java.exe\javac.exe\javadoc.exeQjava.c?br />代码中通过JAVA_ARGS宏来控制生成的代码,如果该宏没定义则~译文g控制?br />成java.exe否则~译文g控制生成其他的‘javaE序’?br />比如Q?br />j2se\make\java\javac\MakefileQ这是javac~译文gQ中Q?br />$(CD) ../../sun/javac ; $(MAKE) $@ RELEASE=$(RELEASE) FULL_VERSION=$(FULL_VERSION)
j2se\make\sun\javac\javac\MakefileQ由上面Makefile文g调用Q中Q?br />JAVA_ARGS = "{ \"-J-ms8m\", \"com.sun.tools.javac.Main\" }"
则由同一份java.c代码生成的javac.exeE序׃直接调用javacL法:
com.sun.tools.javac.MainQ这样其执行v来就像是直接q行的一个exe文gQ?br />而未定义JAVA_ARGS的java.exeE序则会调用传递过来参C的类Ҏ?br />
从java.c的main入口函数说v
main()函数中前面一Dؓ重新分配参数指针的处理?br />然后调用函数QCreateExecutionEnvironmentQ该函数主要查找javaq行环境?br />目录Q和jvm.dllq个虚拟机核心动态连接库文g路径所在。根据操作系l不同,
该函数有不同实现版本Q但大体处理逻辑相同Q我们看看windowsq_该函数的?br />理(j2se\src\windows\bin\java_md.cQ?br />
CreateExecutionEnvironment函数主要分ؓ三步处理Q?br />a、查找jre路径?br />b、装载jvm.cfg中指定的虚拟机动态连接库Qjvm.dllQ参数?br />c、取jvm.dll文g路径?br />
实现Q?br />a、查找jre路径是通过java_md.c中函敎ͼGetJREPath实现的?br />该函数首先调用GetApplicationHome函数QGetApplicationHome函数调用windows
API函数GetModuleFileName取java.exeE序的绝对\径,以我的jdk安装路径ZQ?br />为:“D:\java\j2sdk1.4.2_04\bin\java.exe”,然后L文g名取l对路径为:
“D:\java\j2sdk1.4.2_04\bin”,之后会在L最后一U目录,现在l对路径为:
“D:\java\j2sdk1.4.2_04”?br />然后GetJREPath函数l箋判断刚刚取的路径+\bin\java.dlll合成的q个java.dll
文g是否存在Q如果存在则“D:\java\j2sdk1.4.2_04”ؓJRE路径Q否则判断取?br />的“D:\java\j2sdk1.4.2_04”\?\jre\bin\java.dll文g是否存在Q存在则
“D:\java\j2sdk1.4.2_04\jre”ؓJRE路径。如果上面两U情况都不存在,则从?br />册表中去查找Q参见函数GetPublicJREHomeQ?br />
函数QGetPublicJREHome先查?br />HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\CurrentVersion
键值“当前JRE版本号”,判断“当前JRE版本号”是否ؓ1.4做ؓ版本P如果是则
取HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\“当前JRE版本号?br />\JavaHome的\径所在ؓJRE路径?br />
我的JDKq回的JRE路径为:“D:\java\j2sdk1.4.2_04\jre”?br />
b、装载jvm.cfg虚拟机动态连接库配置文g是通过java.c中函?ReadKnownVMs实现
的?br />该函数首先组合jvm.cfg文g的绝对\径,JRE路径+\lib+\ARCHQCPU构架Q?\jvm.cfg
ARCHQCPU构架Q的判断是通过java_md.c中GetArch函数判断的,该函Cwindowsq?br />台只有两U情况:WIN64的‘ia64’,其他情况都ؓ‘i386’。我的ؓi386所以jvm.cfg
文gl对路径为:“D:\java\j2sdk1.4.2_04\jre\lib\i386\jvm.cfg”。文件内容如
下:
#
# @(#)jvm.cfg        1.7 03/01/23
#
# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
#
#
#
#
# List of JVMs that can be used as an option to java, javac, etc.
# Order is important -- first in this list is the default JVM.
# NOTE that this both this file and its format are UNSUPPORTED and
# WILL GO AWAY in a future release.
#
# You may also select a JVM in an arbitrary location with the
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
# and may not be available in a future release.
#
-client KNOWN
-server KNOWN
-hotspot ALIASED_TO -client
-classic WARN
-native ERROR
-green ERROR


Q如果细心的话,我们会发现在JDK目录中我的ؓQ“D:\java\j2sdk1.4.2_04\jre\bin\client”和“D:\java\j2sdk1.4.2_04\jre\bin\server”两个目录下都存在jvm.dll文g。而java正是通过jvm.cfg配置文g来管理这些不同版本的jvm.dll的。)

ReadKnownVMs函数会将该文件中的配|内容读入到一个JVM配置l构的全局变量中,该函数首先蟩q注释(以?’开始的行)Q然后读取以?’开始的行指定的jvm参数Q每一行ؓ一个jvm信息Q第一部分为jvm虚拟机名UͼW二部分为配|参敎ͼ比如行:
?client KNOWN”则?client”ؓ虚拟机名Uͼ而“KNOWN”ؓ配置cd参数Q“KNOWN?br />表示该虚拟机的jvm.dll存在Q而“ALIASED_TO”表CZؓ另一个jvm.dll的别名,“WARN?br />表示该虚拟机的jvm.dll不存在但q行时会用其他存在的jvm.dll替代执行Q而“ERROR?br />同样表示该类虚拟机的jvm.dll不存在且q行时不会找存在的jvm.dll替代而直接抛出错?br />信息?br />
在运行javaE序时指定用那个虚拟机的判断是由java.c中函敎ͼCheckJvmType判断Q该函数会检查javaq行参数中是否有指定jvm的参敎ͼ然后从ReadKnownVMs函数d的jvm.cfg数据l构中去查找Q从而指定不同的jvmcdQ最l导致装载不同jvm.dllQ。有两种Ҏ可以指定jvmcdQ一U按照jvm.cfg文g中的jvm名称指定Q第二种Ҏ是直接指定,它们执行的方法分别是“java -J<jvm.cfg中jvm名称>”、“java -XXaltjvm=<jvmcd名称>”或“java -J-XXaltjvm=<jvmcd名称>”。如果是W一U参C递方式,CheckJvmType函数会取参数?J’后面的jvm名称Q然后从已知的jvm配置参数中查扑֦果找到同名的则去掉该jvm名称前的?’直接返回该|而第二种ҎQ会直接q回?XXaltjvm=”或?J-XXaltjvm=”后面的jvmcd名称Q如果在q行java时未指定上面两种Ҏ中的M一U参敎ͼCheckJvmType会取配置文g中第一个配|中的jvm名称Q去掉名U前面的?’返回该倹{CheckJvmType函数的这个返回g在下面的函数中汇同jre路径l合成jvm.dll的绝对\径?br />
比如Q如果在q行javaE序时用“java -J-client test”则ReadKnownVMs会读取参数?client”然后查找jvm.cfgd的参C是否有jvm名称为?client”的Q如果有则去掉jvm名称前的?”直接返回“client”;而如果在q行javaE序时用如下参敎ͼ
“java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\client test”,则ReadKnownVMs
会直接返回“D:\java\j2sdk1.4.2_04\jre\bin\client”;如果不带上面参数执行如:
“java test”,因ؓ在jvm.cfg配置文g中第一个存在的jvm为?client”,所以函?br />ReadKnownVMs也会Ljvm名称前的?”返回“client”。其实这三中情况都是使用?br />“D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll”这个jvm动态连接库处理testq个class的,见下面GetJVMPath函数?br />
c、取jvm.dll文g路径是通过java_md.c中函敎ͼGetJVMPath实现的?br />׃面两步我们已l获得了JRE路径和jvm的类型字W串。GetJVMPath函数判断CheckJvmType
q回的jvmcd字符串中是否包含了‘\’或?’如果包含则以该jvmcd字符?\jvm.dll作ؓJVM的全路径Q否则以JRE路径+\bin+\jvmcd字符?\jvm.dll作ؓJVM的全路径?br />
看看上面的例子,W一U情况“java -J-client test”jvm.dll路径为:
JRE路径+\bin+\jvmcd字符?\jvm.dll 按照我的JDK路径则ؓQ?br />“D:\java\j2sdk1.4.2_04\jre?“\bin?“\client?“\jvm.dll”?br />W二U情况“java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\client test”\径ؓQ?br />jvmcd字符?\jvm.dll即ؓQ“D:\java\j2sdk1.4.2_04\jre\bin\client?“\jvm.dll?br />W三U情况“java test”ؓQ“D:\java\j2sdk1.4.2_04\jre?“\bin?“\client?br />+“\jvm.dll”与情况一相同。所以这三种情况都是调用的jvm动态连接库“D:\java\
j2sdk1.4.2_04\jre\bin\client\jvm.dll”处理testcȝ?br />
我们来进一步验证一下:
打开cmd控制収ͼ

讄java装蝲调试
E:\work\java_research>set _JAVA_LAUNCHER_DEBUG=1
情况一
E:\work\java_research>java -J-client test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is D:\java\j2sdk1.4.2_04\jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] = ->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] = ->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] = ->-green<-
299 micro seconds to parse jvm.cfg
JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll
2897 micro seconds to LoadJavaVM
JavaVM args:
    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2
    option[ 0] = '-Djava.class.path=.'
    option[ 1] = '-Dsun.java.command=test.ScanDirectory'
50001 micro seconds to InitializeJVM
Main-Class is 'test.ScanDirectory'
Apps' argc is 0
10208 micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java test.ScanDirectory DIR [output file]
情况?br />E:\work\java_research>java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\client test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is D:\java\j2sdk1.4.2_04\jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] = ->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] = ->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] = ->-green<-
386 micro seconds to parse jvm.cfg
JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll
2795 micro seconds to LoadJavaVM
JavaVM args:
    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2
    option[ 0] = '-Djava.class.path=.'
    option[ 1] = '-Dsun.java.command=test.ScanDirectory'
49978 micro seconds to InitializeJVM
Main-Class is 'test.ScanDirectory'
Apps' argc is 0
9598 micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java test.ScanDirectory DIR [output file]
情况?br />E:\work\java_research>java test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is D:\java\j2sdk1.4.2_04\jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] = ->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] = ->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] = ->-green<-
381 micro seconds to parse jvm.cfg
JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll
3038 micro seconds to LoadJavaVM
JavaVM args:
    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2
    option[ 0] = '-Djava.class.path=.'
    option[ 1] = '-Dsun.java.command=test.ScanDirectory'
50080 micro seconds to InitializeJVM
Main-Class is 'test.ScanDirectory'
Apps' argc is 0
10215 micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java test.ScanDirectory DIR [output file]
三个的JVM路径都ؓQ?br />JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll

其他情况
E:\work\java_research>java -J-server test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is D:\java\j2sdk1.4.2_04\jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] = ->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] = ->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] = ->-green<-
377 micro seconds to parse jvm.cfg
JVM path is D:\java\j2sdk1.4.2_04\jre\bin\server\jvm.dll
2985 micro seconds to LoadJavaVM
JavaVM args:
    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2
    option[ 0] = '-Djava.class.path=.'
    option[ 1] = '-Dsun.java.command=test.ScanDirectory'
62382 micro seconds to InitializeJVM
Main-Class is 'test.ScanDirectory'
Apps' argc is 0
12413 micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java test.ScanDirectory DIR [output file]
E:\work\java_research>java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\server test.ScanDirectory
----_JAVA_LAUNCHER_DEBUG----
JRE path is D:\java\j2sdk1.4.2_04\jre
jvm.cfg[0] = ->-client<-
jvm.cfg[1] = ->-server<-
jvm.cfg[2] = ->-hotspot<-
jvm.cfg[3] = ->-classic<-
jvm.cfg[4] = ->-native<-
jvm.cfg[5] = ->-green<-
376 micro seconds to parse jvm.cfg
JVM path is D:\java\j2sdk1.4.2_04\jre\bin\server\jvm.dll
2937 micro seconds to LoadJavaVM
JavaVM args:
    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2
    option[ 0] = '-Djava.class.path=.'
    option[ 1] = '-Dsun.java.command=test.ScanDirectory'
62725 micro seconds to InitializeJVM
Main-Class is 'test.ScanDirectory'
Apps' argc is 0
8942 micro seconds to load main class
----_JAVA_LAUNCHER_DEBUG----
usage: java test.ScanDirectory DIR [output file]

׃面可以看出,如果我们安装了多个jdk或jre版本的话Q用“java -XXaltjvm=?br />可以通过l对路径指定到其他版本的jvm.dll上去Q至于能不能q行q有待测试?br />
我们下面回到java.c的main函数中看看上面找到的jvm.dll是如何装载挂接执行的?br />
该操作大致分Z步:
a、装载jvm.dll动态连接库?br />b、初始化jvm.dllq挂接到JNIEnvQJNI调用接口Q实例?br />c、调用JNIEnv实例装蝲q处理classcR?br />
实现Q?br />a、装载jvm.dll动态连接库是由main函数调用java_md.c中LoadJavaVM函数实现的?br />main函数首先构造了一个InvocationFunctionsl构的局部变量,InvocationFunctions
l构有两个函数指针:
typedef struct {
    CreateJavaVM_t CreateJavaVM;
    GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
} InvocationFunctions;

函数LoadJavaVM中先调用windows API函数QLoadLibrary装蝲jvm.dll动态连接库Q?br />之后jvm.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs
挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数
指针变量上。jvm.dll的装载工作宣告完成?br />
b、初始化jvm.dllq挂接到JNIEnvQJNI调用接口Q实例是通过java.c中函敎ͼ
InitializeJVM完成的?br />mainҎ中首先定义了一个JNIEnvl构的指针,JNIEnvl构中定义了许多与装载class
cL件、查扄Ҏ、调用类Ҏ有关的函数指针变量。InitializeJVM会调用上?br />以挂接jvm.dll中JNI_CreateJavaVM的InvocationFunctionsl构变量的CreateJavaVMҎQ即调用jvm.dll中函数JNI_CreateJavaVMQ该函数会将JNIEnvl构的实例返回到main中的JNIEnvl构的指针上。这样main中的JNIEnv指针获取了JNIEnv实例后,可以开始对class文gq行处理了?br />
c、调用JNIEnv实例装蝲q处理classcR?br />a)如果是执行jar包?br />如果执行的是一个jar包的话,main函数会调用java.c中的函数QGetMainClassNameQ该函数使用JNIEnv实例构造ƈ调用javac:java.util.jar.JarFile中方法getManifest()q从q回的Manifest对象中取getAttributes("Main-Class")的|即jar包中文gQ?br />META-INF/MANIFEST.MF指定的Main-Class的主cd作ؓq行的主cR?br />之后main函数会调用java.c中LoadClassҎ装蝲该主c(使用JNIEnv实例的FindClassQ?br />b)如果是执行classҎ?br />main函数直接调用java.c中LoadClassҎ装蝲该类?br />
然后main函数调用JNIEnv实例的GetStaticMethodIDҎ查找装蝲的classȝ?br />“public static void main(String[] args)”方法,q判断该Ҏ是否为publicҎQ然后调用JNIEnv实例的CallStaticVoidMethodҎ调用该javacȝmainҎ?br />
ȝ
׃面的代码分析可以看出几个问题?br />a、ؓ什么JDK和JRE不一定通过安装Q直接拷到硬盘上Q设|path环境变量可以执行。因为javaq行获取jre路径的首选方法正是直接通过获取java.exel对路径来判断的Q如果通过修改注册表选项而不讄path环境变量也可以找到jre路径所在。修Ҏ法如下:
首先我们java.exe拷到L目录下,我的拷到e:\temp下,在cmd中运行:
清空path环境变量
E:\temp>set path=
E:\temp>java
Error opening registry key 'Software\JavaSoft\Java Runtime Environment'
Error: could not find java.dll
Error: could not find Java 2 Runtime Environment.

导入如下注册表文Ӟjava.regQ?br />
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft]

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment]
"CurrentVersion"="1.4"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.4]
"JavaHome"="D:\\java\\j2sdk1.4.2_04\\jre"


再执行显C执行正常,如下Q?br />
E:\temp>java
Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)

where options include:
    -client       to select the "client" VM
    -server       to select the "server" VM
    -hotspot      is a synonym for the "client" VM  [deprecated]
                  The default VM is client.

    -cp <class search path of directories and zip/jar files>
    -classpath <class search path of directories and zip/jar files>
                  A ; separated list of directories, JAR archives,
                  and ZIP archives to search for class files.
    -D<name>=<value>
                  set a system property
    -verbose[:class|gc|jni]
                  enable verbose output
    -version      print product version and exit
    -showversion  print product version and continue
    -? -help      print this help message
    -X            print help on non-standard options
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  enable assertions
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  disable assertions
    -esa | -enablesystemassertions
                  enable system assertions
    -dsa | -disablesystemassertions
                  disable system assertions

b、java.exe是通过jvm.cfg文g或直接指定jvm.dll路径来装载执行javaE序的?br />见上面例子?br />c、不同实现版本的jvm.dll必然存在一个名为:JNI_CreateJavaVM的导出函敎ͼ
java.exe正是通过调用该函数获得JNIEnv调用接口来装载执行classcȝ。这?br />函数也是我们下一步研Ijava vm实作技巧的研究出发炏V?br />JNI_CreateJavaVM函数位于Qhotspot\src\share\vm\prims\jni.cpp文g中?br />
原文q接地址Q?a >http://www.matrix.org.cn/resource/article/1/1650_jvm_loading_progress.html





]]>
如何正确地应用Runtimec调用程?http://www.aygfsteel.com/Duffblog/articles/39244.htmlq球?/dc:creator>q球?/author>Tue, 04 Apr 2006 12:27:00 GMThttp://www.aygfsteel.com/Duffblog/articles/39244.htmlhttp://www.aygfsteel.com/Duffblog/comments/39244.htmlhttp://www.aygfsteel.com/Duffblog/articles/39244.html#Feedback1http://www.aygfsteel.com/Duffblog/comments/commentRss/39244.htmlhttp://www.aygfsteel.com/Duffblog/services/trackbacks/39244.html 用Java~写应用Ӟ有时需要在E序中调用另一个现成的可执行程序或pȝ命oQ这时可以通过l合使用Java提供的RuntimecdProcesscȝҎ实现。下面是一U比较典型的E序模式Q?
...
Process process = Runtime.getRuntime().exec(".\\p.exe");
process.waitfor( );
...
在上面的E序中,W一行的?\\p.exe”是要执行的E序名,Runtime.getRuntime()q回当前应用E序的Runtime对象Q该对象的exec()Ҏ指示Java虚拟机创Z个子q程执行指定的可执行E序Qƈq回与该子进E对应的Process对象实例。通过Process可以控制该子q程的执行或获取该子q程的信息。第二条语句的目的等待子q程完成再往下执行?
但在windowsq_上,如果处理不当Q有时ƈ不能得到预期的结果。下面是W者在实际~程中ȝ的几U需要注意的情况Q?
1、执行DOS的内部命?
如果要执行一条DOS内部命oQ有两种Ҏ。一U方法是把命令解释器包含在exec()的参C。例如,执行dir命oQ在NT上, 可写成exec("cmd.exe /c dir")Q在windows 95/98下,可写成“command.exe /c dir”,其中参数?c”表C命令执行后关闭Dos立即关闭H口。另一U方法是Q把内部命o攑֜一个批命omy_dir.bat文g中,在JavaE序中写成exec("my_dir.bat")。如果仅仅写成exec("dir")QJava虚拟机则会报q行旉误。前一U方法要保证E序的可UL性,需要在E序中读取运行的操作pȝq_Q以调用不同的命令解释器。后一U方法则不需要做更多的处理?
2、打开一个不可执行的文g
打开一个不可执行的文gQ但该文件存在关联的应用E序Q则可以有两U方式?以打开一个word文档a.doc文gZQJava中可以有以下两种写法Q?
exec("start .\\a.doc");
exec(" c:\\Program Files\\Microsoft Office\\office\\winword.exe .\\a.doc");
昄Q前一U方法更为简hѝ?
3、执行一个有标准输出的DOS可执行程?
在windowsq_上,q行被调用程序的DOSH口在程序执行完毕后往往q不会自动关闭,从而导致Java应用E序d在waitfor( )。导致该现象的一个可能的原因是,该可执行E序的标准输出比较多Q而运行窗口的标准输出~冲Z够大。解决的办法是,利用Java提供的ProcesscL供的Ҏ让Java虚拟机截莯调用E序的DOSq行H口的标准输出,在waitfor()命o之前dH口的标准输出缓冲区中的内容。一D典型的E序如下Q?
...
String ls_1;
Process process = Runtime.getRuntime().exec("cmd /c dir \\windows");
BufferedReader bufferedReader = new BufferedReader( \
new InputStreamReader(process.getInputStream());
while ( (ls_1=bufferedReader.readLine()) != null)
System.out.println(ls_1);
?
process.waitfor( );

l束?br />
我自己有试q。需要小的修改。我的代码如下:

import java.io.IOException;

public class TestProcess {

 /**
  * @param args
  */
 public static void main(String[] args) {
  System.out.println("runtime~~~~");
  ProcessExec p = new ProcessExec();
  int i = 2;
  try{
   i = p.process11();
  }catch(IOException e){
   
  }
  System.out.println(i);
 }
 
}

class ProcessExec{
 public int process11() throws IOException{
//  Process process = Runtime.getRuntime().exec("C:/Program Files/Outlook Express/msimn.exe");
  Process process = Runtime.getRuntime().exec("cmd.exe /c");
//  Process process = Runtime.getRuntime().exec("C:/WINDOWS/system32/cmd.exe");
  int i=4;
  try{
   i = process.waitFor();
  }catch(InterruptedException e){
   i=3;
  }
  return i;
 }
}





]]>
վ֩ģ壺 ͷ| | | | | ʡ| | | | ʡ| Ѱ| ɽ| տ| | | ¡| | | żҿ| ߴ| կ| ˲| | ԫ| | ɽ| Ͽ| ʻ| | ϻ| | ̩| ƺ| | | | | | ׯ| ɽ| |