﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Duffblog-文章分类-Java</title><link>http://www.blogjava.net/Duffblog/category/9507.html</link><description>前进一步，看看，需要前进更大一步才可以。</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 03:56:57 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 03:56:57 GMT</pubDate><ttl>60</ttl><item><title>算术表达式的计算（转）</title><link>http://www.blogjava.net/Duffblog/articles/87811.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Thu, 14 Dec 2006 12:46:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/87811.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/87811.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/87811.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/87811.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/87811.html</trackback:ping><description><![CDATA[ 在计算机中进行算术表达式的计算是通过栈来实现的。这一节首先讨论算术表达式的两种表示方法，即中缀表示法和后缀表示法，接着讨论后缀表达式求值的算法，最后讨论中缀表达式转换为后缀表达式的算法。<br />1. 算术表达式的两种表示<br />通常书写的算术表达式是由操作数(又叫运算对象或运算量)和运算符以及改变运算次序的圆括号连接而成的式子。操作数可以是常量、变量和函数，同时还可以是表达式。运算符包括单目运算符和双目运算符两类，单目运算符只要求一个操作数，并被放在该操作数的前面，双目运算符要求有两个操作数，并被放在这两个操作数的中间。单目运算符为取正’+’和取负’-’，双目运算符有加’+’,减’-’,乘’*’和除’/’等。为了简便起见，在我们的讨论中只考虑双目运算符。<br />如对于一个算术表达式2+5*6，乘法运算符’*’的两个操作数是它两边的5和6；对于加法运算符’+’的两个操作数，一个是它前面的2，另一个是它后面的 5*6的结果即30。我们把双目运算符出现在两个操作数中间的这种习惯表示叫做算术表达式的中缀表示，这种算术表达式被称为中缀算术表达式或中缀表达式。<br />中缀表达式的计算比较复杂，它必须遵守以下三条规则：<br />(1) 先计算括号内，后计算括号外；<br />(2) 在无括号或同层括号内，先进行乘除运算，后进行加减运算，即乘除运算的优先级高于加减运算的优先级；<br />(3) 同一优先级运算，从左向右依次进行。<br />从这三条规则可以看出，在中缀表达式的计算过程中，既要考虑括号的作用，又要考虑运算符的优先级，还要考虑运算符出现的先后次序。因此，各运算符实际的运算次序往往同它们在表达式中出现的先后次序是不一致的，是不可预测的。当然凭直观判别一个中缀表达式中哪个运算符最先算，哪个次之，……，哪个最后算并不困难，但通过计算机处理就比较困难了，因为计算机只能一个字符一个字符地扫描，要想得到哪一个运算符先算，就必须对整个中缀表达式扫描一遍，一个中缀表达式中有多少个运算符，原则上就得扫描多少遍才能计算完毕，这样就太浪费时间了，显然是不可取的。<br />那么，能否把中缀算术表达式转换成另一种形式的算术表达式，使计算简单化呢? 回答是肯定的。波兰科学家卢卡谢维奇(Lukasiewicz)很早就提出了算术表达式的另一种表示，即后缀表示，又称逆波兰式，其定义是把运算符放在两个运算对象的后面。采用后缀表示的算术表达式被称为后缀算术表达式或后缀表达式。在后缀表达式中，不存在括号，也不存在优先级的差别，计算过程完全按照运算符出现的先后次序进行，整个计算过程仅需一遍扫描便可完成，显然比中缀表达式的计算要简单得多。例如，对于后缀表达式12! 4!-!5!/，其中’!’字符表示成分之间的空格，因减法运算符在前，除法运算符在后，所以应先做减法，后做除法；减法的两个操作数是它前面的12和 4，其中第一个数12是被减数，第二个数4是减数；除法的两个操作数是它前面的12减4的差(即8)和5，其中8是被除数，5是除数。<br />中缀算术表达式转换成对应的后缀算术表达式的规则是：把每个运算符都移到它的两个运算对象的后面，然后删除掉所有的括号即可。<br />例如，对于下列各中缀表达式：<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 />(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 />后缀表达式的求值比较简单，扫描一遍即可完成。它需要使用一个栈，假定用S表示，其元素类型应为操作数的类型，假定为浮点型float，用此栈存储后缀表达式中的操作数、计算过程中的中间结果以及最后结果。假定一个后缀算术表达式以字符’@’作为结束符，并且以一个字符串的方式提供。后缀表达式求值算法的基本思路是：把包含后缀算术表达式的字符串定义为一个输入字符串流对象，每次从中读入一个字符（空格作为数据之间的分隔符，不会被作为字符读入）时，若它是运算符，则表明它的两个操作数已经在栈S中，其中栈顶元素为运算符的后一个操作数，栈顶元素的下一个元素为运算符的前一个操作数，把它们弹出后进行相应运算即可，然后把运算结果再压入栈S中；否则，读入的字符必为操作数的最高位数字，应把它重新送回输入流中，然后把下一个数据作为浮点数输入，并把它压入到栈S中。依次扫描每一个字符（对于浮点数只需扫描它的最高位并一次输入整个浮点数）并进行上述处理，直到遇到结束符’@’为止，表明后缀表达式计算完毕，最终结果保存在栈中，并且栈中仅存这一个值，把它弹出返回即可。具体算法描述为：<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)"> 表达式要以'@'字符结束。</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定义为输入字符串流对象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)">&gt;&gt;</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字符串)中顺序读入一个字符</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)"> 扫描每一个字符并进行相应处理</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)"> 除数为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)">&lt;&lt;</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)">&lt;</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)"> 读入的必为一个浮点数的最高位数字</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)">&gt;&gt;</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/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)"> 把读入的一个浮点数或进行相应运算<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)">&gt;&gt;</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/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)">&lt;&lt;</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)">&lt;</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)"> 若最后栈为空，则终止运行</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)">&lt;&lt;</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)">&lt;</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>此算法的运行时间主要花在while循环上，它从头到尾扫描后缀表达式中的每一个数据（每个操作数或运算符均为一个数据），若后缀表达式由n个数据组成，则此算法的时间复杂度为O(n)。此算法在运行时所占用的临时空间主要取决于栈S的大小，显然，它的最大深度不会超过表达式中操作数的个数，因为操作数的个数与运算符（假定把’@’也看作为一个特殊运算符，即结束运算符）的个数相等，所以此算法的空间复杂度也同样为O(n)。<br />假定一个字符串a为：<br />char a[30]="12 3 20 4 / * 8 - 6 * +@";<br />对应的中缀算术表达式为12+(3*(20/4)-8)*6@，则使用如下语句调用上述函数得到的输出结果为54。<br />cout&lt; 在进行这个后缀算术表达式求值的过程中，从第四个操作数入栈开始，每处理一个操作数或运算符后，栈S中保存的操作数和中间结果的情况如图4-4所示。<br /><br /> <br /><a style="COLOR: rgb(127,127,255)" href="http://www.cstudyhome.com/wenzhang06/uploadpic/200391117511780556.jpg" target="_blank"><img alt="" src="http://www.cstudyhome.com/wenzhang06/uploadpic/200391117511780556.jpg" onload="if(this.width&gt;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.blogjava.net/Duffblog/aggbug/87811.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-12-14 20:46 <a href="http://www.blogjava.net/Duffblog/articles/87811.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>算术表达式（转）</title><link>http://www.blogjava.net/Duffblog/articles/87810.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Thu, 14 Dec 2006 12:44:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/87810.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/87810.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/87810.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/87810.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/87810.html</trackback:ping><description><![CDATA[ 一、算术表达式的中缀表示
<p>把运算符放在参与运算的两个操作数中间的算术表达式称为中缀表达式。例如：2+3*4 - 6/9<br />算术表达式中包含了算术运算符和算术量(常量、变量、函数)，而运算符之间又存在着优先级，不能简单地进行从左到右运算，编译程序在求值时，不能简单从左到右运算，必须先算运算级别高的，再算运算级别低的，同一级运算才从左到右。在计算机中进行中缀表达式求值较麻烦。而后缀表达式求值较方便（无须考虑运算符的优先级及圆括号）。 <br />    <br />    二、算术表达式的后缀表示</p><p>把运算符放在参与运算的两个操作数后面的算术表达式称为后缀表达式。<br />例如，对于下列各中缀表达式：<br />(1)3/5+8<br />(2)18-9*(4+3)<br />对应的后缀表达式为：<br />(1)3 5 / 8 +<br />(2)18 9 4 3 + * -<br />转换规则:把每个运算符都移到它的两个操作数的后面,然后删除掉所有的括号即可.</p><p>    三 表达式的计算：</p><p>由于后缀表达式中没有括号，不需判别优先级，计算严格从左向右进行，故计算一个后缀表达式要比计算机一个中缀表达式简单得多。 </p><p>　　将中缀表达式转换为后缀表达式的算法思想：<br />　　·当读到数字直接送至输出队列中<br />　　·当读到运算符t时，<br />　　　　　a.将栈中所有优先级高于或等于t的运算符弹出，送到输出队列中； <br />　　　　　b.t进栈<br />　　·读到左括号时总是将它压入栈中<br />　　·读到右括号时，将靠近栈顶的第一个左括号上面的运算符全部依次弹出，送至输出队列后，再丢弃左括号。</p><p>    中缀表达式全部读完后，若栈中仍有运算符，将其送到输出队列中</p><p><br />　　 运用后缀表达式进行计算的具体做法：<br />　　·建立一个栈S<br />　　·从左到右读后缀表达式，读到数字就将它转换为数值压入栈S中，读到运算符则从栈中依次弹出两个数分别到Y和X，然后以"X 运算符 Y"的形式计算机出结果，再压加栈S中<br />　　·如果后缀表达式未读完，就重复上面过程，最后输出栈顶的数值则为结束</p><br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=619852</p><img src ="http://www.blogjava.net/Duffblog/aggbug/87810.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-12-14 20:44 <a href="http://www.blogjava.net/Duffblog/articles/87810.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java正则表达式详解(转)-----入门知识。</title><link>http://www.blogjava.net/Duffblog/articles/87626.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Thu, 14 Dec 2006 01:45:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/87626.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/87626.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/87626.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/87626.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/87626.html</trackback:ping><description><![CDATA[
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">如果你曾经用过Perl或任何其他内建正则表达式支持的语言，你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语，那么“正则表达式”（Regular Expression）就是一个字符构成的串，它定义了一个用来搜索匹配字符串的模式。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">许多语言，包括Perl、PHP、Python、JavaScript和JScript，都支持用正则表达式处理文本，一些文本编辑器用正则表达式实现高级“搜索-替换”功能。那么Java又怎样呢？本文写作时，一个包含了用正则表达式进行文本处理的Java规范需求（Specification Request）已经得到认可，你可以期待在JDK的下一版本中看到它。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">然而，如果现在就需要使用正则表达式，又该怎么办呢？你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识，然后以Jakarta-ORO API为例介绍如何使用正则表达式。 </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">我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串，搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感，单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说： </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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">
										<b>1.1 句点符号</b>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">假设你在玩英文拼字游戏，想要找出三个字母的单词，而且这些单词必须以“t”字母开头，以“n”字母结束。另外，假设有一本英文字典，你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式，你可以使用一个通配符——句点符号“.”。这样，完整的表达式就是“t.n”，它匹配“tan”、“ten”、“tin”和“ton”，还匹配“t#n”、“tpn”甚至“t n”，还有其他许多无意义的组合。这是因为句点符号匹配所有字符，包括空格、Tab字符甚至换行符： </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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">
										<b>1.2 方括号符号</b>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">为了解决句点符号匹配范围过于广泛这一问题，你可以在方括号（“[]”）里面指定看来有意义的字符。此时，只有方括号里面指定的字符才参与匹配。也就是说，正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配，因为在方括号之内你只能匹配单个字符： </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&gt;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">如果除了上面匹配的所有单词之外，你还想要匹配“toon”，那么，你可以使用“|”操作符。“|”操作符的基本意义就是“或”运算。要匹配“toon”，使用“t(a|e|i|o|oo)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/i1fus8ynpz96.jpg" onload="javascript:if(this.width&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">
										<b>1.4 表示匹配次数的符号</b>
								</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">
										<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&gt;500)this.style.width=500;" border="0" />
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中，连字符（“-”）有着特殊的意义，它表示一个范围，比如从0到9。因此，匹配社会安全号码中的连字符号时，它的前面要加上一个转义字符“\”。 </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&gt;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">图一：匹配所有123-12-1234形式的社会安全号码</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">假设进行搜索的时候，你希望连字符号可以出现，也可以不出现——即，999-99-9999和999999999都属于正确的格式。这时，你可以在连字符号后面加上“？”数量限定符号，如图二所示： </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&gt;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">图二：匹配所有123-12-1234和123121234形式的社会安全号码</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分“[0-9]{4}”，再加上字母部分“[A-Z]{2}”。图三显示了完整的正则表达式。 </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&gt;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">图三：匹配典型的美国汽车牌照号码，如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">“^”符号称为“否”符号。如果用在方括号内，“^”表示不想要匹配的字符。例如，图四的正则表达式匹配所有单词，但以“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&gt;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">图四：匹配所有单词，但“X”开头的除外</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">1.6 圆括号和空白符号 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">假设要从格式为“June 26, 1951”的生日日期中提取出月份部分，用来匹配该日期的正则表达式可以如图五所示： </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&gt;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">图五：匹配所有Moth DD,YYYY格式的日期</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">新出现的“\s”符号是空白符号，匹配所有的空白字符，包括Tab字符。如果字符串正确匹配，接下来如何提取出月份部分呢？只需在月份周围加上一个圆括号创建一个组，然后用ORO API（本文后面详细讨论）提取出它的值。修改后的正则表达式如图六所示： </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&gt;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">图六：匹配所有Month DD,YYYY格式的日期，定义月份值为第一个组</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">
										<b>1.7 其它符号</b>
								</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">表二：常用符号 </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&gt;500)this.style.width=500;" border="0" />
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">例如，在前面社会安全号码的例子中，所有出现“[0-9]”的地方我们都可以使用“\d”。修改后的正则表达式如图七所示： </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&gt;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">图七：匹配所有123-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">有许多源代码开放的正则表达式库可供Java程序员使用，而且它们中的许多支持Perl 5兼容的正则表达式语法。我在这里选用的是Jakarta-ORO正则表达式库，它是最全面的正则表达式API之一，而且它与Perl 5正则表达式完全兼容。另外，它也是优化得最好的API之一。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">Jakarta-ORO库以前叫做OROMatcher，Daniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下载它。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">我首先将简要介绍使用Jakarta-ORO库时你必须创建和访问的对象，然后介绍如何使用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">首先，创建一个Perl5Compiler类的实例，并把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实现，允许你把正则表达式编译成用来匹配的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&gt;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对象，调用compiler对象的compile()方法，并在调用参数中指定正则表达式。例如，你可以按照下面这种方式编译正则表达式“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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">默认情况下，编译器创建一个大小写敏感的模式（pattern）。因此，上面代码编译得到的模式只匹配“tin”、“tan”、 “ten”和“ton”，但不匹配“Tin”和“taN”。要创建一个大小写不敏感的模式，你应该在调用编译器的时候指定一个额外的参数： </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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">创建好Pattern对象之后，你就可以通过PatternMatcher类用该Pattern对象进行模式匹配。 </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对象和字符串进行匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给PatternMatcher接口。Perl5Matcher类是PatternMatcher接口的一个实现，它根据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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">使用PatternMatcher对象，你可以用多个方法进行匹配操作，这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串： </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">· boolean matches(String input, Pattern pattern)：当输入字符串和正则表达式要精确匹配时使用。换句话说，正则表达式必须完整地描述输入字符串。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">· boolean matchesPrefix(String input, Pattern pattern)：当正则表达式匹配输入字符串起始部分时使用。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">· boolean contains(String input, Pattern pattern)：当正则表达式要匹配输入字符串的一部分时使用（即，它必须是一个子串）。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">另外，在上面三个方法调用中，你还可以用PatternMatcherInput对象作为参数替代String对象；这时，你可以从字符串中最后一次匹配的位置开始继续进行匹配。当字符串可能有多个子串匹配给定的正则表达式时，用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 日志文件处理</b>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">任务：分析一个Web服务器日志文件，确定每一个用户花在网站上的时间。在典型的BEA WebLogic日志文件中，日志记录的格式如下： </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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">分析这个日志记录，可以发现，要从这个日志文件提取的内容有两项：IP地址和页面访问时间。你可以用分组符号（圆括号）从日志记录提取出IP地址和时间标记。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">首先我们来看看IP地址。IP地址有4个字节构成，每一个字节的值在0到255之间，各个字节通过一个句点分隔。因此，IP地址中的每一个字节有至少一个、最多三个数字。图八显示了为IP地址编写的正则表达式： </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&gt;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">图八：匹配IP地址</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">IP地址中的句点字符必须进行转义处理（前面加上“\”），因为IP地址中的句点具有它本来的含义，而不是采用正则表达式语法中的特殊含义。句点在正则表达式中的特殊含义本文前面已经介绍。 </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">
										<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&gt;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">图九：匹配至少一个字符，直至找到“]”</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">现在，把上述两个正则表达式加上分组符号（圆括号）后合并成单个表达式，这样就可以从日志记录提取出IP地址和时间。注意，为了匹配“- -”（但不提取它），正则表达式中间加入了“\s-\s-\s”。完整的正则表达式如图十所示。 </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&gt;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">图十：匹配IP地址和时间标记</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">现在正则表达式已经编写完毕，接下来可以编写使用正则表达式库的Java代码了。 </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">
										<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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">这里使用的正则表达式与图十的正则表达式差不多完全相同，但有一点例外：在Java中，你必须对每一个向前的斜杠（“\”）进行转义处理。图十不是Java的表示形式，所以我们要在每个“\”前面加上一个“\”以免出现编译错误。遗憾的是，转义处理过程很容易出现错误，所以应该小心谨慎。你可以首先输入未经转义处理的正则表达式，然后从左到右依次把每一个“\”替换成“\\”。如果要复检，你可以试着把它输出到屏幕上。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">初始化字符串之后，实例化PatternCompiler对象，用PatternCompiler编译正则表达式创建一个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/4o3y3mdkct2x.jpg" onload="javascript:if(this.width&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">现在，创建PatternMatcher对象，调用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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">接下来，利用PatternMatcher接口返回的MatchResult对象，输出匹配的组。由于logEntry字符串包含匹配的内容，你可以看到类如下面的输出： </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&gt;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">下面一个任务是分析HTML页面内FONT标记的所有属性。HTML页面内典型的FONT标记如下所示： </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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">程序将按照如下形式，输出每一个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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">在这种情况下，我建议你使用两个正则表达式。第一个如图十一所示，它从字体标记提取出“"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&gt;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">图十一：匹配FONT标记的所有属性</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">
										<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&gt;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">图十二：匹配单个属性，并把它分割成名字-值对</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/7jjzyu7lfs84.jpg" onload="javascript:if(this.width&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">现在我们来看看完成这个任务的Java代码。首先创建两个正则表达式字符串，用Perl5Compiler把它们编译成Pattern对象。编译正则表达式的时候，指定Perl5Compiler.CASE_INSENSITIVE_MASK选项，使得匹配操作不区分大小写。 </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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">假设有一个String类型的变量html，它代表了HTML文件中的一行内容。如果html字符串包含FONT标记，匹配器将返回true。此时，你可以用匹配器对象返回的MatchResult对象获得第一个组，它包含了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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">接下来创建一个PatternMatcherInput对象。这个对象允许你从最后一次匹配的位置开始继续进行匹配操作，因此，它很适合于提取FONT标记内属性的名字-值对。创建PatternMatcherInput对象，以参数形式传入待匹配的字符串。然后，用匹配器实例提取出每一个FONT的属性。这通过指定PatternMatcherInput对象（而不是字符串对象）为参数，反复地调用PatternMatcher对象的contains()方法完成。PatternMatcherInput对象之中的每一次迭代将把它内部的指针向前移动，下一次检测将从前一次匹配位置的后面开始。 </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&gt;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.com移到了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&gt;500)this.style.width=500;" border="0" />
								</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">
										<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&gt;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">图十三：匹配修改前的链接</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">
										<a href="http://newserver.acme.com/interface.html#$1">
										</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&gt;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等表示已经匹配且提取出来的组。图十三的表达式把所有作为一个组匹配和提取出来的内容附加到链接的后面。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">现在，返回Java。就象前面我们所做的那样，你必须创建测试字符串，创建把正则表达式编译到Pattern对象所必需的对象，以及创建一个PatternMatcher对象：<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&gt;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包Util类的substitute()静态方法进行替换，输出结果字符串： </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&gt;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&gt;500)this.style.width=500;" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">这个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象，它决定了替换操作如何进行。本例使用的是Perl5Substitution对象，它能够进行Perl5风格的替换。第四个参数是想要进行替换操作的字符串，最后一个参数允许指定是否替换模式的所有匹配子串（Util.SUBSTITUTE_ALL），或只替换指定的次数。 </td>
						</tr>
				</tbody>
		</table>
		<table width="620" align="center">
				<tbody>
						<tr>
								<td class="a14">
										<b>【结束语】</b>在这篇文章中，我为你介绍了正则表达式的强大功能。只要正确运用，正则表达式能够在字符串提取和文本修改中起到很大的作用。另外，我还介绍了如何在Java程序中通过Jakarta-ORO库利用正则表达式。至于最终采用老式的字符串处理方式（使用StringTokenizer，charAt，和substring），还是采用正则表达式，这就有待你自己决定了。<br /><br />（01年写的，紧参考！）</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/Duffblog/aggbug/87626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-12-14 09:45 <a href="http://www.blogjava.net/Duffblog/articles/87626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 虚礼机的一些配置。</title><link>http://www.blogjava.net/Duffblog/articles/76033.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Wed, 18 Oct 2006 14:40:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/76033.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/76033.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/76033.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/76033.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/76033.html</trackback:ping><description><![CDATA[1.设置MaxPermSize<br />MaxPermSize 可以设置为最大堆分配 (mx) 的一半。尝试设置 .XX:MaxPermSize=256m,但是,也有人设置到和MX一样的.可以尝试一下.<br />2.Heap Size<br />你的ERROR不是OUTOFMEMEROY,所以HEAP的大小应该可用.-Xms512m -Xmx512m 可以试一试.但是最近4月底有人发表意见说设成相同的比太好,会导致GC运行时间过短,导致效率下降.<br />3.HeapFreeRatio<br />这项设置对你的问题有没有帮助不太清楚,做一个比较反差的测试,-XX:MinHeapFreeRatio=10,-XX:MaxHeapFreeRatio=20,看看区别,建议最终设置:<br />-XX:MinHeapFreeRatio=30,-XX:MaxHeapFreeRatio=70<br />4.NewRatio<br />有可能是young generation 的大小过大,导致permanent generation大小不够,所以调整NewRatio有可能有用.<br />-XX:NewRatio=4<br /><img src ="http://www.blogjava.net/Duffblog/aggbug/76033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-10-18 22:40 <a href="http://www.blogjava.net/Duffblog/articles/76033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Spring用JDBC 调用ORACLE存储过程的结果集</title><link>http://www.blogjava.net/Duffblog/articles/72713.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Fri, 29 Sep 2006 00:56:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/72713.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/72713.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/72713.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/72713.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/72713.html</trackback:ping><description><![CDATA[
		<p>
				<u>
						<font color="#0000ff">public class LoadStoredProcedure extends StoredProcedure {</font>
				</u>
		</p>
		<p>
				<u>
						<font color="#0000ff"> <br /> private Map inParam;<br /> <br /> public MktLoadStoredProcedure(String storedProcedureName) {<br />  DataSource ds = (DataSource)SpringContextUtils.getInstance().getBean("dataSource");<br />  setDataSource(ds);<br />  setSql(storedProcedureName);<br /> }<br /> <br /> public RowMapper RouteRowMapper = new RowMapper(){<br />  public Object mapRow(ResultSet rs,int rowNum) throws SQLException{<br />   BidRouteInfo route = new BidRouteInfo();<br />   route.setBidHeaderId(rs.getString("BID_HEADER_ID"));<br />   route.setBidRouteInfoId(rs.getString("BID_ROUTE_INFO_ID"));<br />   route.setCreatedByUser(rs.getString("CREATED_BY_USER"));<br />   route.setCreatedDtmLoc(rs.getDate("CREATED_DTM_LOC"));<br />   route.setCreatedOffice(rs.getString("CREATED_OFFICE"));<br />   route.setCreatedTimeZone(rs.getString("CREATED_TIME_ZONE"));<br />   route.setDestCode(rs.getString("DEST_CODE"));<br />   route.setDestName(rs.getString("DEST_NAME"));<br />   route.setPodCode(rs.getString("POD_CODE"));<br />   route.setPodDestMode(rs.getString("POD_DEST_MODE"));<br />   route.setPodName(rs.getString("POD_NAME"));<br />   route.setPolCode(rs.getString("POL_CODE"));<br />   route.setPolName(rs.getString("POL_NAME"));<br />   route.setPorCode(rs.getString("POR_CODE"));<br />   route.setPorName(rs.getString("POR_NAME"));<br />   route.setPorPolMode(rs.getString("POR_POL_MODE"));<br />   route.setPorState(rs.getString("POR_STATE"));<br />   route.setPrincipalGroupCode(rs.getString("PRINCIPAL_GROUP_CODE"));<br />   route.setRecordVersion(rs.getLong("RECORD_VERSION"));<br />   route.setSeqNo(rs.getLong("SEQ_NO"));<br />   route.setServiceType(rs.getString("SERVICE_TYPE"));<br />   route.setStateCode(rs.getString("STATE_CODE"));<br />   route.setUpdatedByUser(rs.getString("UPDATED_BY_USER"));<br />   route.setUpdatedDtmLoc(rs.getDate("UPDATED_DTM_LOC"));<br />   route.setUpdatedOffice(rs.getString("UPDATED_OFFICE"));<br />   route.setUpdatedTimeZone(rs.getString("UPDATED_TIME_ZONE"));<br />   route.setRowStatus(BaseObject.ROWSTATUS_UNCHANGED);<br />   return route;<br />  }<br /> };<br /> <br /> public RowMapper FreightRowMapper = new RowMapper(){<br />  public Object mapRow(ResultSet rs,int rowNum) throws SQLException{<br />   BidFreightDetail freight = new BidFreightDetail();<br />   freight.setBidRouteInfoId(rs.getString("BID_ROUTE_INFO_ID"));<br />   freight.setBgColor(rs.getString("BG_COLOR"));<br />   freight.setBidFreightDetailId(rs.getString("BID_FREIGHT_DETAIL_ID"));<br />   freight.setChargeCode(rs.getString("CHARGE_CODE"));<br />   freight.setContainerType(rs.getString("CONTAINER_TYPE"));<br />   freight.setCreatedByUser(rs.getString("CREATED_BY_USER"));<br />   freight.setCreatedDtmLoc(rs.getDate("CREATED_DTM_LOC"));<br />   freight.setCreatedOffice(rs.getString("CREATED_OFFICE"));<br />   freight.setCreatedTimeZone(rs.getString("CREATED_TIME_ZONE"));<br />   freight.setPrincipalGroupCode(rs.getString("PRINCIPAL_GROUP_CODE"));<br />   freight.setRate(rs.getBigDecimal("RATE"));<br />   freight.setRecordVersion(rs.getLong("RECORD_VERSION"));<br />   freight.setUpdatedByUser(rs.getString("UPDATED_BY_USER"));<br />   freight.setUpdatedDtmLoc(rs.getDate("UPDATED_DTM_LOC"));<br />   freight.setUpdatedOffice(rs.getString("UPDATED_OFFICE"));<br />   freight.setUpdatedTimeZone(rs.getString("UPDATED_TIME_ZONE"));<br />   freight.setRowStatus(BaseObject.ROWSTATUS_UNCHANGED);<br />   return freight;<br />  }<br /> };<br /> //spring版本从1.2更新到2.0-rc3<br />// private RowMapperResultReader callback = new RowMapperResultReader(rowMapper){<br />//  public void processRow(ResultSet rs) throws SQLException{<br />//   int count = rs.getMetaData().getColumnCount();<br />//   String[] header = new String[count];<br />//   for(int i=0;i&lt;count;i++){<br />//    header[i] = rs.getMetaData().getColumnName(i+1);<br />//   }<br />//   do{<br />//     HashMap&lt;String,String&gt; row = new HashMap&lt;String,String&gt;();<br />//     for(int i=0;i&lt;count;i++){<br />//      row.put(header[i],rs.getString(i+1));<br />//     }<br />//     rsList.add(row);<br />//   }while(rs.next());<br />//  }<br />// };<br /> <br />// private RowMapperResultSetExtractor callback = new RowMapperResultSetExtractor(RouteRowMapper){<br />//  public List extractData(ResultSet rs) throws SQLException{<br />//   int count = rs.getMetaData().getColumnCount();<br />//   String[] header = new String[count];<br />//   for(int i=0;i&lt;count;i++){<br />//    header[i] = rs.getMetaData().getColumnName(i+1);<br />//   }<br />//   while(rs.next()){<br />//     HashMap&lt;String,String&gt; row = new HashMap&lt;String,String&gt;();<br />//     for(int i=0;i&lt;count;i++){<br />//      row.put(header[i],rs.getString(i+1));<br />//     }<br />//     rsList.add(row);<br />//   }<br />//   return rsList;<br />//  }<br />// };<br /> <br /> public Map execute(){<br />  compile();<br />  if(inParam == null){<br />   return execute();<br />  }<br />  return execute(this.inParam);<br /> }</font>
				</u>
		</p>
		<p>
				<u>
						<font color="#0000ff"> public void setOutParameter(String column,int type,RowMapper rowMapper){<br />  declareParameter(new SqlOutParameter(column,type,rowMapper));<br /> }<br /> <br /> public void setParameter(String column,int type){<br />  declareParameter(new SqlParameter(column,type));<br /> }<br /> public void setInParam(Map inParam){<br />  this.inParam = inParam;<br /> }<br />}<br /></font>
				</u>
				<br />调用：<br /><br />   LoadStoredProcedure sp = new LoadStoredProcedure("SP_MKT_LOAD_TEST");<br />  sp.setParameter("V_BID_HEADER_ID", Types.VARCHAR);<br />  sp.setOutParameter("ROUTECURSOR", OracleTypes.CURSOR,sp.RouteRowMapper);<br />  sp.setOutParameter("FRIGHTCURSOR", OracleTypes.CURSOR,sp.FreightRowMapper);<br />  <br />  Map&lt;String,String&gt; mapValue = new HashMap&lt;String,String&gt;(1);<br />  mapValue.put("V_BID_HEADER_ID", bidHeaderId);<br />  sp.setInParam(mapValue);<br />  Map map = sp.execute();<br /><br />List freightDetails = (List)map.get("FRIGHTCURSOR");<br />  List routeInfos = (List)map.get("ROUTECURSOR");<br />具体参考：</p>
		<p>
				<a href="http://www.springframework.org/docs/reference/jdbc.html">http://www.springframework.org/docs/reference/jdbc.html</a>
		</p>
<img src ="http://www.blogjava.net/Duffblog/aggbug/72713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-09-29 08:56 <a href="http://www.blogjava.net/Duffblog/articles/72713.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java AWT Clipboard（Java剪贴板）的用法。</title><link>http://www.blogjava.net/Duffblog/articles/71842.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Mon, 25 Sep 2006 14:45:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/71842.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/71842.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/71842.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/71842.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/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") &gt;= 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&lt;BidRouteInfo&gt; pastedRouteInfos = new LinkedList&lt;BidRouteInfo&gt;();<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 />              //第0列是隐藏的(冻结功能必须在有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.blogjava.net/Duffblog/aggbug/71842.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-09-25 22:45 <a href="http://www.blogjava.net/Duffblog/articles/71842.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>咖啡，还是淡些好</title><link>http://www.blogjava.net/Duffblog/articles/59589.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Sat, 22 Jul 2006 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/59589.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/59589.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/59589.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/59589.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/59589.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font size="3">好久没有给大家写点什么了，由于最近特别忙，希望不要介意！</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<font size="3">
						<span lang="EN-US">
								<span style="mso-spacerun: yes">    </span>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">今天，来谈喝咖啡吗？当然不是，我们要看看咖啡到底该怎么喝，正如学</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一样。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">太浓了吧</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">否則怎会苦的说不出话</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每次都一个人在自问自答</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们的爱到底还在吗</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<font size="3">
						<span lang="EN-US">
								<span style="mso-spacerun: yes">    </span>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">第一次，听到这段台词，您呢？听过没有，这可是我偶像唱的（张学友新专辑，《他在那里》中的，咖啡，建议听听，很不错。他的歌是流行，但又非流行）。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<font size="3">
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，我来谈如何品她，可不是一件简单的事情，因为我喝的也不多，你呢？但我在用心去品。我们学技术，可不要陷入一个怪圈，唯技术论，这样的话你可就错了。无论什么技术，都是为人类服务的，我们的目标是更好的生活，自然咖啡也少不了。所以，我们对待</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的态度一定要有理性，比如，蔡學鏞先生</span>
						<span lang="EN-US">(<a href="http://www.oreilly.com.tw/sleepless/index.htm"><font face="Arial" color="#0030ce">http://www.oreilly.com.tw/sleepless/index.htm</font></a> )</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">都谦虚的说，他的</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">功底是</span>
						<span lang="EN-US">Lots of API</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。所以，心态要放平和，可不要有宗教式的仰慕（本人也是很喜欢</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的）。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">初次接触</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，大家一定会被</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中大量的术语，新名词吓了一大跳。打开</span>
						<span lang="EN-US">The Source for Java Technology</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</span>
						<span lang="EN-US">
								<a href="http://java.sun.com/">
										<font face="Arial" color="#0030ce">http://java.sun.com</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）</span>
						<span lang="EN-US">, </span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">点击进入</span>
						<span lang="EN-US">
								<a href="http://java.sun.com/j2se/">
										<font face="Arial" color="#0030ce">http://java.sun.com/j2se/</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span>
						<span lang="EN-US">Java 2</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">出来了，这可是热气腾腾的，很够味。下载一个</span>
						<span lang="EN-US">JavaTM 2 Platform, Standard Edition (J2SETM)</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，网址</span>
						<span lang="EN-US">
								<a href="http://java.sun.com/j2se/downloads.html">
										<font face="Arial" color="#0030ce">http://java.sun.com/j2se/downloads.html</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。安装在一个没有空格的目录下。比如，俄</span>
						<span lang="EN-US">E:\j2sdk1.4.x</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下。安装完后，您现在所需要的做的就是三件事情。第一，设置环境变量，</span>
						<span lang="EN-US">set JAVA_HOME = E:\j2sdk1.4.x</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，其次再设一个环境变量，</span>
						<span lang="EN-US">set classpath = .;</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，最后还需</span>
						<span lang="EN-US">set path = %JAVA_HOME%\bin</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。这样就完成了</span>
						<span lang="EN-US">J2SE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的安装。安装完后，大家可以去</span>
						<span lang="EN-US">E:\j2sdk1.4.0\demo </span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运行</span>
						<span lang="EN-US">J2SE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">带的</span>
						<span lang="EN-US">Demos</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">看看。哈哈，好漂亮。</span>
						<span lang="EN-US">E:\j2sdk1.4.0\demo\jfc\Java2D</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，这个例子您看过没有，特别好看。好是羡慕。我自己也想写这么漂亮的程序。怎么办？？？？</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US">
						<a href="http://java.sun.com/docs/books/tutorial/">
								<font face="Arial" color="#0030ce" size="3">http://java.sun.com/docs/books/tutorial/</font>
						</a>
						<font size="3">, </font>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font size="3">这个地方可是您的切入点。我英文不怎么样，怎么办？其实技术领域的英文，你刚开始看的时候会有这样的想法，但时间长了，只要你可以坚持，慢慢的你就会发现，原来英文表达技术内涵特别贴切，不相信，你就看吧。。。：）</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当然，做什么东西都得有工具。木匠有自己的一套工具。</span>
						<span lang="EN-US">Brood</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，我们也得有自己的一些好工具。个人认为，这三件宝贝缺一不可。第一件，</span>
						<span lang="EN-US">Java 2 SDK, Standard Edition, Documentation</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span>
						<span lang="EN-US">
								<a href="http://java.sun.com/j2se/1.4.1/docs/index.html">
										<font face="Arial" color="#0030ce">http://java.sun.com/j2se/1.4.1/docs/index.html</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。这就是您的圣经，可要经常看看，不会的、会的，要经常参考，这可使你的功力大增，可要坚持哦，不要因为是一时的热情。第二件，就是，《</span>
						<span lang="EN-US">Thinking in Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">》，</span>
						<span lang="EN-US">
								<a href="http://64.78.49.204/TIJ3.zip">
										<font face="Arial" color="#0030ce">http://64.78.49.204/TIJ3.zip</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有最新版（第三版）下载，其中讲述的</span>
						<span lang="EN-US">J2SE 1.4.0</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。其中，第二版的中文翻译（由侯捷翻译的，一定不要错过！），</span>
						<span lang="EN-US">
								<a href="http://www.china-pub.com/computers/common/info.asp?id=7241">
										<font face="Arial" color="#0030ce">http://www.china-pub.com/computers/common/info.asp?id=7241</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，如果说第一件宝贝是圣经，那么这本就是玄学。这可是大家能修炼到的高境界的入门读物，一定比漫画书好看。那么，第三件是什么呢？那就是你自己，一定要多思考、多练、多写程序。你可以主宰一切，但除了你自己。</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">刚开始工具的选择，这个因人而异。我喜欢用大家伙，比如</span>
						<span lang="EN-US">JBuilder</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">Together</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">Eclipse</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">JDeveloper</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
						<span lang="EN-US">…….</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。当然，你可以用</span>
						<span lang="EN-US">JCreator</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，也挺不错的。大的工具可以加快你的功效，但前提是你对</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本身有良好的操控能力。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font size="3">哦，轻松一下。</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">已经淡了吧</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">多放些糖也很难有变化</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不如喝完这杯就各自回家</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">別坐在对面欣賞我的掙扎</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其实，甜咖啡也挺不错的。看你喜不喜欢喝了。在这里说几句题外话，那就是计算机图书。其实，书，无论写得好与坏，都值得一看。但前提是你不会被他给误导。（如果，你第一次把我骗了，你就是很卑鄙；如果再次被你骗，说明我很无耻！：），这句话不是我说的）每本书都能反映作者的某种思想。所以多看书，还是不错的。这个时候肯定有人会问，看完后，隔上一段时间又忘得差不多了。其实这个很正常，关键看你是否坚持。</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">好了，</span>
						<span lang="EN-US">J2SE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就谈到这里。有了相当的功底后，我们来啃另一快大石头，</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，现在可以说，是一个使自己身价抬高的绝佳途径。但看到那么多概念，术语，名词，算了，还是不学得好。我想我们都有这种想法。其实换一种角度，来看，不如</span>
						<span lang="EN-US">VB,Delphi</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上手快。但有一点，</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的体系特别清晰。由于</span>
						<span lang="EN-US">
								<a href="http://www.jcp.org/">
										<font face="Arial" color="#0030ce">http://www.jcp.org</font>
								</a>, </span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">操控了</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的命脉，所以你一定要知道这个地方。好了，首先去</span>
						<span lang="EN-US">
								<a href="http://java.sun.com/j2ee/download.html">
										<font face="Arial" color="#0030ce">http://java.sun.com/j2ee/download.html</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下载一个</span>
						<span lang="EN-US">Sun</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的参考实现版本</span>
						<span lang="EN-US">JavaTM 2 Platform, Enterprise Edition (J2EETM)</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。安装完后，你可以参考安装目录</span>
						<span lang="EN-US">\doc</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中配置相应的参数。好了，然后，去</span>
						<span lang="EN-US">
								<a href="http://java.sun.com/j2ee/tutorial/1_3-fcs/">
										<font face="Arial" color="#0030ce">http://java.sun.com/j2ee/tutorial/1_3-fcs/</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">看看，当然，事务都是相通的。学</span>
						<span lang="EN-US">J2SE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中类似的过程在这里也可以拿过来。首先，给你</span>
						<span lang="EN-US">3</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">件宝刀。第一件，</span>
						<span lang="EN-US">
								<a href="http://jcp.org/en/jsr/stage?listBy=final">
										<font face="Arial" color="#0030ce">http://jcp.org/en/jsr/stage?listBy=final</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下载</span>
						<span lang="EN-US">J2EE Specification</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，这个规范可要经常看。这就是您的老师，什么时候都是。第二件宝贝您可一定不要错过，</span>
						<span lang="EN-US">
								<a href="http://www2.theserverside.com/resources/index.jsp">
										<font face="Arial" color="#0030ce">http://www2.theserverside.com/resources/index.jsp</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这里很不错。第三件，可以去</span>
						<span lang="EN-US">
								<a href="http://java.sun.com/blueprints/">
										<font face="Arial" color="#0030ce">http://java.sun.com/blueprints/</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">看看</span>
						<span lang="EN-US">Petstore</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（至于其源代码是否值得研究，个人认为不值得，有这么多时间，不如去研究</span>
						<span lang="EN-US">JBoss</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">！）。或者说，换一种角度，您可以去</span>
						<span lang="EN-US">
								<a href="http://otn.oracle.com/sample_code/tutorials/fbs/fbstoc.htm">
										<font face="Arial" color="#0030ce">http://otn.oracle.com/sample_code/tutorials/fbs/fbstoc.htm</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">看看，看完后，你应该不会骂我的。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">等您有了一定的</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">功底后，你可以开始走向更高的地方，首先看段台词先。</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一场失敗的爱情像个笑话</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">热得时后心乱如麻</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">冷了以后看见自己够傻</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">人怎么会如此容易无法自拔</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其实，在</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中，重要的不是各个技术本身（</span>
						<span lang="EN-US">EJB,</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">比</span>
						<span lang="EN-US">COM</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">好学！！！您认为呢？），重要的是</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计模式的合理运用。那么，其中，有三个东西值得您去关注。一个，在这个过程中，一定要把</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的体系结构弄得很清楚。二个，</span>
						<span lang="EN-US">EJB</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">技术，这可是含金量很大的地方。第三，一定要关注常见的</span>
						<span lang="EN-US">Java Open Source</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。。。这个都不知道的话，说明您还没有对</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有很好的认识。其中，有一些较好的资源，</span>
						<span lang="EN-US">
								<a href="http://gceclub.sun.com.cn/experttalk/oct15.html">
										<font face="Arial" color="#0030ce">http://gceclub.sun.com.cn/experttalk/oct15.html</font>
								</a>
						</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这可是一流的</span>
						<span lang="EN-US">Caffee!!! <a href="http://www2.theserverside.com/home/index.jsp"><font face="Arial" color="#0030ce">http://www2.theserverside.com/home/index.jsp</font></a></span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">高手一定要去的地方。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font size="3">慢慢的，您要形成善于、喜欢关注业界动态的习惯！！这种沉淀可是无价的。没有时间、精力的付出，你对业界是不会有很好的、很深的认识。</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一句话，学习</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，一定要有宏观的把握，具体技术的深入细节需要我们在课题中慢慢领悟，这也不是看几本书所能掌握的，贵在坚持，但一定要注意方法。</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一场无味的爱情像个谎话</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">甜的时后只相信它</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">苦了以后每一句都可怕</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt; mso-char-indent-count: 2.0">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">人怎么会如此容易了无牽掛</span>
						<span lang="EN-US">
						</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有了前面这些东东，我们可以开始研究某一个</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用服务器。比如，</span>
						<span lang="EN-US">JBoss, WebLogic</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。首先学会熟练使用，慢慢的深入到具体的细节，比如</span>
						<span lang="EN-US">JMX</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">技术。因</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应用服务器集成、实现了规范中的所有技术，所以这些是很不错的思路。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span lang="EN-US">Web Services</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">技术，可以说</span>
						<span lang="EN-US">J2EE</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">平台生来就有这种驾驭</span>
						<span lang="EN-US">Web Services</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的能力。为什么这么说呢？</span>
						<span lang="EN-US">Web Services</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">技术，要是没有</span>
						<span lang="EN-US">XML</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">技术为先遣部队，我想</span>
						<span lang="EN-US">Web Services</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">业不会有今天。微软也不会把</span>
						<span lang="EN-US">Web Services</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">称之为，</span>
						<span lang="EN-US">XML Web Services</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">技术。</span>
						<span lang="EN-US">XML</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">技术对数据提供了便利、</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对平台提供了便利。其结合的结果可想而知。即使没有“孤独求败”那么厉害，我想也会有“不败孤独”那么好。有些公司很会做技术，有些公司很会做市场。但大家的眼光是雪亮的，我们也没有必要说什么技术是万能的，没有万能的技术，关键看应用，是否能很好的解决实际问题。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">说白了，</span>
						<span lang="EN-US">Web Services</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中其实没多少新东西，但这种体系结构需要您有很好的把握，然后深入技术细则。</span>
				</font>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font size="3">这些，都是我的个人观点，希望看完后，有不对的地方，批评指正！！</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font size="3">也欢迎访问我的个人专栏。（也欢迎大家写信和我交流，交个朋友也可以！）</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<a href="http://www.csdn.net/develop/author/netauthor/worldheart/">
								<font face="Arial" color="#0030ce" size="3">http://www.csdn.net/develop/author/netauthor/worldheart/</font>
						</a>
						<font size="3">
								<o:p>
								</o:p>
						</font>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span lang="EN-US">
						<o:p>
								<font size="3"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
						<font size="3">您开始喝咖啡没有？要不，给你来一杯，不要噎到了，要慢慢品，。。。。。</font>
				</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/Duffblog/aggbug/59589.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-07-22 22:28 <a href="http://www.blogjava.net/Duffblog/articles/59589.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA内存泄漏——内存泄漏原因和内存泄漏检测工具(zt)</title><link>http://www.blogjava.net/Duffblog/articles/50044.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Fri, 02 Jun 2006 11:17:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/50044.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/50044.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/50044.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/50044.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/50044.html</trackback:ping><description><![CDATA[
		<p>摘要 <br />　　虽然Java虚拟机(JVM)及其垃圾收集器(garbage
collector，GC)负责管理大多数的内存任务，Java软件程序中还是有可能出现内存泄漏。实际上，这在大型项目中是一个常见的问题。避免内存泄
漏的第一步是要弄清楚它是如何发生的。本文介绍了编写Java代码的一些常见的内存泄漏陷阱，以及编写不泄漏代码的一些最佳实践。一旦发生了内存泄漏，要
指出造成泄漏的代码是非常困难的。因此本文还介绍了一种新工具，用来诊断泄漏并指出根本原因。该工具的开销非常小，因此可以使用它来寻找处于生产中的系统
的内存泄漏。</p>
		<p>垃圾收集器的作用</p>
		<p>　　虽然垃圾收集器处理了大多数内存管理问题，从而使编程人员的生活变得更轻
松了，但是编程人员还是可能犯错而导致出现内存问题。简单地说，GC循环地跟踪所有来自“根”对象（堆栈对象、静态对象、JNI句柄指向的对象，诸如此
类）的引用，并将所有它所能到达的对象标记为活动的。程序只可以操纵这些对象；其他的对象都被删除了。因为GC使程序不可能到达已被删除的对象，这么做就
是安全的。</p>
		<p>　　虽然内存管理可以说是自动化的，但是这并不能使编程人员免受思考内存管理问题之苦。例如，分配（以及释放）内存总会
有开销，虽然这种开销对编程人员来说是不可见的。创建了太多对象的程序将会比完成同样的功能而创建的对象却比较少的程序更慢一些（在其他条件相同的情况
下）。</p>
		<p>　　而且，与本文更为密切相关的是，如果忘记“释放”先前分配的内存，就可能造成内存泄漏。如果程序保留对永远不再使用的对
象的引用，这些对象将会占用并耗尽内存，这是因为自动化的垃圾收集器无法证明这些对象将不再使用。正如我们先前所说的，如果存在一个对对象的引用，对象就
被定义为活动的，因此不能删除。为了确保能回收对象占用的内存，编程人员必须确保该对象不能到达。这通常是通过将对象字段设置为null或者从集合
(collection)中移除对象而完成的。但是，注意，当局部变量不再使用时，没有必要将其显式地设置为null。对这些变量的引用将随着方法的退出
而自动清除。</p>
		<p>　　概括地说，这就是内存托管语言中的内存泄漏产生的主要原因：保留下来却永远不再使用的对象引用。</p>
		<p>典型泄漏</p>
		<p>　　既然我们知道了在Java中确实有可能发生内存泄漏，就让我们来看一些典型的内存泄漏及其原因。</p>
		<p>全局集合</p>
		<p>　　在大的应用程序中有某种全局的数据储存库是很常见的，例如一个JNDI树或一个会话表。在这些情况下，必须注意管理储存库的大小。必须有某种机制从储存库中移除不再需要的数据。</p>
		<p>　　这可能有多种方法，但是最常见的一种是周期性运行的某种清除任务。该任务将验证储存库中的数据，并移除任何不再需要的数据。</p>
		<p>　　另一种管理储存库的方法是使用反向链接(referrer)计数。然后集合负责统计集合中每个入口的反向链接的数目。这要求反向链接告诉集合何时会退出入口。当反向链接数目为零时，该元素就可以从集合中移除了。</p>
		<p>缓存</p>
		<p>　　缓存是一种数据结构，用于快速查找已经执行的操作的结果。因此，如果一个操作执行起来很慢，对于常用的输入数据，就可以将操作的结果缓存，并在下次调用该操作时使用缓存的数据。</p>
		<p>　　缓存通常都是以动态方式实现的，其中新的结果是在执行时添加到缓存中的。典型的算法是：</p>
		<p>检查结果是否在缓存中，如果在，就返回结果。 <br />如果结果不在缓存中，就进行计算。 <br />将计算出来的结果添加到缓存中，以便以后对该操作的调用可以使用。 <br />　　该算法的问题（或者说是潜在的内存泄漏）出在最后一步。如果调用该操作时有相当多的不同输入，就将有相当多的结果存储在缓存中。很明显这不是正确的方法。</p>
		<p>　　为了预防这种具有潜在破坏性的设计，程序必须确保对于缓存所使用的内存容量有一个上限。因此，更好的算法是：</p>
		<p>检查结果是否在缓存中，如果在，就返回结果。 <br />如果结果不在缓存中，就进行计算。 <br />如果缓存所占的空间过大，就移除缓存最久的结果。 <br />将计算出来的结果添加到缓存中，以便以后对该操作的调用可以使用。 <br />　　通过始终移除缓存最久的结果，我们实际上进行了这样的假设：在将来，比起缓存最久的数据，最近输入的数据更有可能用到。这通常是一个不错的假设。</p>
		<p>　　新算法将确保缓存的容量处于预定义的内存范围之内。确切的范围可能很难计算，因为缓存中的对象在不断变化，而且它们的引用包罗万象。为缓存设置正确的大小是一项非常复杂的任务，需要将所使用的内存容量与检索数据的速度加以平衡。</p>
		<p>　　解决这个问题的另一种方法是使用java.lang.ref.SoftReference类跟踪缓存中的对象。这种方法保证这些引用能够被移除，如果虚拟机的内存用尽而需要更多堆的话。</p>
		<p>ClassLoader</p>
		<p>　
　Java
ClassLoader结构的使用为内存泄漏提供了许多可乘之机。正是该结构本身的复杂性使ClassLoader在内存泄漏方面存在如此多的问题。
ClassLoader的特别之处在于它不仅涉及“常规”的对象引用，还涉及元对象引用，比如：字段、方法和类。这意味着只要有对字段、方法、类或
ClassLoader的对象的引用，ClassLoader就会驻留在JVM中。因为ClassLoader本身可以关联许多类及其静态字段，所以就有
许多内存被泄漏了。</p>
		<p>确定泄漏的位置</p>
		<p>　　通常发生内存泄漏的第一个迹象是：在应用程序中出现了
OutOfMemoryError。这通常发生在您最不愿意它发生的生产环境中，此时几乎不能进行调试。有可能是因为测试环境运行应用程序的方式与生产系
统不完全相同，因而导致泄漏只出现在生产中。在这种情况下，需要使用一些开销较低的工具来监控和查找内存泄漏。还需要能够无需重启系统或修改代码就可以将
这些工具连接到正在运行的系统上。可能最重要的是，当进行分析时，需要能够断开工具而保持系统不受干扰。</p>
		<p>　　虽然
OutOfMemoryError通常都是内存泄漏的信号，但是也有可能应用程序确实正在使用这么多的内存；对于后者，或者必须增加JVM可用的堆的数
量，或者对应用程序进行某种更改，使它使用较少的内存。但是，在许多情况下，OutOfMemoryError都是内存泄漏的信号。一种查明方法是不间断
地监控GC的活动，确定内存使用量是否随着时间增加。如果确实如此，就可能发生了内存泄漏。</p>
		<p>详细输出</p>
		<p>　　有许多监控垃圾收集器活动的方法。而其中使用最广泛的可能是使用-Xverbose:gc选项启动JVM，并观察输出。</p>
		<p>[memory ] 10.109-10.235: GC 65536K-&gt;16788K (65536K), 126.000 ms <br />　箭头后面的值（本例中是16788K）是垃圾收集所使用的堆的容量。</p>
		<p>控制台</p>
		<p>　　查看连续不断的GC的详细统计信息的输出将是非常乏味的。幸好有这方面的工具。JRockit Management Console可以显示堆使用量的图示。借助于该图，可以很容易地看出堆使用量是否随时间增加。<br /><img src="http://dev2dev.bea.com/images/2005/06/mem_leak_002.gif" align="bottom" border="0" hspace="0" /><br /><em>Figure 1. The JRockit Management Console</em></p>
		<p>甚至可以配置该管理控制台，以便如果发生堆使用量过大的情况（或基于其他的事件），控制台能够向您发送电子邮件。这明显使内存泄漏的查看变得更容易了。</p>
		<p>
				<font size="3">内存泄漏检测工具</font>
		</p>
		<p>
				<font size="3">　　还有其他的专门进行内存泄漏检测的工具。JRockit Memory Leak Detector可以用来查看内存泄漏，并可以更深入地查出泄漏的根源。这个强大的工具是紧密集成到JRockit JVM中的，其开销非常小，对虚拟机的堆的访问也很容易。</font>
		</p>
		<p>
				<font size="3">专业工具的优点</font>
		</p>
		<p>
				<font size="3">　
　一旦知道确实发生了内存泄漏，就需要更专业的工具来查明为什么会发生泄漏。JVM自己是不会告诉您的。这些专业工具从JVM获得内存系统信息的方法基本
上有两种：JVMTI和字节码技术(byte code instrumentation)。Java虚拟机工具接口(Java Virtual
Machine Tools Interface，JVMTI)及其前身Java虚拟机监视程序接口(Java Virtual Machine
Profiling
Interface，JVMPI)是外部工具与JVM通信并从JVM收集信息的标准化接口。字节码技术是指使用探测器处理字节码以获得工具所需的信息的技
术。</font>
		</p>
		<p>
				<font size="3">　　对于内存泄漏检测来说，这两种技术有两个缺点，这使它
们不太适合用于生产环境。首先，它们在内存占用和性能降低方面的开销不可忽略。有关堆使用量的信息必须以某种方式从JVM导出，并收集到工具中进行处理。
这意味着要为工具分配内存。信息的导出也影响了JVM的性能。例如，当收集信息时，垃圾收集器将运行得比较慢。另外一个缺点是需要始终将工具连在JVM
上。这是不可能的：将工具连在一个已经启动的JVM上，进行分析，断开工具，并保持JVM运行。</font>
		</p>
		<p>
				<font size="3">　
　因为JRockit Memory Leak
Detector是集成到JVM中的，就没有这两个缺点了。首先，许多处理和分析工作是在JVM内部进行的，所以没有必要转换或重新创建任何数据。处理还
可以背负(piggyback)在垃圾收集器本身上而进行，这意味着提高了速度。其次，只要JVM是使用-Xmanagement选项（允许通过远程
JMX接口监控和管理JVM）启动的，Memory Leak
Detector就可以与运行中的JVM进行连接或断开。当该工具断开时，没有任何东西遗留在JVM中，JVM又将以全速运行代码，正如工具连接之前一
样。</font>
		</p>
		<p>
				<font size="3">趋势分析</font>
		</p>
		<p>
				<font size="3">　
　让我们深入地研究一下该工具以及它是如何用来跟踪内存泄漏的。在知道发生内存泄漏之后，第一步是要弄清楚泄漏了什么数据--哪个类的对象引起了泄漏？
JRockit Memory Leak
Detector是通过在每次垃圾收集时计算每个类的现有对象的数目来实现这一步的。如果特定类的对象数目随时间而增长（“增长率”），就可能发生了内存
泄漏。 </font>
		</p>
		<p>
				<font size="3">
						<img src="http://dev2dev.bea.com/images/2005/06/mem_leak_003.gif" align="bottom" border="0" hspace="0" />
						<br />图2. Memory Leak Detector的趋势分析视图</font>
		</p>
		<p>
				<font size="3">　
　因为泄漏可能像细流一样非常小，所以趋势分析必须运行很长一段时间。在短时间内，可能会发生一些类的局部增长，而之后它们又会跌落。但是趋势分析的开销
很小（最大开销也不过是在每次垃圾收集时将数据包由JRockit发送到Memory Leak
Detector）。开销不应该成为任何系统的问题——即使是一个全速运行的生产中的系统。</font>
		</p>
		<p>
				<font size="3">　　起初数目会跳跃不停，但是一段时间之后它们就会稳定下来，并显示出哪些类的数目在增长。</font>
		</p>
		<p>
				<font size="3">找出根本原因</font>
		</p>
		<p>
				<font size="3">　
　有时候知道是哪些类的对象在泄漏就足以说明问题了。这些类可能只用于代码中的非常有限的部分，对代码进行一次快速检查就可以显示出问题所在。遗憾地是，
很有可能只有这类信息还并不够。例如，常见到泄漏出在类java.lang.String的对象上，但是因为字符串在整个程序中都使用，所以这并没有多大
帮助。</font>
		</p>
		<p>
				<font size="3">　　我们想知道的是，另外还有哪些对象与泄漏对象关联？
在本例中是String。为什么泄漏的对象还存在？哪些对象保留了对这些对象的引用？但是能列出的所有保留对String的引用的对象将会非常多，以至于
没有什么实际用处。为了限制数据的数量，可以将数据按类分组，以便可以看出其他哪些对象的类与泄漏对象(String)关联。例如，String在
Hashtable中是很常见的，因此我们可能会看到与String关联的Hashtable数据项对象。由Hashtable数据项倒推，我们最终可以
找到与这些数据项有关的Hashtable对象以及String（如图3所示）。 </font>
		</p>
		<p>
				<font size="3">
						<img src="http://dev2dev.bea.com/images/2005/06/mem_leak_005.gif" align="bottom" border="0" hspace="0" />
						<br />图3. 在工具中看到的类型图的示例视图</font>
		</p>
		<p>
				<font size="3">倒推</font>
		</p>
		<p>
				<font size="3">　
　因为我们仍然是以类的对象而不是单独的对象来看待对象，所以我们不知道是哪个Hashtable在泄漏。如果我们可以弄清楚系统中所有的
Hashtable都有多大，我们就可以假定最大的Hashtable就是正在泄漏的那一个（因为随着时间的流逝它会累积泄漏而增长得相当大）。因此，一
份有关所有Hashtable对象以及它们引用了多少数据的列表，将会帮助我们指出造成泄漏的确切Hashtabl。 </font>
		</p>
		<p>
				<font size="3">
						<img src="http://dev2dev.bea.com/images/2005/06/mem_leak_006.gif" align="bottom" border="0" hspace="0" />
						<br />图4. 界面：Hashtable对象以及它们所引用数据的数量的列表</font>
		</p>
		<p>
				<font size="3">　
　对对象引用数据数目的计算开销非常大（需要以该对象作为根遍历引用图），如果必须对许多对象都这么做，将会花很多时间。如果了解一点Hashtable
的内部实现原理就可以找到一条捷径。Hashtable的内部有一个Hashtable数据项的数组。该数组随着Hashtable中对象数目的增长而增
长。因此，为找出最大的Hashtable，我们只需找出引用Hashtable数据项的最大数组。这样要快很多。 </font>
		</p>
		<p>
				<img src="http://dev2dev.bea.com/images/2005/06/mem_leak_007.gif" align="bottom" border="0" hspace="0" />
				<br />
				<font size="3">图5. 界面：最大的Hashtable数据项数组及其大小的清单</font>
		</p>
		<p>
				<font size="3">更进一步</font>
		</p>
		<p>
				<font size="3">　　当找到发生泄漏的Hashtable实例时，我们可以看到其他哪些实例在引用该Hashtable，并倒推回去看看是哪个Hashtable在泄漏。</font>
		</p>
		<p>
				<font size="3">
						<img src="http://dev2dev.bea.com/images/2005/06/mem_leak_009.gif" align="bottom" border="0" hspace="0" />
						<br />图 6. 这就是工具中的实例图</font>
		</p>
		<p>
				<font size="3">　　例如，该Hashtable可能是由MyServer类型的对象在名为activeSessions的字段中引用的。这种信息通常就足以查找源代码以定位问题所在了。 </font>
		</p>
		<p>
				<font size="3">
						<img src="http://dev2dev.bea.com/images/2005/06/mem_leak_010.gif" align="bottom" border="0" hspace="0" />
						<br />图7. 检查对象以及它对其他对象的引用</font>
		</p>
		<p>
				<font size="3">找出分配位置</font>
		</p>
		<p>
				<font size="3">　
　当跟踪内存泄漏问题时，查看对象分配到哪里是很有用的。只知道它们如何与其他对象相关联（即哪些对象引用了它们）是不够的，关于它们在何处创建的信息也
很有用。当然了，您并不想创建应用程序的辅助构件，以打印每次分配的堆栈跟踪(stack
trace)。您也不想仅仅为了跟踪内存泄漏而在运行应用程序时将一个分析程序连接到生产环境中。</font>
		</p>
		<p>
				<font size="3">　
　借助于JRockit Memory Leak
Detector，应用程序中的代码可以在分配时进行动态添加，以创建堆栈跟踪。这些堆栈跟踪可以在工具中进行累积和分析。只要不启用就不会因该功能而产
生成本，这意味着随时可以进行分配跟踪。当请求分配跟踪时，JRockit
编译器动态插入代码以监控分配，但是只针对所请求的特定类。更好的是，在进行数据分析时，添加的代码全部被移除，代码中没有留下任何会引起应用程序性能降
低的更改。 </font>
		</p>
		<p>
				<font size="3">
						<img src="http://dev2dev.bea.com/images/2005/06/mem_leak_011.gif" align="bottom" border="0" hspace="0" />
						<br />图8. 示例程序执行期间String的分配的堆栈跟踪</font>
		</p>
		<p>
				<font size="3">结束语</font>
		</p>
		<p>
				<font size="3">　　内存泄漏是难以发现的。本文重点介绍了几种避免内存泄漏的最佳实践，包括要始终记住在数据结构中所放置的内容，以及密切监控内存使用量以发现突然的增长。</font>
		</p>
		<font size="3">　
　我们都已经看到了JRockit Memory Leak
Detector是如何用于生产中的系统以跟踪内存泄漏的。该工具使用一种三步式的方法来找出泄漏。首先，进行趋势分析，找出是哪个类的对象在泄漏。接下
来，看看有哪些其他的类与泄漏的类的对象相关联。最后，进一步研究单个对象，看看它们是如何互相关联的。也有可能对系统中所有对象分配进行动态的堆栈跟
踪。这些功能以及该工具紧密集成到JVM中的特性使您可以以一种安全而强大的方式跟踪内存泄漏并进行修复。<br /></font>
<img src ="http://www.blogjava.net/Duffblog/aggbug/50044.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-06-02 19:17 <a href="http://www.blogjava.net/Duffblog/articles/50044.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Apache commons (转)</title><link>http://www.blogjava.net/Duffblog/articles/49201.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Wed, 31 May 2006 03:11:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/49201.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/49201.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/49201.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/49201.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/49201.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Apache commons之各种武器 								Apache Commons 				是一个非常有用的工具包，解决各种实际的通用问题，你会发现它们正是你冥思苦想所需要的东西。它们不是绝世武功，但确是个随手可用的擒拿手，				Commons				一出，问题手到擒来。																																		...&nbsp;&nbsp;<a href='http://www.blogjava.net/Duffblog/articles/49201.html'>阅读全文</a><img src ="http://www.blogjava.net/Duffblog/aggbug/49201.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-05-31 11:11 <a href="http://www.blogjava.net/Duffblog/articles/49201.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate hql(转)</title><link>http://www.blogjava.net/Duffblog/articles/46883.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Thu, 18 May 2006 12:01:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/46883.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/46883.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/46883.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/46883.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/46883.html</trackback:ping><description><![CDATA[
		<h2>
				<b>HQL: Hibernate查询语言</b>
		</h2>
		<p>Hibernate配备了一种非常强大的查询语言，这种语言看上去很像SQL。但是不要被语法结构 上的相似所迷惑，HQL是非常有意识的被设计为完全面向对象的查询，它可以理解如继承、多态 和关联之类的概念。 </p>
		<p>
		</p>
		<div class="titlepage">
				<div>
						<div>
								<h2 class="title">
										<a name="queryhql">
										</a>第 15 章 HQL: Hibernate查询语言</h2>
						</div>
				</div>
		</div>
		<p>Hibernate配备了一种非常强大的查询语言，这种语言看上去很像SQL。但是不要被语法结构 上的相似所迷惑，HQL是非常有意识的被设计为完全面向对象的查询，它可以理解如继承、多态 和关联之类的概念。 </p>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-casesensitivity">
												</a>15.1. 大小写敏感性问题</h2>
								</div>
						</div>
				</div>
				<p>除了Java类与属性的名称外，查询语句对大小写并不敏感。 所以 <tt class="literal"><font face="新宋体">SeLeCT</font></tt> 与 <tt class="literal"><font face="新宋体">sELEct</font></tt> 以及 <tt class="literal"><font face="新宋体">SELECT</font></tt> 是相同的，但是 <tt class="literal"><font face="新宋体">org.hibernate.eg.FOO</font></tt> 并不等价于 <tt class="literal"><font face="新宋体">org.hibernate.eg.Foo</font></tt> 并且 <tt class="literal"><font face="新宋体">foo.barSet</font></tt> 也不等价于 <tt class="literal"><font face="新宋体">foo.BARSET</font></tt>。 </p>
				<p>本手册中的HQL关键字将使用小写字母. 很多用户发现使用完全大写的关键字会使查询语句 的可读性更强, 但我们发现，当把查询语句嵌入到Java语句中的时候使用大写关键字比较难看。 </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-from">
												</a>15.2. from子句</h2>
								</div>
						</div>
				</div>
				<p>Hibernate中最简单的查询语句的形式如下： </p>
				<pre class="programlisting">from eg.Cat</pre>
				<p>该子句简单的返回<tt class="literal"><font face="新宋体">eg.Cat</font></tt>类的所有实例。 通常我们不需要使用类的全限定名, 因为 <tt class="literal"><font face="新宋体">auto-import</font></tt>（自动引入） 是缺省的情况。 所以我们几乎只使用如下的简单写法： </p>
				<pre class="programlisting">from Cat</pre>
				<p>大多数情况下, 你需要指定一个<span class="emphasis"><em>别名</em></span>, 原因是你可能需要 在查询语句的其它部分引用到<tt class="literal"><font face="新宋体">Cat</font></tt></p>
				<pre class="programlisting">from Cat as cat</pre>
				<p>这个语句把别名<tt class="literal"><font face="新宋体">cat</font></tt>指定给类<tt class="literal"><font face="新宋体">Cat</font></tt> 的实例, 这样我们就可以在随后的查询中使用此别名了。 关键字<tt class="literal"><font face="新宋体">as</font></tt> 是可选的，我们也可以这样写: </p>
				<pre class="programlisting">from Cat cat</pre>
				<p>子句中可以同时出现多个类, 其查询结果是产生一个笛卡儿积或产生跨表的连接。 </p>
				<pre class="programlisting">from Formula, Parameter</pre>
				<pre class="programlisting">from Formula as form, Parameter as param</pre>
				<p>查询语句中别名的开头部分小写被认为是实践中的好习惯， 这样做与Java变量的命名标准保持了一致 (比如，<tt class="literal"><font face="新宋体">domesticCat</font></tt>)。 </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-joins">
												</a>15.3. 关联(Association)与连接(Join)</h2>
								</div>
						</div>
				</div>
				<p>我们也可以为相关联的实体甚至是对一个集合中的全部元素指定一个别名, 这时要使用关键字<tt class="literal"><font face="新宋体">join</font></tt>。 </p>
				<pre class="programlisting">from Cat as cat <br />    inner join cat.mate as mate<br />    left outer join cat.kittens as kitten</pre>
				<pre class="programlisting">from Cat as cat left join cat.mate.kittens as kittens</pre>
				<pre class="programlisting">from Formula form full join form.parameter param</pre>
				<p>受支持的连接类型是从ANSI SQL中借鉴来的。 </p>
				<div class="itemizedlist">
						<ul compact="compact" type="disc">
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">inner join</font>
												</tt>（内连接） </p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">left outer join</font>
												</tt>（左外连接） </p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">right outer join</font>
												</tt>（右外连接） </p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">full join</font>
												</tt> (全连接，并不常用) </p>
								</li>
						</ul>
				</div>
				<p>语句<tt class="literal"><font face="新宋体">inner join</font></tt>, <tt class="literal"><font face="新宋体">left outer join</font></tt> 以及 <tt class="literal"><font face="新宋体">right outer join</font></tt> 可以简写。 </p>
				<pre class="programlisting">from Cat as cat <br />    join cat.mate as mate<br />    left join cat.kittens as kitten</pre>
				<p>还有，一个"fetch"连接允许仅仅使用一个选择语句就将相关联的对象或一组值的集合随着他们的父对象的初始化而被初始化，这种方法在使用到集合
的情况下尤其有用，对于关联和集合来说，它有效的代替了映射文件中的外联接 与延迟声明（lazy declarations）. 查看 <a title="20.1. &#xD;&#xA;	&#xD;&#xA;			抓取策略(Fetching strategies)" href="http://www.hibernate.org/hib_docs/v3/reference/zh-cn/html/performance.html#performance-fetching"><font color="#336699">第 20.1 节 “ 抓取策略(Fetching strategies) ”</font></a> 以获得等多的信息。 </p>
				<pre class="programlisting">from Cat as cat <br />    inner join fetch cat.mate<br />    left join fetch cat.kittens</pre>
				<p>一个fetch连接通常不需要被指定别名, 因为相关联的对象不应当被用在 <tt class="literal"><font face="新宋体">where</font></tt> 子句 (或其它任何子句)中。同时，相关联的对象 并不在查询的结果中直接返回，但可以通过他们的父对象来访问到他们。 </p>
				<p>注意<tt class="literal"><font face="新宋体">fetch</font></tt>构造变量在使用了<tt class="literal"><font face="新宋体">scroll()</font></tt> 或 <tt class="literal"><font face="新宋体">iterate()</font></tt>函数 的查询中是不能使用的。最后注意，使用<tt class="literal"><font face="新宋体">full join fetch</font></tt> 与 <tt class="literal"><font face="新宋体">right join fetch</font></tt>是没有意义的。 </p>
				<p>如果你使用属性级别的延迟获取（lazy fetching）（这是通过重新编写字节码实现的），可以使用 <tt class="literal"><font face="新宋体">fetch all properties</font></tt> 来强制Hibernate立即取得那些原本需要延迟加载的属性（在第一个查询中）。 </p>
				<pre class="programlisting">from Document fetch all properties order by name</pre>
				<pre class="programlisting">from Document doc fetch all properties where lower(doc.name) like '%cats%'</pre>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-select">
												</a>15.4. select子句</h2>
								</div>
						</div>
				</div>
				<p>
						<tt class="literal">
								<font face="新宋体">select</font>
						</tt> 子句选择将哪些对象与属性返 回到查询结果集中. 考虑如下情况: </p>
				<pre class="programlisting">select mate <br />from Cat as cat <br />    inner join cat.mate as mate</pre>
				<p>该语句将选择<tt class="literal"><font face="新宋体">mate</font></tt>s of other <tt class="literal"><font face="新宋体">Cat</font></tt>s。（其他猫的配偶） 实际上, 你可以更简洁的用以下的查询语句表达相同的含义: </p>
				<pre class="programlisting">select cat.mate from Cat cat</pre>
				<p>查询语句可以返回值为任何类型的属性，包括返回类型为某种组件(Component)的属性: </p>
				<pre class="programlisting">select cat.name from DomesticCat cat<br />where cat.name like 'fri%'</pre>
				<pre class="programlisting">select cust.name.firstName from Customer as cust</pre>
				<p>查询语句可以返回多个对象和（或）属性，存放在 <tt class="literal"><font face="新宋体">Object[]</font></tt>队列中, </p>
				<pre class="programlisting">select mother, offspr, mate.name <br />from DomesticCat as mother<br />    inner join mother.mate as mate<br />    left outer join mother.kittens as offspr</pre>
				<p>或存放在一个<tt class="literal"><font face="新宋体">List</font></tt>对象中, </p>
				<pre class="programlisting">select new list(mother, offspr, mate.name)<br />from DomesticCat as mother<br />    inner join mother.mate as mate<br />    left outer join mother.kittens as offspr</pre>
				<p>也可能直接返回一个实际的类型安全的Java对象, </p>
				<pre class="programlisting">select new Family(mother, mate, offspr)<br />from DomesticCat as mother<br />    join mother.mate as mate<br />    left join mother.kittens as offspr</pre>
				<p>假设类<tt class="literal"><font face="新宋体">Family</font></tt>有一个合适的构造函数. </p>
				<p>你可以使用关键字<tt class="literal"><font face="新宋体">as</font></tt>给“被选择了的表达式”指派别名: </p>
				<pre class="programlisting">select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n<br />from Cat cat</pre>
				<p>这种做法在与子句<tt class="literal"><font face="新宋体">select new map</font></tt>一起使用时最有用: </p>
				<pre class="programlisting">select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )<br />from Cat cat</pre>
				<p>该查询返回了一个<tt class="literal"><font face="新宋体">Map</font></tt>的对象，内容是别名与被选择的值组成的名-值映射。 </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-aggregation">
												</a>15.5. 聚集函数</h2>
								</div>
						</div>
				</div>
				<p>HQL查询甚至可以返回作用于属性之上的聚集函数的计算结果: </p>
				<pre class="programlisting">select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)<br />from Cat cat</pre>
				<p>受支持的聚集函数如下： </p>
				<div class="itemizedlist">
						<ul compact="compact" type="disc">
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">avg(...), sum(...), min(...), max(...)</font>
												</tt>
										</p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">count(*)</font>
												</tt>
										</p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">count(...), count(distinct ...), count(all...)</font>
												</tt>
										</p>
								</li>
						</ul>
				</div>
				<p>你可以在选择子句中使用数学操作符、连接以及经过验证的SQL函数： </p>
				<pre class="programlisting">select cat.weight + sum(kitten.weight) <br />from Cat cat <br />    join cat.kittens kitten<br />group by cat.id, cat.weight</pre>
				<pre class="programlisting">select firstName||' '||initial||' '||upper(lastName) from Person</pre>
				<p>关键字<tt class="literal"><font face="新宋体">distinct</font></tt>与<tt class="literal"><font face="新宋体">all</font></tt> 也可以使用，它们具有与SQL相同的语义. </p>
				<pre class="programlisting">select distinct cat.name from Cat cat<br /><br />select count(distinct cat.name), count(cat) from Cat cat</pre>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-polymorphism">
												</a>15.6. 多态查询</h2>
								</div>
						</div>
				</div>
				<p>一个如下的查询语句: </p>
				<pre class="programlisting">from Cat as cat</pre>
				<p>不仅返回<tt class="literal"><font face="新宋体">Cat</font></tt>类的实例, 也同时返回子类 <tt class="literal"><font face="新宋体">DomesticCat</font></tt>的实例. Hibernate 可以在<tt class="literal"><font face="新宋体">from</font></tt>子句中指定<span class="emphasis"><em>任何</em></span> Java 类或接口. 查询会返回继承了该类的所有持久化子类 的实例或返回声明了该接口的所有持久化类的实例。下面的查询语句返回所有的被持久化的对象： </p>
				<pre class="programlisting">from java.lang.Object o</pre>
				<p>接口<tt class="literal"><font face="新宋体">Named</font></tt> 可能被各种各样的持久化类声明： </p>
				<pre class="programlisting">from Named n, Named m where n.name = m.name</pre>
				<p>注意，最后的两个查询将需要超过一个的SQL <tt class="literal"><font face="新宋体">SELECT</font></tt>.这表明<tt class="literal"><font face="新宋体">order by</font></tt>子句 没有对整个结果集进行正确的排序. (这也说明你不能对这样的查询使用<tt class="literal"><font face="新宋体">Query.scroll()</font></tt>方法.) </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-where">
												</a>15.7. where子句</h2>
								</div>
						</div>
				</div>
				<p>
						<tt class="literal">
								<font face="新宋体">where</font>
						</tt>子句允许你将返回的实例列表的范围缩小. 如果没有指定别名，你可以使用属性名来直接引用属性: </p>
				<pre class="programlisting">from Cat where name='Fritz'</pre>
				<p>如果指派了别名，需要使用完整的属性名: </p>
				<pre class="programlisting">from Cat as cat where cat.name='Fritz'</pre>
				<p>返回名为（属性name等于）'Fritz'的<tt class="literal"><font face="新宋体">Cat</font></tt>类的实例。 </p>
				<pre class="programlisting">select foo <br />from Foo foo, Bar bar<br />where foo.startDate = bar.date</pre>
				<p>将返回所有满足下面条件的<tt class="literal"><font face="新宋体">Foo</font></tt>类的实例： 存在如下的<tt class="literal"><font face="新宋体">bar</font></tt>的一个实例，其<tt class="literal"><font face="新宋体">date</font></tt>属性等于 <tt class="literal"><font face="新宋体">Foo</font></tt>的<tt class="literal"><font face="新宋体">startDate</font></tt>属性。 复合路径表达式使得<tt class="literal"><font face="新宋体">where</font></tt>子句非常的强大，考虑如下情况： </p>
				<pre class="programlisting">from Cat cat where cat.mate.name is not null</pre>
				<p>该查询将被翻译成为一个含有表连接（内连接）的SQL查询。如果你打算写像这样的查询语句 </p>
				<pre class="programlisting">from Foo foo  <br />where foo.bar.baz.customer.address.city is not null</pre>
				<p>在SQL中，你为达此目的将需要进行一个四表连接的查询。 </p>
				<p>
						<tt class="literal">
								<font face="新宋体">=</font>
						</tt>运算符不仅可以被用来比较属性的值，也可以用来比较实例： </p>
				<pre class="programlisting">from Cat cat, Cat rival where cat.mate = rival.mate</pre>
				<pre class="programlisting">select cat, mate <br />from Cat cat, Cat mate<br />where cat.mate = mate</pre>
				<p>特殊属性（小写）<tt class="literal"><font face="新宋体">id</font></tt>可以用来表示一个对象的唯一的标识符。（你也可以使用该对象的属性名。） </p>
				<pre class="programlisting">from Cat as cat where cat.id = 123<br /><br />from Cat as cat where cat.mate.id = 69</pre>
				<p>第二个查询是有效的。此时不需要进行表连接！ </p>
				<p>同样也可以使用复合标识符。比如<tt class="literal"><font face="新宋体">Person</font></tt>类有一个复合标识符，它由<tt class="literal"><font face="新宋体">country</font></tt>属性 与<tt class="literal"><font face="新宋体">medicareNumber</font></tt>属性组成。 </p>
				<pre class="programlisting">from bank.Person person<br />where person.id.country = 'AU' <br />    and person.id.medicareNumber = 123456</pre>
				<pre class="programlisting">from bank.Account account<br />where account.owner.id.country = 'AU' <br />    and account.owner.id.medicareNumber = 123456</pre>
				<p>第二个查询也不需要进行表连接。 </p>
				<p>同样的，特殊属性<tt class="literal"><font face="新宋体">class</font></tt>在进行多态持久化的情况下被用来存取一个实例的鉴别值（discriminator value）。 一个嵌入到where子句中的Java类的名字将被转换为该类的鉴别值。 </p>
				<pre class="programlisting">from Cat cat where cat.class = DomesticCat</pre>
				<p>你也可以声明一个属性的类型是组件或者复合用户类型（以及由组件构成的组件等等）。永远不要尝试使用以组件类型来结尾的路径表达式（path-expression） （与此相反，你应当使用组件的一个属性来结尾）。 举例来说，如果<tt class="literal"><font face="新宋体">store.owner</font></tt>含有一个包含了组件的实体<tt class="literal"><font face="新宋体">address</font></tt></p>
				<pre class="programlisting">store.owner.address.city    // 正确<br />store.owner.address         // 错误!</pre>
				<p>一个“任意”类型有两个特殊的属性<tt class="literal"><font face="新宋体">id</font></tt>和<tt class="literal"><font face="新宋体">class</font></tt>, 来允许我们按照下面的方式表达一个连接（<tt class="literal"><font face="新宋体">AuditLog.item</font></tt> 是一个属性，该属性被映射为<tt class="literal"><font face="新宋体">&lt;any&gt;</font></tt>）。 </p>
				<pre class="programlisting">from AuditLog log, Payment payment <br />where log.item.class = 'Payment' and log.item.id = payment.id</pre>
				<p>注意，在上面的查询与句中，<tt class="literal"><font face="新宋体">log.item.class</font></tt> 和 <tt class="literal"><font face="新宋体">payment.class</font></tt> 将涉及到完全不同的数据库中的列。 </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-expressions">
												</a>15.8. 表达式</h2>
								</div>
						</div>
				</div>
				<p>在<tt class="literal"><font face="新宋体">where</font></tt>子句中允许使用的表达式包括 大多数你可以在SQL使用的表达式种类: </p>
				<div class="itemizedlist">
						<ul compact="compact" type="disc">
								<li>
										<p>数学运算符<tt class="literal"><font face="新宋体">+, -, *, /</font></tt></p>
								</li>
								<li>
										<p>二进制比较运算符<tt class="literal"><font face="新宋体">=, &gt;=, &lt;=, &lt;&gt;, !=, like</font></tt></p>
								</li>
								<li>
										<p>逻辑运算符<tt class="literal"><font face="新宋体">and, or, not</font></tt></p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">in</font>
												</tt>, <tt class="literal"><font face="新宋体">not in</font></tt>, <tt class="literal"><font face="新宋体">between</font></tt>, <tt class="literal"><font face="新宋体">is null</font></tt>, <tt class="literal"><font face="新宋体">is not null</font></tt>, <tt class="literal"><font face="新宋体">is empty</font></tt>, <tt class="literal"><font face="新宋体">is not empty</font></tt>, <tt class="literal"><font face="新宋体">member of</font></tt> and <tt class="literal"><font face="新宋体">not member of</font></tt></p>
								</li>
								<li>
										<p>"简单的" case, <tt class="literal"><font face="新宋体">case ... when ... then ... else ... end</font></tt>,和 "搜索" case, <tt class="literal"><font face="新宋体">case when ... then ... else ... end</font></tt></p>
								</li>
								<li>
										<p>字符串连接符<tt class="literal"><font face="新宋体">...||...</font></tt> or <tt class="literal"><font face="新宋体">concat(...,...)</font></tt></p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">current_date()</font>
												</tt>, <tt class="literal"><font face="新宋体">current_time()</font></tt>, <tt class="literal"><font face="新宋体">current_timestamp()</font></tt></p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">second(...)</font>
												</tt>, <tt class="literal"><font face="新宋体">minute(...)</font></tt>, <tt class="literal"><font face="新宋体">hour(...)</font></tt>, <tt class="literal"><font face="新宋体">day(...)</font></tt>, <tt class="literal"><font face="新宋体">month(...)</font></tt>, <tt class="literal"><font face="新宋体">year(...)</font></tt>, </p>
								</li>
								<li>
										<p>EJB-QL 3.0定义的任何函数或操作：<tt class="literal"><font face="新宋体">substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length()</font></tt></p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">coalesce()</font>
												</tt> 和 <tt class="literal"><font face="新宋体">nullif()</font></tt></p>
								</li>
								<li>
										<p>
												<tt class="literal">
														<font face="新宋体">cast(... as ...)</font>
												</tt>, 其第二个参数是某Hibernate类型的名字，以及<tt class="literal"><font face="新宋体">extract(... from ...)</font></tt>，只要ANSI <tt class="literal"><font face="新宋体">cast()</font></tt> 和 <tt class="literal"><font face="新宋体">extract()</font></tt> 被底层数据库支持 </p>
								</li>
								<li>
										<p>任何数据库支持的SQL标量函数，比如<tt class="literal"><font face="新宋体">sign()</font></tt>, <tt class="literal"><font face="新宋体">trunc()</font></tt>, <tt class="literal"><font face="新宋体">rtrim()</font></tt>, <tt class="literal"><font face="新宋体">sin()</font></tt></p>
								</li>
								<li>
										<p>JDBC参数传入 <tt class="literal"><font face="新宋体">?</font></tt></p>
								</li>
								<li>
										<p>命名参数<tt class="literal"><font face="新宋体">:name</font></tt>, <tt class="literal"><font face="新宋体">:start_date</font></tt>, <tt class="literal"><font face="新宋体">:x1</font></tt></p>
								</li>
								<li>
										<p>SQL 直接常量 <tt class="literal"><font face="新宋体">'foo'</font></tt>, <tt class="literal"><font face="新宋体">69</font></tt>, <tt class="literal"><font face="新宋体">'1970-01-01 10:00:01.0'</font></tt></p>
								</li>
								<li>
										<p>Java <tt class="literal"><font face="新宋体">public static final</font></tt> 类型的常量 <tt class="literal"><font face="新宋体">eg.Color.TABBY</font></tt></p>
								</li>
						</ul>
				</div>
				<p>关键字<tt class="literal"><font face="新宋体">in</font></tt>与<tt class="literal"><font face="新宋体">between</font></tt>可按如下方法使用: </p>
				<pre class="programlisting">from DomesticCat cat where cat.name between 'A' and 'B'</pre>
				<pre class="programlisting">from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )</pre>
				<p>而且否定的格式也可以如下书写： </p>
				<pre class="programlisting">from DomesticCat cat where cat.name not between 'A' and 'B'</pre>
				<pre class="programlisting">from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )</pre>
				<p>同样, 子句<tt class="literal"><font face="新宋体">is null</font></tt>与<tt class="literal"><font face="新宋体">is not null</font></tt>可以被用来测试空值(null). </p>
				<p>在Hibernate配置文件中声明HQL“查询替代（query substitutions）”之后， 布尔表达式（Booleans）可以在其他表达式中轻松的使用: </p>
				<pre class="programlisting">&lt;property name="hibernate.query.substitutions"&gt;true 1, false 0&lt;/property&gt;</pre>
				<p>系统将该HQL转换为SQL语句时，该设置表明将用字符 <tt class="literal"><font face="新宋体">1</font></tt> 和 <tt class="literal"><font face="新宋体">0</font></tt> 来 取代关键字<tt class="literal"><font face="新宋体">true</font></tt> 和 <tt class="literal"><font face="新宋体">false</font></tt>: </p>
				<pre class="programlisting">from Cat cat where cat.alive = true</pre>
				<p>你可以用特殊属性<tt class="literal"><font face="新宋体">size</font></tt>, 或是特殊函数<tt class="literal"><font face="新宋体">size()</font></tt>测试一个集合的大小。 </p>
				<pre class="programlisting">from Cat cat where cat.kittens.size &gt; 0</pre>
				<pre class="programlisting">from Cat cat where size(cat.kittens) &gt; 0</pre>
				<p>对于索引了（有序）的集合，你可以使用<tt class="literal"><font face="新宋体">minindex</font></tt> 与 <tt class="literal"><font face="新宋体">maxindex</font></tt>函数来引用到最小与最大的索引序数。 同理，你可以使用<tt class="literal"><font face="新宋体">minelement</font></tt> 与 <tt class="literal"><font face="新宋体">maxelement</font></tt>函数来 引用到一个基本数据类型的集合中最小与最大的元素。 </p>
				<pre class="programlisting">from Calendar cal where maxelement(cal.holidays) &gt; current date</pre>
				<pre class="programlisting">from Order order where maxindex(order.items) &gt; 100</pre>
				<pre class="programlisting">from Order order where minelement(order.items) &gt; 10000</pre>
				<p>在传递一个集合的索引集或者是元素集(<tt class="literal"><font face="新宋体">elements</font></tt>与<tt class="literal"><font face="新宋体">indices</font></tt> 函数) 或者传递一个子查询的结果的时候，可以使用SQL函数<tt class="literal"><font face="新宋体">any, some, all, exists, in</font></tt></p>
				<pre class="programlisting">select mother from Cat as mother, Cat as kit<br />where kit in elements(foo.kittens)</pre>
				<pre class="programlisting">select p from NameList list, Person p<br />where p.name = some elements(list.names)</pre>
				<pre class="programlisting">from Cat cat where exists elements(cat.kittens)</pre>
				<pre class="programlisting">from Player p where 3 &gt; all elements(p.scores)</pre>
				<pre class="programlisting">from Show show where 'fizard' in indices(show.acts)</pre>
				<p>注意，在Hibernate3种，这些结构变量- <tt class="literal"><font face="新宋体">size</font></tt>, <tt class="literal"><font face="新宋体">elements</font></tt>, <tt class="literal"><font face="新宋体">indices</font></tt>, <tt class="literal"><font face="新宋体">minindex</font></tt>, <tt class="literal"><font face="新宋体">maxindex</font></tt>, <tt class="literal"><font face="新宋体">minelement</font></tt>, <tt class="literal"><font face="新宋体">maxelement</font></tt> - 只能在where子句中使用。 </p>
				<p>一个被索引过的（有序的）集合的元素(arrays, lists, maps)可以在其他索引中被引用（只能在where子句中）： </p>
				<pre class="programlisting">from Order order where order.items[0].id = 1234</pre>
				<pre class="programlisting">select person from Person person, Calendar calendar<br />where calendar.holidays['national day'] = person.birthDay<br />    and person.nationality.calendar = calendar</pre>
				<pre class="programlisting">select item from Item item, Order order<br />where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11</pre>
				<pre class="programlisting">select item from Item item, Order order<br />where order.items[ maxindex(order.items) ] = item and order.id = 11</pre>
				<p>在<tt class="literal"><font face="新宋体">[]</font></tt>中的表达式甚至可以是一个算数表达式。 </p>
				<pre class="programlisting">select item from Item item, Order order<br />where order.items[ size(order.items) - 1 ] = item</pre>
				<p>对于一个一对多的关联（one-to-many association）或是值的集合中的元素， HQL也提供内建的<tt class="literal"><font face="新宋体">index()</font></tt>函数， </p>
				<pre class="programlisting">select item, index(item) from Order order <br />    join order.items item<br />where index(item) &lt; 5</pre>
				<p>如果底层数据库支持标量的SQL函数，它们也可以被使用 </p>
				<pre class="programlisting">from DomesticCat cat where upper(cat.name) like 'FRI%'</pre>
				<p>如果你还不能对所有的这些深信不疑，想想下面的查询。如果使用SQL，语句长度会增长多少，可读性会下降多少： </p>
				<pre class="programlisting">select cust<br />from Product prod,<br />    Store store<br />    inner join store.customers cust<br />where prod.name = 'widget'<br />    and store.location.name in ( 'Melbourne', 'Sydney' )<br />    and prod = all elements(cust.currentOrder.lineItems)</pre>
				<p>
						<span class="emphasis">
								<em>提示:</em>
						</span> 会像如下的语句 </p>
				<pre class="programlisting">SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order<br />FROM customers cust,<br />    stores store,<br />    locations loc,<br />    store_customers sc,<br />    product prod<br />WHERE prod.name = 'widget'<br />    AND store.loc_id = loc.id<br />    AND loc.name IN ( 'Melbourne', 'Sydney' )<br />    AND sc.store_id = store.id<br />    AND sc.cust_id = cust.id<br />    AND prod.id = ALL(<br />        SELECT item.prod_id<br />        FROM line_items item, orders o<br />        WHERE item.order_id = o.id<br />            AND cust.current_order = o.id<br />    )</pre>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-ordering">
												</a>15.9. order by子句</h2>
								</div>
						</div>
				</div>
				<p>查询返回的列表(list)可以按照一个返回的类或组件（components)中的任何属性（property）进行排序： </p>
				<pre class="programlisting">from DomesticCat cat<br />order by cat.name asc, cat.weight desc, cat.birthdate</pre>
				<p>可选的<tt class="literal"><font face="新宋体">asc</font></tt>或<tt class="literal"><font face="新宋体">desc</font></tt>关键字指明了按照升序或降序进行排序. </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-grouping">
												</a>15.10. group by子句</h2>
								</div>
						</div>
				</div>
				<p>一个返回聚集值(aggregate values)的查询可以按照一个返回的类或组件（components)中的任何属性（property）进行分组： </p>
				<pre class="programlisting">select cat.color, sum(cat.weight), count(cat) <br />from Cat cat<br />group by cat.color</pre>
				<pre class="programlisting">select foo.id, avg(name), max(name) <br />from Foo foo join foo.names name<br />group by foo.id</pre>
				<p>
						<tt class="literal">
								<font face="新宋体">having</font>
						</tt>子句在这里也允许使用. </p>
				<pre class="programlisting">select cat.color, sum(cat.weight), count(cat) <br />from Cat cat<br />group by cat.color <br />having cat.color in (eg.Color.TABBY, eg.Color.BLACK)</pre>
				<p>如果底层的数据库支持的话(例如不能在MySQL中使用)，SQL的一般函数与聚集函数也可以出现 在<tt class="literal"><font face="新宋体">having</font></tt>与<tt class="literal"><font face="新宋体">order by</font></tt> 子句中。 </p>
				<pre class="programlisting">select cat<br />from Cat cat<br />    join cat.kittens kitten<br />group by cat<br />having avg(kitten.weight) &gt; 100<br />order by count(kitten) asc, sum(kitten.weight) desc</pre>
				<p>注意<tt class="literal"><font face="新宋体">group by</font></tt>子句与 <tt class="literal"><font face="新宋体">order by</font></tt>子句中都不能包含算术表达式（arithmetic expressions）. </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-subqueries">
												</a>15.11. 子查询</h2>
								</div>
						</div>
				</div>
				<p>对于支持子查询的数据库，Hibernate支持在查询中使用子查询。一个子查询必须被圆括号包围起来（经常是SQL聚集函数的圆括号）。 甚至相互关联的子查询（引用到外部查询中的别名的子查询）也是允许的。 </p>
				<pre class="programlisting">from Cat as fatcat <br />where fatcat.weight &gt; ( <br />    select avg(cat.weight) from DomesticCat cat <br />)</pre>
				<pre class="programlisting">from DomesticCat as cat <br />where cat.name = some ( <br />    select name.nickName from Name as name <br />)</pre>
				<pre class="programlisting">from Cat as cat <br />where not exists ( <br />    from Cat as mate where mate.mate = cat <br />)</pre>
				<pre class="programlisting">from DomesticCat as cat <br />where cat.name not in ( <br />    select name.nickName from Name as name <br />)</pre>
				<p>在select列表中包含一个表达式以上的子查询，你可以使用一个元组构造符（tuple constructors）： </p>
				<pre class="programlisting">from Cat as cat <br />where not ( cat.name, cat.color ) in ( <br />    select cat.name, cat.color from DomesticCat cat <br />)</pre>
				<p>注意在某些数据库中（不包括Oracle与HSQL），你也可以在其他语境中使用元组构造符， 比如查询用户类型的组件与组合： </p>
				<pre class="programlisting">from Person where name = ('Gavin', 'A', 'King')</pre>
				<p>该查询等价于更复杂的： </p>
				<pre class="programlisting">from Person where name.first = 'Gavin' and name.initial = 'A' and name.last = 'King')</pre>
				<p>有两个很好的理由使你不应当作这样的事情：首先，它不完全适用于各个数据库平台；其次，查询现在依赖于映射文件中属性的顺序。 </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-examples">
												</a>15.12. HQL示例</h2>
								</div>
						</div>
				</div>
				<p>Hibernate查询可以非常的强大与复杂。实际上，Hibernate的一个主要卖点就是查询语句的威力。这里有一些例子，它们与我在最近的 一个项目中使用的查询非常相似。注意你能用到的大多数查询比这些要简单的多！ </p>
				<p>下面的查询对于某个特定的客户的所有未支付的账单，在给定给最小总价值的情况下，返回订单的id，条目的数量和总价值， 返回值按照总价值的结果进行排序。为了决定价格，查询使用了当前目录。作为转换结果的SQL查询，使用了<tt class="literal"><font face="新宋体">ORDER</font></tt>, <tt class="literal"><font face="新宋体">ORDER_LINE</font></tt>, <tt class="literal"><font face="新宋体">PRODUCT</font></tt>, <tt class="literal"><font face="新宋体">CATALOG</font></tt> 和<tt class="literal"><font face="新宋体">PRICE</font></tt> 库表。 </p>
				<pre class="programlisting">select order.id, sum(price.amount), count(item)<br />from Order as order<br />    join order.lineItems as item<br />    join item.product as product,<br />    Catalog as catalog<br />    join catalog.prices as price<br />where order.paid = false<br />    and order.customer = :customer<br />    and price.product = product<br />    and catalog.effectiveDate &lt; sysdate<br />    and catalog.effectiveDate &gt;= all (<br />        select cat.effectiveDate <br />        from Catalog as cat<br />        where cat.effectiveDate &lt; sysdate<br />    )<br />group by order<br />having sum(price.amount) &gt; :minAmount<br />order by sum(price.amount) desc</pre>
				<p>这简直是一个怪物！实际上，在现实生活中，我并不热衷于子查询，所以我的查询语句看起来更像这个： </p>
				<pre class="programlisting">select order.id, sum(price.amount), count(item)<br />from Order as order<br />    join order.lineItems as item<br />    join item.product as product,<br />    Catalog as catalog<br />    join catalog.prices as price<br />where order.paid = false<br />    and order.customer = :customer<br />    and price.product = product<br />    and catalog = :currentCatalog<br />group by order<br />having sum(price.amount) &gt; :minAmount<br />order by sum(price.amount) desc</pre>
				<p>下面一个查询计算每一种状态下的支付的数目，除去所有处于<tt class="literal"><font face="新宋体">AWAITING_APPROVAL</font></tt>状态的支付，因为在该状态下 当前的用户作出了状态的最新改变。该查询被转换成含有两个内连接以及一个相关联的子选择的SQL查询，该查询使用了表 <tt class="literal"><font face="新宋体">PAYMENT</font></tt>, <tt class="literal"><font face="新宋体">PAYMENT_STATUS</font></tt> 以及 <tt class="literal"><font face="新宋体">PAYMENT_STATUS_CHANGE</font></tt>。 </p>
				<pre class="programlisting">select count(payment), status.name <br />from Payment as payment <br />    join payment.currentStatus as status<br />    join payment.statusChanges as statusChange<br />where payment.status.name &lt;&gt; PaymentStatus.AWAITING_APPROVAL<br />    or (<br />        statusChange.timeStamp = ( <br />            select max(change.timeStamp) <br />            from PaymentStatusChange change <br />            where change.payment = payment<br />        )<br />        and statusChange.user &lt;&gt; :currentUser<br />    )<br />group by status.name, status.sortOrder<br />order by status.sortOrder</pre>
				<p>如果我把<tt class="literal"><font face="新宋体">statusChanges</font></tt>实例集映射为一个列表（list）而不是一个集合（set）, 书写查询语句将更加简单. </p>
				<pre class="programlisting">select count(payment), status.name <br />from Payment as payment<br />    join payment.currentStatus as status<br />where payment.status.name &lt;&gt; PaymentStatus.AWAITING_APPROVAL<br />    or payment.statusChanges[ maxIndex(payment.statusChanges) ].user &lt;&gt; :currentUser<br />group by status.name, status.sortOrder<br />order by status.sortOrder</pre>
				<p>下面一个查询使用了MS SQL Server的 <tt class="literal"><font face="新宋体">isNull()</font></tt>函数用以返回当前用户所属组织的组织帐号及组织未支付的账。 它被转换成一个对表<tt class="literal"><font face="新宋体">ACCOUNT</font></tt>, <tt class="literal"><font face="新宋体">PAYMENT</font></tt>, <tt class="literal"><font face="新宋体">PAYMENT_STATUS</font></tt>, <tt class="literal"><font face="新宋体">ACCOUNT_TYPE</font></tt>, <tt class="literal"><font face="新宋体">ORGANIZATION</font></tt> 以及 <tt class="literal"><font face="新宋体">ORG_USER</font></tt>进行的三个内连接， 一个外连接和一个子选择的SQL查询。 </p>
				<pre class="programlisting">select account, payment<br />from Account as account<br />    left outer join account.payments as payment<br />where :currentUser in elements(account.holder.users)<br />    and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)<br />order by account.type.sortOrder, account.accountNumber, payment.dueDate</pre>
				<p>对于一些数据库，我们需要弃用（相关的）子选择。 </p>
				<pre class="programlisting">select account, payment<br />from Account as account<br />    join account.holder.users as user<br />    left outer join account.payments as payment<br />where :currentUser = user<br />    and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)<br />order by account.type.sortOrder, account.accountNumber, payment.dueDate</pre>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-bulk">
												</a>15.13. 批量的UPDATE &amp; DELETE语句</h2>
								</div>
						</div>
				</div>
				<p>HQL现在支持UPDATE与DELETE语句. 查阅 <a title="14.3. 大批量更新/删除（Bulk update/delete）" href="http://www.hibernate.org/hib_docs/v3/reference/zh-cn/html/batch.html#batch-direct"><font color="#336699">第 14.3 节 “大批量更新/删除（Bulk update/delete）”</font></a> 以获得更多信息。 </p>
		</div>
		<div class="sect1" lang="zh-cn">
				<div class="titlepage">
						<div>
								<div>
										<h2 class="title" style="clear: both;">
												<a name="queryhql-tipstricks">
												</a>15.14. 小技巧 &amp; 小窍门</h2>
								</div>
						</div>
				</div>
				<p>你可以统计查询结果的数目而不必实际的返回他们： </p>
				<pre class="programlisting">( (Integer) session.iterate("select count(*) from ....").next() ).intValue()</pre>
				<p>若想根据一个集合的大小来进行排序，可以使用如下的语句： </p>
				<pre class="programlisting">select usr.id, usr.name<br />from User as usr <br />    left join usr.messages as msg<br />group by usr.id, usr.name<br />order by count(msg)</pre>
				<p>如果你的数据库支持子选择，你可以在你的查询的where子句中为选择的大小（selection size）指定一个条件: </p>
				<pre class="programlisting">from User usr where size(usr.messages) &gt;= 1</pre>
				<p>如果你的数据库不支持子选择语句，使用下面的查询： </p>
				<pre class="programlisting">select usr.id, usr.name<br />from User usr.name<br />    join usr.messages msg<br />group by usr.id, usr.name<br />having count(msg) &gt;= 1</pre>
				<p>因为内连接（inner join）的原因，这个解决方案不能返回含有零个信息的<tt class="literal"><font face="新宋体">User</font></tt> 类的实例, 所以这种情况下使用下面的格式将是有帮助的: </p>
				<pre class="programlisting">select usr.id, usr.name<br />from User as usr<br />    left join usr.messages as msg<br />group by usr.id, usr.name<br />having count(msg) = 0</pre>
				<p>JavaBean的属性可以被绑定到一个命名查询（named query）的参数上： </p>
				<pre class="programlisting">Query q = s.createQuery("from foo Foo as foo where foo.name=:name and foo.size=:size");<br />q.setProperties(fooBean); // fooBean包含方法getName()与getSize()<br />List foos = q.list();</pre>
				<p>通过将接口<tt class="literal"><font face="新宋体">Query</font></tt>与一个过滤器（filter）一起使用，集合（Collections）是可以分页的： </p>
				<pre class="programlisting">Query q = s.createFilter( collection, "" ); // 一个简单的过滤器<br />q.setMaxResults(PAGE_SIZE);<br />q.setFirstResult(PAGE_SIZE * pageNumber);<br />List page = q.list();</pre>
				<p>通过使用查询过滤器（query filter）可以将集合（Collection）的原素分组或排序: </p>
				<pre class="programlisting">Collection orderedCollection = s.filter( collection, "order by this.amount" );<br />Collection counts = s.filter( collection, "select this.type, count(this) group by this.type" );</pre>
				<p>不用通过初始化，你就可以知道一个集合（Collection）的大小： </p>
				<pre class="programlisting">( (Integer) session.iterate("select count(*) from ....").next() ).intValue();</pre>
		</div>
<img src ="http://www.blogjava.net/Duffblog/aggbug/46883.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-05-18 20:01 <a href="http://www.blogjava.net/Duffblog/articles/46883.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 Tomcat 上配置虚拟主机（转）</title><link>http://www.blogjava.net/Duffblog/articles/45269.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Tue, 09 May 2006 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/45269.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/45269.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/45269.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/45269.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/45269.html</trackback:ping><description><![CDATA[天在论坛上看见有人问

如何将 IP 绑定到  Tomcat ，估计提问者是想实现虚拟主机的功能。什么是虚拟主机？虚拟主机是使用特殊的

软硬件技术，把一台计算机主机分成一台台"虚拟"的主机，每一台虚拟主机都具有独立的域名和 IP 地址(或共

享的 IP 地址)有完整的 Internet 服务器（WWW、FTP、Email等）功能。利用“虚拟主机”技术，每一台虚拟

主机和一台独立的主机完全一样，每一台虚拟主机都具有独立的域名,具有完整 Internet 服务器功能。
<p>
Tomcat 支持虚拟主机技术，不需要额外的插件，而且配置简单。 <br /></p><br /><h3>一 准备</h3>
我们将配置两台虚拟主机，假设域名分别为<br />

www.sentom1.net<br />
www.sentom2.net<br />

为了测试方便，请在客户机的:<br />
Win2K:\\WINNT\system32\drivers\etc\hosts<br />
Linux:/etc/hosts<br />
文件中增加下面内容，然后检查一下这两个域名是否解析正确。
<pre class="code">	192.168.0.1	www.sentom1.net<br />	192.168.0.1	www.sentom2.net<br /><br /></pre>
当然，在生产环境中这样做是不行的，需要的在 DNS 上做相应的域名解析。
<h3>二 Tomcat安装</h3>
Tomcat 的安装不在本文的讨论范围，请参考<a href="http://jakarta.apache.org/tomcat/tomcat-5.0-doc/setup.html" target="_blank"><font color="#3300cc">这里</font></a>。请确保Tomcat安装正确，不然请不要继续进行下面的配置步骤。<br /><br />
将 tomcat 目录下的 webapps 目录在同一目录复制一份，目录名分为 webapps2 ，然后将 webapps 目录改名

为 webapps1 。最后 tomcat 的目录结构大致如下：
<pre class="code">	tomcat<br />	   |--bin<br />	   |--common<br />	   |--conf<br />	   |--logs<br />	   |--server<br />	   |--shared<br />	   ......<br />	   |--webpapps1<br />	   |--webpapps2<br />	   |--work<br /><br /></pre>
最后，写一个简单 html 文件用于测试，文件名为 test.html ，文件内容如下：<br /><pre class="code">&lt;HTML&gt;<br />&lt;HEAD&gt;<br />&lt;TITLE&gt;测试&lt;/TITLE&gt;<br />&lt;/HEAD&gt;<br /><br />&lt;BODY&gt;<br />&lt;P align="center"&gt;你现在访问的是 &lt;FONT COLOR="#FF0000"&gt;<font color="#ff0000">www.sentom1.net</font>&lt;/FONT&gt;&lt;/P&gt;<br />&lt;/BODY&gt;<br />&lt;/HTML&gt;<br /></pre>
将 test.html 文件分别在 tomcat/webapps1/ROOT、tomcat/webapps2/ROOT 目录放置一份，然后将 

tomcat/webapps2/ROOT/test.html 文件内容中“www.sentom1.net”改为“www.sentom2.net”。<br /><br />
至此，前期的准备工作做完了，全是一些体力活。
<h3>三 配置虚拟主机</h3>
前面提到了独立 IP 和共享的 IP。本文介绍的是共享的 IP 模式，这种模式就是所有的虚拟主机都使用同一 

IP 。目前国内 IDC 提供的虚拟主机都是这种模式。这种模式的优点是节约数量有限的 IP ，缺点就是虚拟主

机只能通过域名访问而不能通过 IP 访问（其实也不算是缺点，只对邮件系统中用户的访问方式有一点点影响

）。而另外一种独立 IP 模式主要应用在邮件服务中，这里就不做介绍了。<br /><br />
配置 www.sentom1.net 虚拟主机<br /><br />
打开 tomcat/conf/server.xml 文件，将 Host 元素之间的内容全部删掉，然后把下面内容加如到 Host 元素

原来的位置。
<pre class="code">    &lt;Host name="<font color="#ff0000">www.sentom1.net</font>" debug="0" appBase="<font color="#ff0000">webapps1</font>"<br />             unpackWARs="true" autoDeploy="true"&gt;<br /><br />        &lt;Valve className="org.apache.catalina.valves.AccessLogValve"<br />                 directory="logs"  prefix="sentom1_access_log." suffix=".txt"<br />                 pattern="common" resolveHosts="false"/&gt;<br /><br />        &lt;Logger className="org.apache.catalina.logger.FileLogger"<br />                 directory="logs"  prefix="sentom1_log." suffix=".txt"<br />                 timestamp="true"/&gt;<br /><br />      &lt;/Host&gt;<br /></pre>
配置 www.sentom2.net 虚拟主机<br /><br />
将下面内容追加到 Host 元素后面，注意 Host 元素中 name 属性和 appBase 属性的值的变化。
<pre class="code">    &lt;Host name="<font color="#ff0000">www.sentom2.net</font>" debug="0" appBase="<font color="#ff0000">webapps2</font>"<br />             unpackWARs="true" autoDeploy="true"&gt;<br /><br />        &lt;Valve className="org.apache.catalina.valves.AccessLogValve"<br />                 directory="logs"  prefix="sentom2_access_log." suffix=".txt"<br />                 pattern="common" resolveHosts="false"/&gt;<br /><br />        &lt;Logger className="org.apache.catalina.logger.FileLogger"<br />                 directory="logs"  prefix="sentom2_log." suffix=".txt"<br />                 timestamp="true"/&gt;<br /><br />      &lt;/Host&gt;<br /></pre>
现在可以启动 Tomcat 了，分别访问<br />
http://www.sentom1.net:8080/test.html<br />
http://www.sentom2.net:8080/test.html<br />
如果访问得到的页面内容分别是下面的内容，那表明虚拟主机已经配置成功了。否则，请检查你的配置过程并

重新按照文档配置。
<pre class="code">你现在访问的是 <font color="#ff0000">www.sentom1.net</font></pre><pre class="code">你现在访问的是 <font color="#ff0000">www.sentom2.net</font></pre><h3>四 参考</h3><a href="http://jakarta.apache.org/tomcat/"><font color="#3300ff">http://jakarta.apache.org/tomcat/</font></a><p><br /></p><img src ="http://www.blogjava.net/Duffblog/aggbug/45269.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-05-09 19:43 <a href="http://www.blogjava.net/Duffblog/articles/45269.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java源码分析：深入探讨Iterator模式</title><link>http://www.blogjava.net/Duffblog/articles/45267.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Tue, 09 May 2006 11:20:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/45267.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/45267.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/45267.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/45267.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/45267.html</trackback:ping><description><![CDATA[
		<h4>正文</h4>
		<br />
		<p>java.util包中包含了一系列重要的集合类。本文将从分析源码入手，深入研究一个集合类的内部结构，以及遍历集合的迭代模式的源码实现内幕。</p>
		<p>下面我们先简单讨论一个根接口Collection，然后分析一个抽象类AbstractList和它的对应Iterator接口，并仔细研究迭代子模式的实现原理。</p>
		<p>本文讨论的源代码版本是JDK 1.4.2，因为JDK 1.5在java.util中使用了很多泛型代码，为了简化问题，所以我们还是讨论1.4版本的代码。</p>
		<h4>集合类的根接口Collection</h4>
		<br />
		<p>Collection接口是所有集合类的根类型。它的一个主要的接口方法是：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    boolean add(Object c)<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>add()方法将添加一个新元素。注意这个方法会返回一个boolean，但是返回值不是表示添加成功与否。仔细阅读doc可以看到，
Collection规定：如果一个集合拒绝添加这个元素，无论任何原因，都必须抛出异常。这个返回值表示的意义是add()方法执行后，集合的内容是否
改变了（就是元素有无数量，位置等变化），这是由具体类实现的。即：如果方法出错，总会抛出异常；返回值仅仅表示该方法执行后这个Collection的
内容有无变化。</p>
		<p>类似的还有：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    boolean addAll(Collection c);<br />    boolean remove(Object o);<br />    boolean removeAll(Collection c);<br />    boolean remainAll(Collection c);<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>Object[] toArray()方法很简单，把集合转换成数组返回。Object[] toArray(Object[] a)方法就有点复杂了，首先，返回的Object[]仍然是把集合的所有元素变成的数组，但是类型和参数a的类型是相同的，比如执行：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    String[] o = (String[])c.toArray(new String[0]);<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>得到的o实际类型是String[]。</p>
		<p>其次，如果参数a的大小装不下集合的所有元素，返回的将是一个新的数组。如果参数a的大小能装下集合的所有元素，则返回的还是a，但a的内容用集合的元素来填充。尤其要注意的是，如果a的大小比集合元素的个数还多，a后面的部分全部被置为null。</p>
		<p>最后一个最重要的方法是iterator()，返回一个Iterator（迭代子），用于遍历集合的所有元素。</p>
		<h4>用Iterator模式实现遍历集合</h4>
		<br />
		<p>Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来，从而避免向客户端暴露集合的内部结构。</p>
		<p>例如，如果没有使用Iterator，遍历一个数组的方法是使用索引：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    for(int i=0; i&lt;array.size(); i++) { ... get(i) ... }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>而访问一个链表（LinkedList）又必须使用while循环：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    while((e=e.next())!=null) { ... e.data() ... }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>以上两种方法客户端都必须事先知道集合的内部结构，访问代码和集合本身是紧耦合，无法将访问逻辑从集合类和客户端代码中分离出来，每一种集合对应一种遍历方法，客户端代码无法复用。</p>
		<p>更恐怖的是，如果以后需要把ArrayList更换为LinkedList，则原来的客户端代码必须全部重写。</p>
		<p>为解决以上问题，Iterator模式总是用同一种逻辑来遍历集合：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    for(Iterator it = c.iterater(); it.hasNext(); ) { ... }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>奥秘在于客户端自身不维护遍历集合的"指针"，所有的内部状态（如当前元素位置，是否有下一个元素）都由Iterator来维护，而这个Iterator由集合类通过工厂方法生成，因此，它知道如何遍历整个集合。</p>
		<p>客户端从不直接和集合类打交道，它总是控制Iterator，向它发送"向前"，"向后"，"取当前元素"的命令，就可以间接遍历整个集合。</p>
		<p>首先看看java.util.Iterator接口的定义：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    public interface Iterator {<br />        boolean hasNext();<br />        Object next();<br />        void remove();<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>依赖前两个方法就能完成遍历，典型的代码如下：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    for(Iterator it = c.iterator(); it.hasNext(); ) {<br />        Object o = it.next();<br />        // 对o的操作...<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在JDK1.5中，还对上面的代码在语法上作了简化：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    // Type是具体的类型，如String。<br />    for(Type t : c) {<br />        // 对t的操作...<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>每一种集合类返回的Iterator具体类型可能不同，Array可能返回ArrayIterator，Set可能返回SetIterator，
Tree可能返回TreeIterator，但是它们都实现了Iterator接口，因此，客户端不关心到底是哪种Iterator，它只需要获得这个
Iterator接口即可，这就是面向对象的威力。</p>
		<h4>Iterator源码剖析</h4>
		<br />
		<p>让我们来看看AbstracyList如何创建Iterator。首先AbstractList定义了一个内部类（inner class）：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    private class Itr implements Iterator {<br />        ...<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>而iterator()方法的定义是：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    public Iterator iterator() {<br />        return new Itr();<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>因此客户端不知道它通过Iterator it = a.iterator();所获得的Iterator的真正类型。</p>
		<p>现在我们关心的是这个申明为private的Itr类是如何实现遍历AbstractList的：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    private class Itr implements Iterator {<br />        int cursor = 0;<br />        int lastRet = -1;<br />        int expectedModCount = modCount;<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>Itr类依靠3个int变量（还有一个隐含的AbstractList的引用）来实现遍历，cursor是下一次next()调用时元素的位置，第一次调用next()将返回索引为0的元素。lastRet记录上一次游标所在位置，因此它总是比cursor少1。</p>
		<p>变量cursor和集合的元素个数决定hasNext()：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    public boolean hasNext() {<br />        return cursor != size();<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>方法next()返回的是索引为cursor的元素，然后修改cursor和lastRet的值：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    public Object next() {<br />        checkForComodification();<br />        try {<br />            Object next = get(cursor);<br />            lastRet = cursor++;<br />            return next;<br />        } catch(IndexOutOfBoundsException e) {<br />            checkForComodification();<br />            throw new NoSuchElementException();<br />        }<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>expectedModCount表示期待的modCount值，用来判断在遍历过程中集合是否被修改过。AbstractList包含一个
modCount变量，它的初始值是0，当集合每被修改一次时（调用add，remove等方法），modCount加1。因此，modCount如果不
变，表示集合内容未被修改。</p>
		<p>Itr初始化时用expectedModCount记录集合的modCount变量，此后在必要的地方它会检测modCount的值：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    final void checkForComodification() {<br />        if (modCount != expectedModCount)<br />            throw new ConcurrentModificationException();<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果modCount与一开始记录在expectedModeCount中的值不等，说明集合内容被修改过，此时会抛出ConcurrentModificationException。</p>
		<p>这个ConcurrentModificationException是RuntimeException，不要在客户端捕获它。如果发生此异常，说明程序代码的编写有问题，应该仔细检查代码而不是在catch中忽略它。</p>
		<p>但是调用Iterator自身的remove()方法删除当前元素是完全没有问题的，因为在这个方法中会自动同步expectedModCount和modCount的值：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    public void remove() {<br />        ...<br />        AbstractList.this.remove(lastRet);<br />        ...<br />        // 在调用了集合的remove()方法之后重新设置了expectedModCount：<br />        expectedModCount = modCount;<br />        ...<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>要确保遍历过程顺利完成，必须保证遍历过程中不更改集合的内容（Iterator的remove()方法除外），因此，确保遍历可靠的原则是只在一个线程中使用这个集合，或者在多线程中对遍历代码进行同步。</p>
		<p>最后给个完整的示例：</p>
		<table class="grey4" border="0" cellpadding="10" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<pre>    Collection c = new ArrayList();<br />    c.add("abc");<br />    c.add("xyz");<br />    for(Iterator it = c.iterator(); it.hasNext(); ) {<br />        String s = (String)it.next();<br />        System.out.println(s);<br />    }<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果你把第一行代码的ArrayList换成LinkedList或Vector，剩下的代码不用改动一行就能编译，而且功能不变，这就是针对抽象编程的原则：对具体类的依赖性最小。</p>
		<br />
		<p>/**********************************************************************</p>
		<p>这个算是比较满意的答案了。<br /></p>
<img src ="http://www.blogjava.net/Duffblog/aggbug/45267.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-05-09 19:20 <a href="http://www.blogjava.net/Duffblog/articles/45267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>异常：java.util.ConcurrentModificationException</title><link>http://www.blogjava.net/Duffblog/articles/45266.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Tue, 09 May 2006 11:19:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/45266.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/45266.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/45266.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/45266.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/45266.html</trackback:ping><description><![CDATA[今天，写程序，关于Iterator遍历，出现了这个java.util.ConcurrentModificationException。这个问题，已经碰到了好几次了，再次，在网上查找，终于，找到了一个比较满意的答案。如下：<br /><br />/*********************************************************************************<br /><div class="postbody"><p>在Map或者Collection的时候，不要用它们的API直接修改集合的内容，如果要修改可以用Iterator的remove()方法，例如：</p><p>    public void setReparation( Reparation reparation ) {<br />        for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations为Collection<br />            Reparation repa = (Reparation)it.next();<br />            if (repa.getId() == reparation.getId()){<br />                this.reparations.remove(repa);<br />                this.reparations.add(reparation);<br />            }<br />        }<br />   }</p><p>如上写会在运行期报ConcurrentModificationException，可以如下修改：</p><p>    public void setReparation( Reparation reparation ) {<br />        boolean flag = false;<br />        for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations为Collection<br />            Reparation repa = (Reparation)it.next();<br />            if (repa.getId() == reparation.getId()){<br />                it.remove();<br />                flag = true;<br />                break;<br />            }<br />        }<br />        if(flag){<br />          this.reparations.add(reparation);<br />        }<br />    }</p><p>具体可以参考：<a href="http://gceclub.sun.com.cn/yuanchuang/week-14/iterator.html">http://gceclub.sun.com.cn/yuanchuang/week-14/iterator.html</a></p><p>*******************************************************************************/</p><br /><h4>深入探讨Iterator模式，见下一篇。</h4><br /><br /></div><br /><img src ="http://www.blogjava.net/Duffblog/aggbug/45266.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-05-09 19:19 <a href="http://www.blogjava.net/Duffblog/articles/45266.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 Eclipse Workbench 之外使用 Eclipse GUI，第 1 部分: 单独使用 JFace 和 SWT</title><link>http://www.blogjava.net/Duffblog/articles/43415.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Wed, 26 Apr 2006 13:26:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/43415.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/43415.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/43415.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/43415.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/43415.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 开放源码 Eclipse 项目是 Java 领域中最有趣的新近开发项目之一。Eclipse 把自己描述成“一种通用的工具平台 — 开放的可扩展 IDE，可用于任何用途且没有特殊之处”。关于 Eclipse 的介绍，请参阅        developerWorks文章“        Getting started with the Eclipse Platform”。      ...&nbsp;&nbsp;<a href='http://www.blogjava.net/Duffblog/articles/43415.html'>阅读全文</a><img src ="http://www.blogjava.net/Duffblog/aggbug/43415.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-04-26 21:26 <a href="http://www.blogjava.net/Duffblog/articles/43415.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java读取File的问题 </title><link>http://www.blogjava.net/Duffblog/articles/39254.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Tue, 04 Apr 2006 13:17:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/39254.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/39254.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/39254.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/39254.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/39254.html</trackback:ping><description><![CDATA[
		<font face="Arial" size="2">我想要读取某一个路径下,文件最后修改的时间大于我给定的所有的文件.<br />比如是E:\file<br />我想要等到一部分的file,即是文件最后修改的时间大于我给定的<br />我目前的做法是:<br />查看所有的File,一一比对,得到我想要的File<br />//read path<br />Vector needReadFile = new Vector();<br />Date fileDate = new Date();<br />File[] files = new File(readFilePath).listFiles();<br />if (files == null) {<br />continue;<br />}<br />for (int x = 0; x &lt; files.length; x++) {<br />File tempFile = files[x];<br />Date fileDate = new Date(tempFile.<br />lastModified());<br />if (fileDate.compare(lastModifyDate) == 1 ) {<br />needReadFile.add(readFilePath + File.separator +<br />tempFile.getName());<br />}<br />} //end for(int i = 0 ; i&lt; files.length ; i++)<br /><br />虽然这样做是可以达到,当我的File很多的时候,效率很差了<br /><br />效率好一点的方法：<br /><br />看看listFiles()和listFiles(FileFilter filter) 的源代码<br /><br />public File[] listFiles() {<br />String[] ss = list();<br />if (ss == null) return null;<br />int n = ss.length;<br />File[] fs = new File[n];<br />for (int i = 0; i &lt; n; i++) {<br />fs[i] = new File(this.path, ss[i]);<br />}<br />return fs;<br />}<br /><br />public File[] listFiles(FileFilter filter) {<br />String ss[] = list();<br />if (ss == null) return null;<br />ArrayList v = new ArrayList();<br />for (int i = 0 ; i &lt; ss.length ; i++) {<br />File f = new File(this.path, ss[i]);<br />if ((filter == null) || filter.accept(f)) {<br />v.add(f);<br />}<br />}<br />return (File[])(v.toArray(new File[0]));<br />}<br /><br />采用第二个方法以后,只需要遍历一遍,而且代码更清晰,<br />采用第一个方法,你取得列表以后还需要遍历一遍过滤掉不符合条件的.<br /><br />File[] files = new File(readFilePath).listFiles(new FileFilter(){ <br />public boolean accept(File pathname){<br />//.判断修改日期,符合条件返回true;否则false;<br /><br />}});<br /><br />这里采用匿名类,实现一个FileFilter,你要修改过滤的逻辑,只需要修改accept()方法就是了,当然,你也可以专门写一个类比如<br /><br />class FileModifyDateFilter implements FileFilter{<br />private Date baseDate = null;<br />public FileModifyDateFilter(Date d) {<br />baseDate = d;<br />} <br /><br />public boolean accept(File f) {<br />if (baseDate == null)<br />return true;<br />if (f.lastModified() &gt; baseDate.getTime()) <br />return true;<br /><br />return false;<br />}<br />}<br /><br /><br />原文来自：<a href="http://www.jdon.com/jive/thread.jsp?forum=16&amp;thread=22478&amp;message=13169392">http://www.jdon.com/jive/thread.jsp?forum=16&amp;thread=22478&amp;message=13169392</a></font>
<img src ="http://www.blogjava.net/Duffblog/aggbug/39254.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-04-04 21:17 <a href="http://www.blogjava.net/Duffblog/articles/39254.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java源代码分析----jvm.dll装载过程</title><link>http://www.blogjava.net/Duffblog/articles/39245.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Tue, 04 Apr 2006 12:32:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/39245.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/39245.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/39245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/39245.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/39245.html</trackback:ping><description><![CDATA[原文来自：<a href="http://www.matrix.org.cn">http://www.matrix.org.cn</a><br /><br /><h4>摘要:</h4>众所周知java.exe是java class文件的执行程序，但实际上java.exe程序只是一个执行的外壳，它会装载jvm.dll（windows下，以下皆以windows平台为例， linux下和solaris下其实类似，为：libjvm.so），这个动态连接库才是java 虚拟机的实际操作处理所在。本文探究java.exe程序是如何查找和装载jvm.dll 动态库，并调用它进行class文件执行处理的. <br /><br /><strong>简述<br /></strong>众所周知java.exe是java class文件的执行程序，但实际上java.exe程序只是<br />一个执行的外壳，它会装载jvm.dll（windows下，以下皆以windows平台为例，<br />linux下和solaris下其实类似，为：libjvm.so），这个动态连接库才是java<br />虚拟机的实际操作处理所在。本文探究java.exe程序是如何查找和装载jvm.dll<br />动态库，并调用它进行class文件执行处理的。<br /><br /><b>源代码</b><br />本文分析之代码，《JavaTM 2 SDK, Standard Edition, v1.4.2 fcs<br />Community Source Release》，可从sun官方网站下载，主要分析的源代码为：<br />j2se\src\share\bin\java.c<br />j2se\src\windows\bin\java_md.c<br /><br /><b>java.c是什么东西</b><br />‘java程序’源代码<br />所谓‘java程序’，包括jdk中的java.exe\javac.exe\javadoc.exe，java.c源<br />代码中通过JAVA_ARGS宏来控制生成的代码，如果该宏没定义则编译文件控制生<br />成java.exe否则编译文件控制生成其他的‘java程序’。<br />比如：<br />j2se\make\java\javac\Makefile（这是javac编译文件）中：<br />$(CD) ../../sun/javac ; $(MAKE) $@ RELEASE=$(RELEASE) FULL_VERSION=$(FULL_VERSION)<br />j2se\make\sun\javac\javac\Makefile（由上面Makefile文件调用）中：<br />JAVA_ARGS = "{ \"-J-ms8m\", \"com.sun.tools.javac.Main\" }"<br />则由同一份java.c代码生成的javac.exe程序就会直接调用java类方法：<br />com.sun.tools.javac.Main，这样使其执行起来就像是直接运行的一个exe文件，<br />而未定义JAVA_ARGS的java.exe程序则会调用传递过来参数中的类方法。<br /><br /><b>从java.c的main入口函数说起</b><br />main()函数中前面一段为重新分配参数指针的处理。<br />然后调用函数：CreateExecutionEnvironment，该函数主要查找java运行环境的<br />目录，和jvm.dll这个虚拟机核心动态连接库文件路径所在。根据操作系统不同，<br />该函数有不同实现版本，但大体处理逻辑相同，我们看看windows平台该函数的处<br />理（j2se\src\windows\bin\java_md.c）。<br /><br />CreateExecutionEnvironment函数主要分为三步处理：<br />a、查找jre路径。<br />b、装载jvm.cfg中指定的虚拟机动态连接库（jvm.dll）参数。<br />c、取jvm.dll文件路径。<br /><br />实现：<br />a、查找jre路径是通过java_md.c中函数：GetJREPath实现的。<br />该函数首先调用GetApplicationHome函数，GetApplicationHome函数调用windows<br />API函数GetModuleFileName取java.exe程序的绝对路径，以我的jdk安装路径为例，<br />为：“D:\java\j2sdk1.4.2_04\bin\java.exe”，然后去掉文件名取绝对路径为：<br />“D:\java\j2sdk1.4.2_04\bin”，之后会在去掉最后一级目录，现在绝对路径为：<br />“D:\java\j2sdk1.4.2_04”。<br />然后GetJREPath函数继续判断刚刚取的路径+\bin\java.dll组合成的这个java.dll<br />文件是否存在，如果存在则“D:\java\j2sdk1.4.2_04”为JRE路径，否则判断取得<br />的“D:\java\j2sdk1.4.2_04”路径+\jre\bin\java.dll文件是否存在，存在则<br />“D:\java\j2sdk1.4.2_04\jre”为JRE路径。如果上面两种情况都不存在，则从注<br />册表中去查找（参见函数GetPublicJREHome）。<br /><br />函数：GetPublicJREHome先查找<br />HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\CurrentVersion<br />键值“当前JRE版本号”，判断“当前JRE版本号”是否为1.4做为版本号，如果是则<br />取HKEY_LOCAL_MACHINE\Software\JavaSoft\Java Runtime Environment\“当前JRE版本号”<br />\JavaHome的路径所在为JRE路径。<br /><br />我的JDK返回的JRE路径为：“D:\java\j2sdk1.4.2_04\jre”。<br /><br />b、装载jvm.cfg虚拟机动态连接库配置文件是通过java.c中函数:ReadKnownVMs实现<br />的。<br />该函数首先组合jvm.cfg文件的绝对路径，JRE路径+\lib+\ARCH（CPU构架）+\jvm.cfg<br />ARCH（CPU构架）的判断是通过java_md.c中GetArch函数判断的，该函数中windows平<br />台只有两种情况：WIN64的‘ia64’，其他情况都为‘i386’。我的为i386所以jvm.cfg<br />文件绝对路径为：“D:\java\j2sdk1.4.2_04\jre\lib\i386\jvm.cfg”。文件内容如<br />下：<br /><pre class="overflow">#<br /># @(#)jvm.cfg        1.7 03/01/23<br /># <br /># Copyright 2003 Sun Microsystems, Inc. All rights reserved.<br /># SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.<br /># <br /># <br />#<br />#<br /># List of JVMs that can be used as an option to java, javac, etc.<br /># Order is important -- first in this list is the default JVM.<br /># NOTE that this both this file and its format are UNSUPPORTED and<br /># WILL GO AWAY in a future release.<br />#<br /># You may also select a JVM in an arbitrary location with the<br /># "-XXaltjvm=&lt;jvm_dir&gt;" option, but that too is unsupported<br /># and may not be available in a future release.<br />#<br />-client KNOWN<br />-server KNOWN<br />-hotspot ALIASED_TO -client<br />-classic WARN<br />-native ERROR<br />-green ERROR</pre><br /><br />（如果细心的话，我们会发现在JDK目录中我的为：“D:\java\j2sdk1.4.2_04\jre\bin\client”和“D:\java\j2sdk1.4.2_04\jre\bin\server”两个目录下都存在jvm.dll文件。而java正是通过jvm.cfg配置文件来管理这些不同版本的jvm.dll的。）<br /><br />ReadKnownVMs函数会将该文件中的配置内容读入到一个JVM配置结构的全局变量中，该函数首先跳过注释（以‘#’开始的行），然后读取以‘-’开始的行指定的jvm参数，每一行为一个jvm信息，第一部分为jvm虚拟机名称，第二部分为配置参数，比如行：<br />“-client KNOWN”则“-client”为虚拟机名称，而“KNOWN”为配置类型参数，“KNOWN”<br />表示该虚拟机的jvm.dll存在，而“ALIASED_TO”表示为另一个jvm.dll的别名，“WARN”<br />表示该虚拟机的jvm.dll不存在但运行时会用其他存在的jvm.dll替代执行，而“ERROR”<br />同样表示该类虚拟机的jvm.dll不存在且运行时不会找存在的jvm.dll替代而直接抛出错误<br />信息。<br /><br />在运行java程序时指定使用那个虚拟机的判断是由java.c中函数：CheckJvmType判断，该函数会检查java运行参数中是否有指定jvm的参数，然后从ReadKnownVMs函数读取的jvm.cfg数据结构中去查找，从而指定不同的jvm类型（最终导致装载不同jvm.dll）。有两种方法可以指定jvm类型，一种按照jvm.cfg文件中的jvm名称指定，第二种方法是直接指定，它们执行的方法分别是“java -J&lt;jvm.cfg中jvm名称&gt;”、“java -XXaltjvm=&lt;jvm类型名称&gt;”或“java -J-XXaltjvm=&lt;jvm类型名称&gt;”。如果是第一种参数传递方式，CheckJvmType函数会取参数‘-J’后面的jvm名称，然后从已知的jvm配置参数中查找如果找到同名的则去掉该jvm名称前的‘-’直接返回该值；而第二种方法，会直接返回“-XXaltjvm=”或“-J-XXaltjvm=”后面的jvm类型名称；如果在运行java时未指定上面两种方法中的任一一种参数，CheckJvmType会取配置文件中第一个配置中的jvm名称，去掉名称前面的‘-’返回该值。CheckJvmType函数的这个返回值会在下面的函数中汇同jre路径组合成jvm.dll的绝对路径。<br /><br />比如：如果在运行java程序时使用“java -J-client test”则ReadKnownVMs会读取参数“-client”然后查找jvm.cfg读入的参数中是否有jvm名称为“-client”的，如果有则去掉jvm名称前的“-”直接返回“client”；而如果在运行java程序时使用如下参数：<br />“java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\client test”，则ReadKnownVMs<br />会直接返回“D:\java\j2sdk1.4.2_04\jre\bin\client”；如果不带上面参数执行如：<br />“java test”，因为在jvm.cfg配置文件中第一个存在的jvm为“-client”，所以函数<br />ReadKnownVMs也会去掉jvm名称前的“-”返回“client”。其实这三中情况都是使用的<br />“D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll”这个jvm动态连接库处理test这个class的，见下面GetJVMPath函数。<br /><br />c、取jvm.dll文件路径是通过java_md.c中函数：GetJVMPath实现的。<br />由上面两步我们已经获得了JRE路径和jvm的类型字符串。GetJVMPath函数判断CheckJvmType<br />返回的jvm类型字符串中是否包含了‘\’或‘/’如果包含则以该jvm类型字符串+\jvm.dll作为JVM的全路径，否则以JRE路径+\bin+\jvm类型字符串+\jvm.dll作为JVM的全路径。<br /><br />看看上面的例子，第一种情况“java -J-client test”jvm.dll路径为：<br />JRE路径+\bin+\jvm类型字符串+\jvm.dll 按照我的JDK路径则为：<br />“D:\java\j2sdk1.4.2_04\jre”+“\bin”+“\client”+“\jvm.dll”。<br />第二种情况“java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\client test”路径为：<br />jvm类型字符串+\jvm.dll即为：“D:\java\j2sdk1.4.2_04\jre\bin\client”+“\jvm.dll”<br />第三种情况“java test”为：“D:\java\j2sdk1.4.2_04\jre”+“\bin”+“\client”<br />+“\jvm.dll”与情况一相同。所以这三种情况都是调用的jvm动态连接库“D:\java\<br />j2sdk1.4.2_04\jre\bin\client\jvm.dll”处理test类的。<br /><br />我们来进一步验证一下：<br />打开cmd控制台：<br /><br />设置java装载调试<br />E:\work\java_research&gt;set _JAVA_LAUNCHER_DEBUG=1<br />情况一<br />E:\work\java_research&gt;java -J-client test.ScanDirectory<br />----_JAVA_LAUNCHER_DEBUG----<br />JRE path is D:\java\j2sdk1.4.2_04\jre<br />jvm.cfg[0] = -&gt;-client&lt;-<br />jvm.cfg[1] = -&gt;-server&lt;-<br />jvm.cfg[2] = -&gt;-hotspot&lt;-<br />jvm.cfg[3] = -&gt;-classic&lt;-<br />jvm.cfg[4] = -&gt;-native&lt;-<br />jvm.cfg[5] = -&gt;-green&lt;-<br />299 micro seconds to parse jvm.cfg<br />JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll<br />2897 micro seconds to LoadJavaVM<br />JavaVM args:<br />    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2<br />    option[ 0] = '-Djava.class.path=.'<br />    option[ 1] = '-Dsun.java.command=test.ScanDirectory'<br />50001 micro seconds to InitializeJVM<br />Main-Class is 'test.ScanDirectory'<br />Apps' argc is 0<br />10208 micro seconds to load main class<br />----_JAVA_LAUNCHER_DEBUG----<br />usage: java test.ScanDirectory DIR [output file]<br />情况二<br />E:\work\java_research&gt;java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\client test.ScanDirectory<br />----_JAVA_LAUNCHER_DEBUG----<br />JRE path is D:\java\j2sdk1.4.2_04\jre<br />jvm.cfg[0] = -&gt;-client&lt;-<br />jvm.cfg[1] = -&gt;-server&lt;-<br />jvm.cfg[2] = -&gt;-hotspot&lt;-<br />jvm.cfg[3] = -&gt;-classic&lt;-<br />jvm.cfg[4] = -&gt;-native&lt;-<br />jvm.cfg[5] = -&gt;-green&lt;-<br />386 micro seconds to parse jvm.cfg<br />JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll<br />2795 micro seconds to LoadJavaVM<br />JavaVM args:<br />    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2<br />    option[ 0] = '-Djava.class.path=.'<br />    option[ 1] = '-Dsun.java.command=test.ScanDirectory'<br />49978 micro seconds to InitializeJVM<br />Main-Class is 'test.ScanDirectory'<br />Apps' argc is 0<br />9598 micro seconds to load main class<br />----_JAVA_LAUNCHER_DEBUG----<br />usage: java test.ScanDirectory DIR [output file]<br />情况三<br />E:\work\java_research&gt;java test.ScanDirectory<br />----_JAVA_LAUNCHER_DEBUG----<br />JRE path is D:\java\j2sdk1.4.2_04\jre<br />jvm.cfg[0] = -&gt;-client&lt;-<br />jvm.cfg[1] = -&gt;-server&lt;-<br />jvm.cfg[2] = -&gt;-hotspot&lt;-<br />jvm.cfg[3] = -&gt;-classic&lt;-<br />jvm.cfg[4] = -&gt;-native&lt;-<br />jvm.cfg[5] = -&gt;-green&lt;-<br />381 micro seconds to parse jvm.cfg<br />JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll<br />3038 micro seconds to LoadJavaVM<br />JavaVM args:<br />    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2<br />    option[ 0] = '-Djava.class.path=.'<br />    option[ 1] = '-Dsun.java.command=test.ScanDirectory'<br />50080 micro seconds to InitializeJVM<br />Main-Class is 'test.ScanDirectory'<br />Apps' argc is 0<br />10215 micro seconds to load main class<br />----_JAVA_LAUNCHER_DEBUG----<br />usage: java test.ScanDirectory DIR [output file]<br />三个的JVM路径都为：<br />JVM path is D:\java\j2sdk1.4.2_04\jre\bin\client\jvm.dll<br /><br />其他情况<br />E:\work\java_research&gt;java -J-server test.ScanDirectory<br />----_JAVA_LAUNCHER_DEBUG----<br />JRE path is D:\java\j2sdk1.4.2_04\jre<br />jvm.cfg[0] = -&gt;-client&lt;-<br />jvm.cfg[1] = -&gt;-server&lt;-<br />jvm.cfg[2] = -&gt;-hotspot&lt;-<br />jvm.cfg[3] = -&gt;-classic&lt;-<br />jvm.cfg[4] = -&gt;-native&lt;-<br />jvm.cfg[5] = -&gt;-green&lt;-<br />377 micro seconds to parse jvm.cfg<br />JVM path is D:\java\j2sdk1.4.2_04\jre\bin\server\jvm.dll<br />2985 micro seconds to LoadJavaVM<br />JavaVM args:<br />    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2<br />    option[ 0] = '-Djava.class.path=.'<br />    option[ 1] = '-Dsun.java.command=test.ScanDirectory'<br />62382 micro seconds to InitializeJVM<br />Main-Class is 'test.ScanDirectory'<br />Apps' argc is 0<br />12413 micro seconds to load main class<br />----_JAVA_LAUNCHER_DEBUG----<br />usage: java test.ScanDirectory DIR [output file]<br />E:\work\java_research&gt;java -XXaltjvm=D:\java\j2sdk1.4.2_04\jre\bin\server test.ScanDirectory<br />----_JAVA_LAUNCHER_DEBUG----<br />JRE path is D:\java\j2sdk1.4.2_04\jre<br />jvm.cfg[0] = -&gt;-client&lt;-<br />jvm.cfg[1] = -&gt;-server&lt;-<br />jvm.cfg[2] = -&gt;-hotspot&lt;-<br />jvm.cfg[3] = -&gt;-classic&lt;-<br />jvm.cfg[4] = -&gt;-native&lt;-<br />jvm.cfg[5] = -&gt;-green&lt;-<br />376 micro seconds to parse jvm.cfg<br />JVM path is D:\java\j2sdk1.4.2_04\jre\bin\server\jvm.dll<br />2937 micro seconds to LoadJavaVM<br />JavaVM args:<br />    version 0x00010002, ignoreUnrecognized is JNI_FALSE, nOptions is 2<br />    option[ 0] = '-Djava.class.path=.'<br />    option[ 1] = '-Dsun.java.command=test.ScanDirectory'<br />62725 micro seconds to InitializeJVM<br />Main-Class is 'test.ScanDirectory'<br />Apps' argc is 0<br />8942 micro seconds to load main class<br />----_JAVA_LAUNCHER_DEBUG----<br />usage: java test.ScanDirectory DIR [output file]<br /><br />由上面可以看出，如果我们安装了多个jdk或jre版本的话，使用“java -XXaltjvm=”<br />可以通过绝对路径指定到其他版本的jvm.dll上去，至于能不能运行还有待测试。<br /><br />我们下面回到java.c的main函数中看看上面找到的jvm.dll是如何装载挂接执行的。<br /><br />该操作大致分为三步：<br />a、装载jvm.dll动态连接库。<br />b、初始化jvm.dll并挂接到JNIEnv（JNI调用接口）实例。<br />c、调用JNIEnv实例装载并处理class类。<br /><br />实现：<br />a、装载jvm.dll动态连接库是由main函数调用java_md.c中LoadJavaVM函数实现的。<br />main函数首先构造了一个InvocationFunctions结构的局部变量，InvocationFunctions<br />结构有两个函数指针：<br /><pre class="overflow">typedef struct {<br />    CreateJavaVM_t CreateJavaVM;<br />    GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;<br />} InvocationFunctions;</pre><br />函数LoadJavaVM中先调用windows API函数：LoadLibrary装载jvm.dll动态连接库，<br />之后将jvm.dll中的导出函数JNI_CreateJavaVM和JNI_GetDefaultJavaVMInitArgs<br />挂接到InvocationFunctions变量的CreateJavaVM和GetDefaultJavaVMInitArgs函数<br />指针变量上。jvm.dll的装载工作宣告完成。<br /><br />b、初始化jvm.dll并挂接到JNIEnv（JNI调用接口）实例是通过java.c中函数：<br />InitializeJVM完成的。<br />main方法中首先定义了一个JNIEnv结构的指针，JNIEnv结构中定义了许多与装载class<br />类文件、查找类方法、调用类方法有关的函数指针变量。InitializeJVM会调用上面<br />以挂接jvm.dll中JNI_CreateJavaVM的InvocationFunctions结构变量的CreateJavaVM方法，即调用jvm.dll中函数JNI_CreateJavaVM，该函数会将JNIEnv结构的实例返回到main中的JNIEnv结构的指针上。这样main中的JNIEnv指针获取了JNIEnv实例后，就可以开始对class文件进行处理了。<br /><br />c、调用JNIEnv实例装载并处理class类。<br />a)如果是执行jar包。<br />如果执行的是一个jar包的话，main函数会调用java.c中的函数：GetMainClassName，该函数使用JNIEnv实例构造并调用java类：java.util.jar.JarFile中方法getManifest()并从返回的Manifest对象中取getAttributes("Main-Class")的值，即jar包中文件：<br />META-INF/MANIFEST.MF指定的Main-Class的主类名作为运行的主类。<br />之后main函数会调用java.c中LoadClass方法装载该主类（使用JNIEnv实例的FindClass）。<br />b)如果是执行class方法。<br />main函数直接调用java.c中LoadClass方法装载该类。<br /><br />然后main函数调用JNIEnv实例的GetStaticMethodID方法查找装载的class主类中<br />“public static void main(String[] args)”方法，并判断该方法是否为public方法，然后调用JNIEnv实例的CallStaticVoidMethod方法调用该java类的main方法。<br /><br /><b>总结</b><br />由上面的代码分析可以看出几个问题。<br />a、为什么JDK和JRE不一定通过安装，直接拷到硬盘上，设置path环境变量就可以执行。因为java运行获取jre路径的首选方法正是直接通过获取java.exe绝对路径来判断的，如果通过修改注册表选项而不设置path环境变量也可以找到jre路径所在。修改方法如下：<br />首先我们将java.exe拷到任意目录下，我的拷到e:\temp下，在cmd中运行：<br />清空path环境变量<br />E:\temp&gt;set path=<br />E:\temp&gt;java<br />Error opening registry key 'Software\JavaSoft\Java Runtime Environment'<br />Error: could not find java.dll<br />Error: could not find Java 2 Runtime Environment.<br /><br />导入如下注册表文件（java.reg）<br /><pre class="overflow">Windows Registry Editor Version 5.00<br /><br />[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft]<br /><br />[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment]<br />"CurrentVersion"="1.4"<br /><br />[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.4]<br />"JavaHome"="D:\\java\\j2sdk1.4.2_04\\jre"</pre><br /><br />再执行显示执行正常，如下：<br /><pre class="overflow">E:\temp&gt;java<br />Usage: java [-options] class [args...]<br />           (to execute a class)<br />   or  java [-options] -jar jarfile [args...]<br />           (to execute a jar file)<br /><br />where options include:<br />    -client       to select the "client" VM<br />    -server       to select the "server" VM<br />    -hotspot      is a synonym for the "client" VM  [deprecated]<br />                  The default VM is client.<br /><br />    -cp &lt;class search path of directories and zip/jar files&gt;<br />    -classpath &lt;class search path of directories and zip/jar files&gt;<br />                  A ; separated list of directories, JAR archives,<br />                  and ZIP archives to search for class files.<br />    -D&lt;name&gt;=&lt;value&gt;<br />                  set a system property<br />    -verbose[:class|gc|jni]<br />                  enable verbose output<br />    -version      print product version and exit<br />    -showversion  print product version and continue<br />    -? -help      print this help message<br />    -X            print help on non-standard options<br />    -ea[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />    -enableassertions[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />                  enable assertions<br />    -da[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />    -disableassertions[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />                  disable assertions<br />    -esa | -enablesystemassertions<br />                  enable system assertions<br />    -dsa | -disablesystemassertions<br />                  disable system assertions</pre><br />b、java.exe是通过jvm.cfg文件或直接指定jvm.dll路径来装载执行java程序的。<br />见上面例子。<br />c、不同实现版本的jvm.dll必然存在一个名为：JNI_CreateJavaVM的导出函数，<br />java.exe正是通过调用该函数获得JNIEnv调用接口来装载执行class类的。这个<br />函数也是我们下一步研究java vm实作技巧的研究出发点。<br />JNI_CreateJavaVM函数位于：hotspot\src\share\vm\prims\jni.cpp文件中。<br /><br />原文连接地址：<a href="http://www.matrix.org.cn/resource/article/1/1650_jvm_loading_progress.html">http://www.matrix.org.cn/resource/article/1/1650_jvm_loading_progress.html</a><br /><br /><br /><br /><img src ="http://www.blogjava.net/Duffblog/aggbug/39245.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-04-04 20:32 <a href="http://www.blogjava.net/Duffblog/articles/39245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何正确地应用Runtime类调用程序 </title><link>http://www.blogjava.net/Duffblog/articles/39244.html</link><dc:creator>追球者</dc:creator><author>追球者</author><pubDate>Tue, 04 Apr 2006 12:27:00 GMT</pubDate><guid>http://www.blogjava.net/Duffblog/articles/39244.html</guid><wfw:comment>http://www.blogjava.net/Duffblog/comments/39244.html</wfw:comment><comments>http://www.blogjava.net/Duffblog/articles/39244.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/Duffblog/comments/commentRss/39244.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Duffblog/services/trackbacks/39244.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Verdana">用Java编写应用时，有时需要在程序中调用另一个现成的可执行程序或系统命令，这时可以通过组合使用Java提供的Runtime类和Process类的方法实现。下面是一种比较典型的程序模式： <br />... <br />Process process = Runtime.getRuntime().exec(".\\p.exe"); <br />process.waitfor( ); <br />... <br />在上面的程序中，第一行的“.\\p.exe”是要执行的程序名，Runtime.getRuntime()返回当前应用程序的Runtime对象，该对象的exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序，并返回与该子进程对应的Process对象实例。通过Process可以控制该子进程的执行或获取该子进程的信息。第二条语句的目的等待子进程完成再往下执行。 <br />但在windows平台上，如果处理不当，有时并不能得到预期的结果。下面是笔者在实际编程中总结的几种需要注意的情况： <br />1、执行DOS的内部命令 <br />如果要执行一条DOS内部命令，有两种方法。一种方法是把命令解释器包含在exec()的参数中。例如，执行dir命令，在NT上， 可写成exec("cmd.exe /c dir")，在windows 95/98下，可写成“command.exe /c dir”，其中参数“/c”表示命令执行后关闭Dos立即关闭窗口。另一种方法是，把内部命令放在一个批命令my_dir.bat文件中，在Java程序中写成exec("my_dir.bat")。如果仅仅写成exec("dir")，Java虚拟机则会报运行时错误。前一种方法要保证程序的可移植性，需要在程序中读取运行的操作系统平台，以调用不同的命令解释器。后一种方法则不需要做更多的处理。 <br />2、打开一个不可执行的文件 <br />打开一个不可执行的文件，但该文件存在关联的应用程序，则可以有两种方式。 以打开一个word文档a.doc文件为例，Java中可以有以下两种写法： <br />exec("start .\\a.doc"); <br />exec(" c:\\Program Files\\Microsoft Office\\office\\winword.exe .\\a.doc"); <br />显然，前一种方法更为简捷方便。 <br />3、执行一个有标准输出的DOS可执行程序 <br />在windows平台上，运行被调用程序的DOS窗口在程序执行完毕后往往并不会自动关闭，从而导致Java应用程序阻塞在waitfor( )。导致该现象的一个可能的原因是，该可执行程序的标准输出比较多，而运行窗口的标准输出缓冲区不够大。解决的办法是，利用Java提供的Process类提供的方法让Java虚拟机截获被调用程序的DOS运行窗口的标准输出，在waitfor()命令之前读出窗口的标准输出缓冲区中的内容。一段典型的程序如下： <br />... <br />String ls_1; <br />Process process = Runtime.getRuntime().exec("cmd /c dir \\windows"); <br />BufferedReader bufferedReader = new BufferedReader( \ <br />new InputStreamReader(process.getInputStream()); <br />while ( (ls_1=bufferedReader.readLine()) != null) <br />System.out.println(ls_1); <br /> <br />process.waitfor( ); <br /><br />结束。<br /><br />我自己有测试过。需要小小的修改。我的代码如下：<br /><br />import java.io.IOException;</font>
		</p>
		<p>
				<font face="Verdana">public class TestProcess {</font>
		</p>
		<p>
				<font face="Verdana"> /**<br />  * @param args<br />  */<br /> public static void main(String[] args) {<br />  System.out.println("runtime~~~~");<br />  ProcessExec p = new ProcessExec();<br />  int i = 2;<br />  try{<br />   i = p.process11();<br />  }catch(IOException e){<br />   <br />  }<br />  System.out.println(i);<br /> }<br /> <br />}</font>
		</p>
		<p>
				<font face="Verdana">class ProcessExec{<br /> public int process11() throws IOException{<br />//  Process process = Runtime.getRuntime().exec("C:/Program Files/Outlook Express/msimn.exe");<br />  Process process = Runtime.getRuntime().exec("cmd.exe /c");<br />//  Process process = Runtime.getRuntime().exec("C:/WINDOWS/system32/cmd.exe");<br />  int i=4;<br />  try{<br />   i = process.waitFor();<br />  }catch(InterruptedException e){<br />   i=3;<br />  }<br />  return i;<br /> }<br />}<br /><br /></font>
				<br />
				<br />
		</p>
<img src ="http://www.blogjava.net/Duffblog/aggbug/39244.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Duffblog/" target="_blank">追球者</a> 2006-04-04 20:27 <a href="http://www.blogjava.net/Duffblog/articles/39244.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>