﻿<?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-学历代表过去，能力代表现在，学习力代表未来！</title><link>http://www.blogjava.net/ljc-java/</link><description>模仿中成长，在创新中成功！</description><language>zh-cn</language><lastBuildDate>Tue, 12 May 2026 08:53:48 GMT</lastBuildDate><pubDate>Tue, 12 May 2026 08:53:48 GMT</pubDate><ttl>60</ttl><item><title>Java中的内部类</title><link>http://www.blogjava.net/ljc-java/articles/416442.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Fri, 01 Aug 2014 09:34:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/articles/416442.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/416442.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/articles/416442.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/416442.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/416442.html</trackback:ping><description><![CDATA[<ol>
     <li>什么是内部类 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     <br />
     <div>内部类是指在一个外部类的内部再定义一个类。</div>
     <div>内部类可以是静态static的，也可用public，default，protected和private修饰。（而外部顶级类即类名和文件名相同的只能使用public和default）。</div>
     <div><span style="color: red;">注意：内部类是一个编译时的概念，一旦编译成功，就会成为完全不同的两类。对于一个名为Outer的外部类和其内部定义的名为Inner的内部类。编译完成后出现Outer.class和Outer$Inner.class两类。</span><span style="color: #0000ff;">所以内部类的成员变量/方法名可以和外部类的相同。</span></div>
     <div>java内部类分为： 成员内部类、静态嵌套类、局部内部类、匿名内部类 。</div>
     <br />
     </li>
     <li>内部类的共性<br />
     <br />
     <div>(1)、内部类仍然是一个独立的类，在编译之后内部类会被编译成独立的.class文件，但是前面冠以外部类的类名和$符号 。</div>
     <div>(2)、内部类不能用普通的方式访问。内部类是外部类的一个成员，因此内部类可以自由地访问外部类的成员变量，无论是否是private的 。</div>
     <div>(3)、内部类声明成静态的，就不能随便的访问外部类的成员变量了，此时内部类只能访问外部类的静态成员变量 。</div>
     </li>
     <li>成员内部类<br />
     <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Outer&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;a&nbsp;=&nbsp;10;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;b&nbsp;=&nbsp;15;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;print()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Outer.a="+<span style="color: #0000FF; ">this</span>.a);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;add(<span style="color: #0000FF; ">int</span>&nbsp;i,<span style="color: #0000FF; ">int</span>&nbsp;j)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;i+j;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Inner&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;a&nbsp;=&nbsp;20;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;c&nbsp;=&nbsp;b;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;print()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">内部类访问外部类中的同名成员变量</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Outer.a="+Outer.<span style="color: #0000FF; ">this</span>.a);&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Inner.a="+<span style="color: #0000FF; ">this</span>.a);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("a="+a);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">内部类中可以直接访问外部类的成员变量和方法（内部类对象持有指向外部类对象的引用。）</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("c="+c);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("c+1="+add(c,1));<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Outer&nbsp;outer&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Outer();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outer.print();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">内部类对象的创建依赖于外部类对象；</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;outer.<span style="color: #0000FF; ">new</span>&nbsp;Inner().print();&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     }</div>
     <font size="2">
     <div></div>
     </font><font size="2">
     <div>
     这个类编译后出现Outer.class和Outer$Inner.class两个class文件。编译后成为两个独立的类，<br />
     因此，内部类中可以定义与外部类中同名的属性和方法。<br />
     <br />
     成员内部类，就是作为外部类的成员，与外部类的属性、方法并列。可以直接使用外部类的所有成员和方法，即使是private的。<br />
     同时外部类要访问内部类的所有成员变量和方法，则需要通过内部类的对象来获取。</div>
     <div>要注意的是，成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类，才能创建它自己的</div>
     <br />
     <div></div>
     </font></li>
     <li>局部内部类<br />
     <div>局部内部类，是指内部类定义在方法和作用域内。</div>
     (1)、定义在方法内<br />
     &nbsp; &nbsp;&nbsp;<br />
     <div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Teacher&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;String&nbsp;name;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;age;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;teach()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;String&nbsp;str&nbsp;=&nbsp;"I'm&nbsp;a&nbsp;teacher!";<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;EnglishTeacher&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;teachEnglish()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("My&nbsp;name&nbsp;is&nbsp;"+name);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("I'm&nbsp;"+age);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(str);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("I&nbsp;teach&nbsp;English");<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EnglishTeacher&nbsp;englishTeacher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;EnglishTeacher();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;englishTeacher.teachEnglish();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;args<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Teacher&nbsp;teacher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Teacher();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;teacher.name&nbsp;=&nbsp;"张三";<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;teacher.age&nbsp;=&nbsp;35;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;teacher.teach();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     }<span style="font-size: 14px;">&nbsp;</span></div>
     <br />
     <br />
     (2)、定义在作用域内<br />
     <!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><span style="color: #008080; ">&nbsp;</span>
     <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><br />
     <span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Teacher1&nbsp;{<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;String&nbsp;name;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;age;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;teach(String&nbsp;course)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;String&nbsp;str&nbsp;=&nbsp;"I'm&nbsp;a&nbsp;teacher!";<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(str);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>("English".equals(course))&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;EnglishTeacher&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;teachEnglish()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("My&nbsp;name&nbsp;is&nbsp;"+name);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("I'm&nbsp;"+age);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("I&nbsp;teach&nbsp;English");<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EnglishTeacher&nbsp;englishTeacher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;EnglishTeacher();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;englishTeacher.teachEnglish();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;args<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Teacher1&nbsp;teacher&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Teacher1();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;teacher.name&nbsp;=&nbsp;"张三";<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;teacher.age&nbsp;=&nbsp;35;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;teacher.teach("English");<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     <br />
     }</div>
     &nbsp; &nbsp;&nbsp;<br />
     <br />
     <div>
     <div>(1)、局部内部类只能在定义该内部类的方法内实例化，不可以在此方法外对其实例化。</div>
     <div>(2)、局部内部类对象不能使用该内部类所在方法的非final局部变量。<br />
     (3)、局部内部类的地位和方法内的局部变量的位置类似，因此不能修饰局部变量的修饰符也不能修饰局部内部类，<br />
     &nbsp; &nbsp; &nbsp; &nbsp;譬如public、private、protected、static、transient等</div>
     <div>因为方法的局部变量位于栈上，只存在于该方法的生命期内。当一个方法结束，其栈结构被删除，局部变量成为历史。但是该方法结束之后，在方法内创建的内部类对象可能仍然存在于堆中！例如，如果对它的引用被传递到其他某些代码，并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长，所以内部类对象不能使用它们。</div>
     </div>
     </li>
     <li>静态嵌套类<br />
     <br />
     <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><br />
     <span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;StaticOuter&nbsp;{<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;a&nbsp;=&nbsp;10;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;b&nbsp;=&nbsp;15;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;StaticInner&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;print()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("b="+b);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;print1()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("b="+b);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;args<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StaticOuter.StaticInner.print();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;StaticOuter.StaticInner().print1();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     <br />
     }</div>
     <br />
     <div>嵌套类和普通的内部类还有一个区别：普通内部类不能有static数据和static属性，也不能包含嵌套类，但嵌套类可以。<br />
     而嵌套类不能声明为private，一般声明为public，方便调用。<br />
     <br />
     <div>在静态方法中定义的内部类也是StaticNested Class，这时候不能在类前面加static关键字，静态方法中的StaticNested Class与<br />
     普通方法中的内部类的应用方式很相似，它除了可以直接访问外部类中的static的成员变量，还可以访问静态方法中的局部变量，<br />
     但是，该局部变量前必须加final修饰符。</div>
     </div>
     <br />
     </li>
     <li>匿名内部类</li>
     <br />
     <div>匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类？如果满足下面的一些条件，使用匿名内部类是比较合适的：</div>
     <div>&#183;只用到类的一个实例 。</div>
     <div>&#183;类在定义后马上用到。</div>
     <div>&#183;类非常小（SUN推荐是在4行代码以下）</div>
     <div>&#183;给类命名并不会导致你的代码更容易被理解。</div>
     <div>在使用匿名内部类时，要记住以下几个原则：</div>
     <div>&#183;匿名内部类不能有构造方法。</div>
     <div>&#183;匿名内部类不能定义任何静态成员、静态方法。</div>
     <div>&#183;匿名内部类不能是public,protected,private,static。</div>
     <div>&#183;只能创建匿名内部类的一个实例。</div>
     <div>&#183;一个匿名内部类一定是在new的后面，用其隐含实现一个接口或实现一个类。</div>
     &#183;因匿名内部类为局部内部类，所以局部内部类的所有限制都对其生效。<br />
     <br />
     (1)、继承式的匿名内部类<br />
     <div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><br />
     <span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Singer&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sing()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Sing&nbsp;a&nbsp;song");<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;args<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Singer&nbsp;singer&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Singer()&nbsp;{<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;sing()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Sing&nbsp;a&nbsp;popular&nbsp;song");<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;singer.sing();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     <br />
     }</div>
     <br />
     输出结果：Sing a popular song<br />
     <br />
     (2)、接口式的匿名内部类<br />
     <br />
     <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><br />
     <span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;Programmer&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;code();<br />
     <br />
     }<br />
     <br />
     <br />
     <br />
     <span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;TestProgrammer&nbsp;{<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;args<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Programmer&nbsp;javaProgrammer&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Programmer()&nbsp;{<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;code()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Java&nbsp;programmer");<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;javaProgrammer.code();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Programmer&nbsp;phpProgrammer&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Programmer()&nbsp;{<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;code()&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Php&nbsp;programmer");<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
     <br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;phpProgrammer.code();<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     <br />
     }</div>
     <br />
     (3)、参数式的匿名内部类<br /><br /><div style="font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br /><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;Programmer&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;code();<br /><br />}<br /><br /><br /><br /><br /><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;TestProgrammer1&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;testCode(Programmer&nbsp;p)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.code();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;args<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;main(String[]&nbsp;args)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TestProgrammer1&nbsp;testProgrammer1&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;TestProgrammer1();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testProgrammer1.testCode(<span style="color: #0000FF; ">new</span>&nbsp;Programmer()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;code()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("testing&nbsp;code");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />}</div><br /><br /><li>为什么需要内部类<br /><br /></li><div>典型的情况是，内部类继承自某个类或实现某个接口，内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。<br />使用内部类最吸引人的原因是：</div><div>每个内部类都能独立地继承自一个（接口的）实现，所以无论外围类是否已经继承了某个（接口的）实现，对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力，一些设计与编程问题就很难解决。从这个角度看，内部类使得多重继承的解决方案变得完整。接口解决了部分问题，而内部类有效地实现了&#8220;多重继承&#8221;。</div>
</ol><img src ="http://www.blogjava.net/ljc-java/aggbug/416442.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2014-08-01 17:34 <a href="http://www.blogjava.net/ljc-java/articles/416442.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 设计模式</title><link>http://www.blogjava.net/ljc-java/articles/415369.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Wed, 02 Jul 2014 08:16:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/articles/415369.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/415369.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/articles/415369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/415369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/415369.html</trackback:ping><description><![CDATA[<div>Java设计模式分为<span style="color: #ff0000;">创建模式</span>, <span style="color: #ff0000;">结构模式</span>, <span style="color: #ff0000;">行为模式</span> 3种类型：</div>
<div></div>
<div>Java设计模式之<span style="color: #ff0000;">创建模式</span>包括：</div>
<div></div>
<div style="text-align: justify;">&nbsp;&nbsp;&nbsp;&nbsp;Factory, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 工厂模式</div>
<div></div>
<div style="text-align: justify;">&nbsp;&nbsp;&nbsp;&nbsp;Singleton, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;单例模式</div>
<div></div>
<div style="text-align: justify;">&nbsp;&nbsp;&nbsp;&nbsp;Builder, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;建造模式</div>
<div></div>
<div style="text-align: justify;">&nbsp;&nbsp;&nbsp;&nbsp;Prototype, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 原型模式</div>
<div></div>
<div>Java设计模式之<span style="color: #ff0000;">结构模式</span>包括：</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Facade, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 门面模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Decorator, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 装饰模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Composite, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;合成模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Proxy, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 代理模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Adapter, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;适配器模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Bridge, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;桥梁模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Flyweight, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;共享元类模式</div>
<div></div>
<div>Java设计模式之<span style="color: #ff0000;">行为模式</span>包括：</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Chain of responsibleif, &nbsp; &nbsp;责任链模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Command, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;命令模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Strategy, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;策略模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Observer, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;观察模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Interpreter , &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;解释器模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Iterator, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;迭代模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Mediator, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 中介模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Memento, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;备忘录模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;State, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 状态模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Template, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;模板模式</div>
<div></div>
<div style="text-align: justify; ">&nbsp;&nbsp;&nbsp;&nbsp;Visitor, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 访问者模式</div><img src ="http://www.blogjava.net/ljc-java/aggbug/415369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2014-07-02 16:16 <a href="http://www.blogjava.net/ljc-java/articles/415369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jQuery操作radio</title><link>http://www.blogjava.net/ljc-java/articles/401141.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Tue, 02 Jul 2013 09:44:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/articles/401141.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/401141.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/articles/401141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/401141.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/401141.html</trackback:ping><description><![CDATA[<p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">&lt;input type="radio"&gt;如下：<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">input&nbsp;</span><span style="color: #FF0000; ">type</span><span style="color: #0000FF; ">="radio"</span><span style="color: #FF0000; ">&nbsp;name</span><span style="color: #0000FF; ">="city"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="BeiJing"</span><span style="color: #0000FF; ">&gt;</span>北京<br /><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">input&nbsp;</span><span style="color: #FF0000; ">type</span><span style="color: #0000FF; ">="radio"</span><span style="color: #FF0000; ">&nbsp;name</span><span style="color: #0000FF; ">="city"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="TianJin"</span><span style="color: #0000FF; ">&gt;</span>天津<br /><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">input&nbsp;</span><span style="color: #FF0000; ">type</span><span style="color: #0000FF; ">="radio"</span><span style="color: #FF0000; ">&nbsp;name</span><span style="color: #0000FF; ">="city"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="NanJing"</span><span style="color: #0000FF; ">&gt;</span>南京<br /><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">input&nbsp;</span><span style="color: #FF0000; ">type</span><span style="color: #0000FF; ">="radio"</span><span style="color: #FF0000; ">&nbsp;name</span><span style="color: #0000FF; ">="city"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="YangZhou"</span><span style="color: #0000FF; ">&gt;</span>扬州<br /><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">input&nbsp;</span><span style="color: #FF0000; ">type</span><span style="color: #0000FF; ">="radio"</span><span style="color: #FF0000; ">&nbsp;name</span><span style="color: #0000FF; ">="city"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="SuZhou"</span><span style="color: #0000FF; ">&gt;</span>苏州</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px;">&nbsp; &nbsp;&nbsp;</span><span style="font-family: verdana, geneva;">1、获取选中的radio的值：<br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city']:checked").val();</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">　　<span style="font-family: verdana, geneva;">使用元素选择器，再使用属性过滤器name='city'，最后使用:checked选取被选中的元素。</span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　2、给指定值的radio设置选中状态：<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city'][value='YangZhou']").attr("checked",true);</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　给name="city"而且value="YangZhou"的radio设置选中状态。</span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　3、取消name="city"的radio的选中状态：<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$('input[name="city"]:checked').attr("checked",false);</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　4、获取name="city"的radio的个数：<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city']").length;</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　5、获取name="city"而且索引是偶数的radio:<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city']:even");</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　索引是从0开始的。</span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　6、获取name="city"而且索引是奇数的radio:<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city']:odd");</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">　<span style="font-family: verdana, geneva;">　索引是从0开始的。</span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　7、迭代radio:<br /><br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city']").each(function(i,obj){<br />&nbsp;&nbsp;&nbsp;&nbsp;//i,迭代的下标，从0开始<br />&nbsp;&nbsp;&nbsp;&nbsp;//obj,当前的对象(HTMLInputElement),可以使用obj.value格式获取属性值<br />&nbsp;&nbsp;&nbsp;&nbsp;//$(this);当前jQuery对象,可以使用$(this).val()获取属性值<br />});</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">　<span style="font-family: verdana, geneva;">　迭代name="city"的radio。</span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　8、禁用radio:<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city']").attr("disabled",true);</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;">　　<span style="font-family: verdana, geneva;">禁用name="city"的radio。</span></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　9、启用radio:<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$("input[name='city']").attr("disabled",false);</div><p style="margin-top: 10px; margin-bottom: 10px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><span style="font-family: verdana, geneva;">　　启用name="city"的radio。</span></p><img src ="http://www.blogjava.net/ljc-java/aggbug/401141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2013-07-02 17:44 <a href="http://www.blogjava.net/ljc-java/articles/401141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>框 架</title><link>http://www.blogjava.net/ljc-java/archive/2011/12/05/365600.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Mon, 05 Dec 2011 07:57:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/archive/2011/12/05/365600.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/365600.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/archive/2011/12/05/365600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/365600.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/365600.html</trackback:ping><description><![CDATA[<strong>框  架是为了解决一个又一个在Web开发中所遇到的问题而诞生的。不同的框架，都是为了解决不同的问题，但是对于程序员而言，他们只是jar包而已。框架的优   缺点的评论，也完全取决于其对问题解决程度和解决方式的优雅性的评论。所以，千万不要为了学习框架而学习框架，而是要为了解决问题而学习框架，这才是一个  程序员的正确学习之道。</strong><img src ="http://www.blogjava.net/ljc-java/aggbug/365600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2011-12-05 15:57 <a href="http://www.blogjava.net/ljc-java/archive/2011/12/05/365600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA事务,JTA,JDBC,JDO,DAO,JNDI概念(转载) </title><link>http://www.blogjava.net/ljc-java/articles/365595.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Mon, 05 Dec 2011 07:17:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/articles/365595.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/365595.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/articles/365595.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/365595.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/365595.html</trackback:ping><description><![CDATA[<strong style="font-weight: bold"><span style="font-size: small">一、什么是</span></strong><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">Java</span></strong></span><strong style="font-weight: bold"><span style="font-size: small">事务</span></strong><div> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">通常的观念认为，事务仅与数据库相关。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br /></span></span><span style="font-size: small">事务必须服从</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">ISO/IEC</span></span><span style="font-size: small">所制定的</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">ACID</span></span><span style="font-size: small">原则。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">ACID</span></span><span style="font-size: small">是原子性（</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">atomicity</span></span><span style="font-size: small">）、一致性（</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">consistency</span></span><span style="font-size: small">）、隔离性（</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">isolation</span></span><span style="font-size: small">）和持久性（</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">durability</span></span><span style="font-size: small">）的缩写。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">事务的原子性表示事务执行过程中的任何失败都将导致事务所做的任何修改失效。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">一致性表示当事务执行失败时，所有被该事务影响的数据都应该恢复到事务执行前的状态。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">隔离性表示在事务执行过程中对数据的修改，在事务提交之前对其他事务不可见。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">持久性表示已提交的数据在事务执行失败时，数据的状态都应该正确。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-family: 'Times New Roman', serif"><span style="font-size: small"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">通俗的理解，事务是一组原子操作单元，从数据库角度说，就是一组</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">SQL</span></span><span style="font-size: small">指令，要么全部执行成功，若因为某个原因其中一条指令执行有错误，则撤销先前执行过的所有指令。更简答的说就是：要么全部执行成功，要么撤销不执行。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-family: 'Times New Roman', serif"><span style="font-size: small"><br /></span></span><span style="font-size: small">既然事务的概念从数据库而来，那</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">Java</span></span><span style="font-size: small">事务是什么？之间有什么联系？</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;&nbsp;</span></span><span style="font-size: small">实际上，一个</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">Java</span></span><span style="font-size: small">应用系统，如果要操作数据库，则通过</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JDBC</span></span><span style="font-size: small">来实现的。增加、修改、删除都是通过相应方法间接来实现的，事务的控制也相应转移到</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">Java</span></span><span style="font-size: small">程序代码中。因此，数据库操作的事务习惯上就称为</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">Java</span></span><span style="font-size: small">事务。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="font-size: small">二、为什么需要事务</span></strong></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">事务是为解决数据安全操作提出的，事务控制实际上就是控制数据的安全访问。具一个简单例子：比如银行转帐业务，账户</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">A</span></span><span style="font-size: small">要将自己账户上的</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">1000&nbsp;</span></span><span style="font-size: small">元转到</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">B</span></span><span style="font-size: small">账户下面，</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">A</span></span><span style="font-size: small">账户余额首先要减去</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">1000</span></span><span style="font-size: small">元，然后</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">B</span></span><span style="font-size: small">账户要增加</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">1000</span></span><span style="font-size: small">元。假如在中间网络出现了问题，</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">A</span></span><span style="font-size: small">账户减去</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">1000</span></span><span style="font-size: small">元已经结束，</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">B</span></span><span style="font-size: small">因为网络中断而操作失败，那么整个业务失败，必须做出控制，要求</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">A</span></span><span style="font-size: small">账户转帐业务撤销。这才能保证业务的正确性，完成这个操走就需要事务，将</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">A</span></span><span style="font-size: small">账户资金减少和</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">B</span></span><span style="font-size: small">账户资金增加方到一个事务里面，要么全部执行成功，要么操作全部撤销，这样就保持了数据的安全性。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-family: 'Times New Roman', serif"><span style="font-size: small"><br /></span><strong style="font-weight: bold"><span style="font-size: small">三、</span></strong></span><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">Java</span></strong></span><strong style="font-weight: bold"><span style="font-size: small">事务的类型</span></strong><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">&nbsp;</span></strong><span style="font-size: small"><br />&nbsp;&nbsp;&nbsp; Java&nbsp;</span></span><span style="font-size: small">事务的类型有三种：</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JDBC</span></span><span style="font-size: small">事务、</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JTA(Java Transaction API)</span></span><span style="font-size: small">事务、容器事务。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br /></span><strong style="font-weight: bold"><span style="font-size: small">1</span></strong></span><strong style="font-weight: bold"><span style="font-size: small">、</span></strong><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">JDBC</span></strong></span><strong style="font-weight: bold"><span style="font-size: small">事务</span></strong><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">&nbsp;</span></strong><span style="font-size: small"><br />JDBC&nbsp;</span></span><span style="font-size: small">事务是用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;Connection&nbsp;</span></span><span style="font-size: small">对象控制的。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JDBC Connection&nbsp;</span></span><span style="font-size: small">接口</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">( java.sql.Connection )</span></span><span style="font-size: small">提供了两种事务模式：自动提交和手工提交。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;java.sql.Connection&nbsp;</span></span><span style="font-size: small">提供了以下控制事务的方法：</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">public void setAutoCommit(boolean)&nbsp;<br />public boolean getAutoCommit()&nbsp;<br />public void commit()&nbsp;<br />public void rollback()&nbsp;<br /></span><span style="font-size: small">使用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JDBC&nbsp;</span></span><span style="font-size: small">事务界定时，您可以将多个</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;SQL&nbsp;</span></span><span style="font-size: small">语句结合到一个事务中。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JDBC&nbsp;</span></span><span style="font-size: small">事务的一个缺点是事务的范围局限于一个数据库连接。一个</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JDBC&nbsp;</span></span><span style="font-size: small">事务不能跨越多个数据库。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br /></span><strong style="font-weight: bold"><span style="font-size: small">2</span></strong></span><strong style="font-weight: bold"><span style="font-size: small">、</span></strong></span><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">JTA(Java Transaction  API)</span></strong></span><strong style="font-weight: bold"><span style="font-size: small">事务</span></strong><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br />&nbsp;&nbsp;&nbsp;  JTA&nbsp;</span></span><span style="font-size: small">是一种高层的，与实现无关的，与协议无关的</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">API</span></span><span style="font-size: small">，应用程序和应用服务器可以使用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JTA</span></span><span style="font-size: small">来访问事务。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br />JTA</span></span><span style="font-size: small">允许应用程序执行分布式事务处理</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">--</span></span><span style="font-size: small">在两个或多个网络计算机资源上访问并且更新数据，这些数据可以分布在多个数据库上。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JDBC</span></span><span style="font-size: small">驱动程序的</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JTA</span></span><span style="font-size: small">支持极大地增强了数据访问能力。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br /></span></span><span style="font-size: small">如果计划用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JTA&nbsp;</span></span><span style="font-size: small">界定事务，那么就需要有一个实现</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;javax.sql.XADataSource&nbsp;</span></span><span style="font-size: small">、</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;javax.sql.XAConnection&nbsp;</span></span><span style="font-size: small">和</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;javax.sql.XAResource</span></span><span style="font-size: small">接口的</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JDBC&nbsp;</span></span><span style="font-size: small">驱动程序。一个实现了这些接口的驱动程序将可以参与</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JTA&nbsp;</span></span><span style="font-size: small">事务。一个</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;XADataSource&nbsp;</span></span><span style="font-size: small">对象就是一个</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">XAConnection&nbsp;</span></span><span style="font-size: small">对象的工厂。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;XAConnection  s&nbsp;</span></span><span style="font-size: small">是参与</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JTA&nbsp;</span></span><span style="font-size: small">事务的</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JDBC&nbsp;</span></span><span style="font-size: small">连接。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br /></span></span><span style="font-size: small">您将需要用应用服务器的管理工具设置</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;XADataSource&nbsp;</span></span><span style="font-size: small">。从应用服务器和</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JDBC&nbsp;</span></span><span style="font-size: small">驱动程序的文档中可以了解到相关的指导。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br />J2EE&nbsp;</span></span><span style="font-size: small">应用程序用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JNDI&nbsp;</span></span><span style="font-size: small">查询数据源。一旦应用程序找到了数据源对象，它就调用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;javax.sql.DataSource.getConnection()&nbsp;</span></span><span style="font-size: small">以获得到数据库的连接。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;  XA&nbsp;</span></span><span style="font-size: small">连接与非</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;XA&nbsp;</span></span><span style="font-size: small">连接不同。一定要记住</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;XA&nbsp;</span></span><span style="font-size: small">连接参与了</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JTA&nbsp;</span></span><span style="font-size: small">事务。这意味着</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;XA&nbsp;</span></span><span style="font-size: small">连接不支持</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;JDBC&nbsp;</span></span><span style="font-size: small">的自动提交功能。同时，应用程序一定不要对</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;XA&nbsp;</span></span><span style="font-size: small">连接调用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;java.sql.Connection.commit()&nbsp;</span></span><span style="font-size: small">或者</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;java.sql.Connection.rollback()&nbsp;</span></span><span style="font-size: small">。相反，应用程序应该使用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;UserTransaction.begin()</span></span><span style="font-size: small">、</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;UserTransaction.commit()&nbsp;</span></span><span style="font-size: small">和</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;serTransaction.rollback()&nbsp;</span></span><span style="font-size: small">。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">3</span></strong></span><strong style="font-weight: bold"><span style="font-size: small">、容器事务</span></strong><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">&nbsp;</span></strong><span style="font-size: small"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="font-size: small">容器事务主要是</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">J2EE</span></span><span style="font-size: small">应用服务器提供的，容器事务大多是基于</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JTA</span></span><span style="font-size: small">完成，这是一个基于</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JNDI</span></span><span style="font-size: small">的，相当复杂的</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">API</span></span><span style="font-size: small">实现。相对编码实现</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JTA&nbsp;</span></span><span style="font-size: small">事务管理，我们可以通过</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">EJB</span></span><span style="font-size: small">容器提供的容器事务管理机制（</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">CMT</span></span><span style="font-size: small">）完成同一个功能，这项功能由</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">J2EE</span></span><span style="font-size: small">应用服务器提供。这使得我们可以简单的指定将哪个方法加入事务，一旦指定，容器将负责事务管理任务。这是我们土建的解决方式，因为通过这种方式我们可以将事务代码排除在逻辑编码之外，同时将所有困难交给</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;J2EE</span></span><span style="font-size: small">容器去解决。使用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">EJB CMT</span></span><span style="font-size: small">的另外一个好处就是程序员无需关心</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JTA API</span></span><span style="font-size: small">的编码，不过，理论上我们必须使用</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">EJB</span></span><span style="font-size: small">。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br /></span></span><strong style="font-weight: bold"><span style="font-size: small">四、三种事务差异</span></strong><span style="font-family: 'Times New Roman', serif"><strong style="font-weight: bold"><span style="font-size: small">&nbsp;</span></strong><span style="font-size: small"><br />1</span></span><span style="font-size: small">、</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JDBC</span></span><span style="font-size: small">事务控制的局限性在一个数据库连接内，但是其使用简单。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br />2</span></span><span style="font-size: small">、</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">JTA</span></span><span style="font-size: small">事务的功能强大，事务可以跨越多个数据库或多个</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">DAO</span></span><span style="font-size: small">，使用也比较复杂。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br />3</span></span><span style="font-size: small">、容器事务，主要指的是</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">J2EE</span></span><span style="font-size: small">应用服务器提供的事务管理，局限于</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">EJB</span></span><span style="font-size: small">应用使用。</span><span style="font-family: 'Times New Roman', serif"><span style="font-size: small">&nbsp;<br /></span></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="color: #0000ff"><span style="font-size: small">JTA</span></span></strong></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span><span style="font-size: small">Java事务API（JTA；Java Transaction  API）和它的同胞Java事务服务(JTS；Java Transaction  Service)，为J2EE平台提供了分布式事务服务。一个分布式事务（distributed transaction）包括一个事务管理器（transaction  manager）和一个或多个资源管理器(resource manager)。一个资源管理器（resource  manager）是任意类型的持久化数据存储。事务管理器（transaction  manager）承担着所有事务参与单元者的相互通讯的责任。下图显示了事务管理器和资源管理的间的关系。</span></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JTA事务比JDBC事务更强大。一个JTA事务可以有多个参与者，而一个JDBC事务则被限定在一个单一的数据库连接。</span><span style="font-size: small">下列任一个Java平台的组件都可以参与到一个JTA事务中：</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JDBC连接</span></p> <ul style="padding-bottom: 0px; margin: 0px 0px 1.5em; padding-left: 0px; padding-right: 0px; padding-top: 0px"><li style="padding-bottom: 0px; margin: 0px 0px 0.25em 30px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JDO PersistenceManager 对象</span>  </li><li style="padding-bottom: 0px; margin: 0px 0px 0.25em 30px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JMS 队列</span>  </li><li style="padding-bottom: 0px; margin: 0px 0px 0.25em 30px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JMS 主题</span>  </li><li style="padding-bottom: 0px; margin: 0px 0px 0.25em 30px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">企业JavaBeans（EJB）</span>  </li><li style="padding-bottom: 0px; margin: 0px 0px 0.25em 30px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">一个用J2EE Connector Architecture 规范编译的资源分配器。</span>  </li></ul> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="color: #0000ff"><strong style="font-weight: bold"><span style="font-size: small">DAO</span></strong></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span><span style="font-size: small">DAO是Data Access  Object数据访问接口，数据访问：顾名思义就是与数据库打交道。夹在业务逻辑与数据库资源中间。对数据库进行CURD（增删查改操作）。</span></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">　　在核心</span><a style="color: #136ec2; text-decoration: underline" href="http://baike.baidu.com/view/1507.htm" target="_blank"><span style="font-size: small">J2EE</span></a><span style="font-size: small">模式中是这样介绍DAO模式的：为了建立一个健壮的J2EE应用，应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的语言来说，就是建立一个接口，接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中，当需要和数据源进行交互的时候则使用这个接口，并且编写一个单独的类来实现这个接口在逻辑上对应这个特定的数据存储。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="color: #0000ff"><strong style="font-weight: bold"><span style="font-size: small">JDBC</span></strong></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span><span style="font-size: small">JDBC（Java Data Base  Connectivity,java数据库连接）是一种用于执行SQL语句的Java  API，可以为多种关系数据库提供统一访问，它由一组用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API，据此可以构建更高级的工具和接口，使数据库开发人员能够用纯  Java API 编写数据库应用程序，同时，JDBC也是个商标名。</span></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px">&nbsp;</p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">有了JDBC，向各种关系数据发送SQL语句就是一件很容易的事。换言之，有了JDBC  API，就不必为访问Sybase数据库专门写一个程序，为访问Oracle数据库又专门写一个程序，或为访问Informix数据库又编写另一个程序等等，程序员只需用JDBC  API写一个程序就够了，它可向相应数据库发送SQL调用。同时，将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序，只须写一遍程序就可以让它在任何平台上运行，这也是Java语言&#8220;编写一次，处处运行&#8221;的优势。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span><span style="font-size: small">简单地说，JDBC 可做三件事：与数据库建立连接、发送  操作数据库的语句并处理结果。</span></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="color: #0000ff"><strong style="font-weight: bold"><span style="font-size: small">JDO</span></strong></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span><span style="font-size: small">JDO(Java Data Object  )是一个JAVA用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储，因此对开发人员来说，存储数据对象完全不需要额外的代码（如JDBC  API的使用）。这些繁琐的例行工作已经转移到JDO产品提供商身上，使开发人员解脱出来，从而集中时间和精力在业务逻辑上。另外，JDO很灵活，因为它可以在任何数据底层上运行。JDBC只是面向关系数据库（RDBMS）JDO更通用，提供到任何数据底层的存储功能，比如关系数据库、文件、XML以及对象数据库（ODBMS）等等，使得应用可移植性更强。</span></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><strong style="font-weight: bold"><span style="color: #0000ff"><span style="font-size: small">JNDI</span></span></strong></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span><span style="font-size: small">英文全称是:Java Naming and Directory  Interface</span></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">术语解释：一组帮助做多个命名和目录服务接口的API。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JNDI(Java Naming and Directory  Interface)是SUN公司提供的一种标准的Java命名系统接口，JNDI提供统一的客户端API，通过不同的访问提供者接口JNDI  SPI的实现，由管理者将JNDI  API映射为特定的命名服务和目录系统，使得Java应用程序可以和这些命名服务和目录服务之间进行交互。集群JNDI实现了高可靠性JNDI[8]，通过服务器的集群，保证了JNDI的负载平衡和错误恢复。在全局共享的方式下，集群中的一个应用服务器保证本地JNDI树的独立性，并拥有全局的JNDI树。每个应用服务器在把部署的服务对象绑定到自己本地的JNDI树的同时，还绑定到一个共享的全局JNDI树，实现全局JNDI和自身JNDI的联系。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p>&nbsp;</p> <div style="line-height: 14px; height: 14px; font-size: 12px"><span style="line-height: normal; font-size: small">JNDI(Java Naming and Directory  Interface)是一个应用程序设计的API，为开发人员提供了查找和访问各种</span></div> <p>&nbsp;</p> <div style="line-height: 14px; height: 14px; font-size: 12px"><span style="line-height: normal; font-size: small">命名和目录服务的通用、统一的接口，类似JDBC都是构建在抽象层上。</span></div> <p>&nbsp;</p> <div style="line-height: 14px; height: 14px; font-size: 12px"><span style="line-height: normal; font-size: small">JNDI可访问的现有的目录及服务有：DNS、XNam  、Novell目录服务、LDAP(Lightweight Directory Access Protocol 轻型目录访问协议)、  CORBA对象服务、文件系统、Windows XP/2000/NT/Me/9x的注册表、RMI、<div><span style="line-height: normal; font-size: small"><span style="line-height: normal; font-size: small">DSML v1&amp;v2、NIS。</span></span></div></span></div> <p>&nbsp;</p> <div style="line-height: 14px; height: 14px; font-size: 12px"></div><p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><br /></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small"><strong style="font-weight: bold">JNDI与JDBC</strong></span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JNDI提供了一种统一的方式，可以用在网络上查找和访问服务。通过指定一个资源名称，该名称对应于数据库或命名服务中的一个记录，同时返回数据库连接建立所必须的信息。</span></p> <p style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px"><span style="font-size: small">JNDI主要有两部分组成：应用程序编辑接口和服务供应商接口。应用程序编程接口提供了Java应用程序访问各种命名和目录服务的功能，服务供应商接口提供了任意一种服务的供应商使用的功能。</span></p></div><img src ="http://www.blogjava.net/ljc-java/aggbug/365595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2011-12-05 15:17 <a href="http://www.blogjava.net/ljc-java/articles/365595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jquery-autocomplete</title><link>http://www.blogjava.net/ljc-java/articles/363160.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Tue, 08 Nov 2011 03:41:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/articles/363160.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/363160.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/articles/363160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/363160.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/363160.html</trackback:ping><description><![CDATA[<div><p style="text-indent: 2em">jquery-autocomplete学习</p> <p style="text-indent: 2em">一、用前必备</p> <p style="text-indent: 2em">官方网站：<a href="http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/" rel="nofollow">http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/</a></p> <p style="text-indent: 2em">当前版本：1.0.2</p> <p style="text-indent: 2em">需要JQuery版本：1.2.6</p> <p style="text-indent: 2em">二、使用</p> <p style="text-indent: 2em">&lt;script src="./jquery-1.3.2.js"  type="text/javas<wbr>cript"&gt;&lt;/script&gt;</p> <p style="text-indent: 2em">&lt;script src="./jquery.autocomplete.js"  type="text/javas<wbr>cript"&gt;&lt;/script&gt;</p> <p style="text-indent: 2em">&lt;link rel="stylesheet"  href="./jquery.autocomplete.css" /&gt;</p> <p style="text-indent: 2em">autocomplete( url or da<wbr>ta, options ) Returns:  jQuery</p> <p style="text-indent: 2em">让一个input或textarea有autocomplete功能</p> <p style="text-indent: 2em">例子</p> <p style="text-indent: 2em">Js代码</p> <p style="text-indent: 2em">var da<wbr>ta = "Core Selectors Attributes  Traversing Manipulation CSS Events Effects Ajax Utilities".split("  ");&nbsp;<wbr>&nbsp;<wbr></p> <p style="text-indent: 2em">$("#example").autocomplete(da<wbr>ta);</p> <p style="text-indent: 2em">以上的例子就是为id为example添加autocomplete</p> <p style="text-indent: 2em">var emails = [</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Peter Pan", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/peter@pan.de">peter@pan.de</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Molly", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/molly@yahoo.com">molly@yahoo.com</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Forneria Marconi", to:  "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/live@japan.jp">live@japan.jp</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Master  &lt;em&gt;Sync&lt;/em&gt;", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/205bw@samsung.com">205bw@samsung.com</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Dr.  &lt;strong&gt;Tech&lt;/strong&gt; de Log", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/g15@logitech.com">g15@logitech.com</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Don Corleone", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/don@vegas.com">don@vegas.com</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Mc Chick", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/info@donalds.org">info@donalds.org</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Donnie Darko", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/dd@timeshift.info">dd@timeshift.info</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Quake The Net", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/webmaster@quakenet.org">webmaster@quakenet.org</a>" },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> { name: "Dr. Write", to: "<a href="http://mm.ala.blog.163.com/blog/static/30516034200992913015903/write@writable.com">write@writable.com</a>" }</p> <p style="text-indent: 2em">];</p> <p style="text-indent: 2em">//emails的数组格式如上，formatItem代表的是显示的格式，formatMatch表示匹配的内容，formatResult表示结果的内容</p> <p style="text-indent: 2em">$("#suggest13").autocomplete(emails, {</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> minChars: 0,</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> width: 310,</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> matchContains: true,</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> autoFill: false,</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> formatItem: function(row, i, max)  {</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return i  + "/" + max + ": \"" + row.name + "\" [" + row.to + "]";</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> formatMatch: function(row, i,  max) {</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return  row.name + " " + row.to;</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> },</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> formatResult: function(row) {</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> return  row.to;</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p> <p style="text-indent: 2em">});</p> <p style="text-indent: 2em">三、参数说明：</p> <p style="text-indent: 2em">* minChars (Number):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  在触发autoComplete前用户至少需要输入的字符数.Default: 1，如果设为0，在输入框内双击或者删除输入框内内容时显示列表</p> <p style="text-indent: 2em">* width (Number):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 指定下拉框的宽度. Default: input元素的宽度</p> <p style="text-indent: 2em">* max (Number):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> autoComplete下拉显示项目的个数.Default:  10</p> <p style="text-indent: 2em">* delay (Number):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  击键后激活autoComplete的延迟时间(单位毫秒).Default: 远程为400 本地10</p> <p style="text-indent: 2em">* autoFill (Boolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 要不要在用户选择时自动将用户当前鼠标所在的值填入到input框.  Default: false</p> <p style="text-indent: 2em">* mustMatch (Booolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  如果设置为true,autoComplete只会允许匹配的结果出现在输入框,所有当用户输入的是非法字符时将会得不到下拉框.Default: false</p> <p style="text-indent: 2em">* matchContains (Boolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 决定比较时是否要在字符串内部查看匹配,如ba是否与foo  bar中的ba匹配.使用缓存时比较重要.不要和autofill混用.Default: false</p> <p style="text-indent: 2em">* selectFirst (Boolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  如果设置成true,在用户键入tab或return键时autoComplete下拉列表的第一个值将被自动选择,尽管它没被手工选中(用键盘或鼠标).当然如果用户选中某个项目,那么就用用户选中的值.  Default: true</p> <p style="text-indent: 2em">* cacheLength (Number):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  缓存的长度.即对从数据库中取到的结果集要缓存多少条记录.设成1为不缓存.Default: 10</p> <p style="text-indent: 2em">* matchSubset (Boolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  autoComplete可不可以使用对服务器查询的缓存,如果缓存对foo的查询结果,那么如果用户输入foo就不需要再进行检索了,直接使用缓存.通常是打开这个选项以减轻服务器的负担以提高性能.只会在缓存长度大于1时有效.Default:  true</p> <p style="text-indent: 2em">* matchCase (Boolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  比较是否开启大小写敏感开关.使用缓存时比较重要.如果你理解上一个选项,这个也就不难理解,就好比foot要不要到FOO的缓存中去找.Default:  false</p> <p style="text-indent: 2em">* multiple (Boolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 是否允许输入多个值即多次使用autoComplete以输入多个值.  Default: false</p> <p style="text-indent: 2em">* multipleSeparator (String):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 如果是多选时,用来分开各个选择的字符. Default:  ","</p> <p style="text-indent: 2em">* scroll (Boolean):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 当结果集大于默认高度时是否使用卷轴显示 Default:  true</p> <p style="text-indent: 2em">* scrollHeight (Number):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 自动完成提示的卷轴高度用像素大小表示 Default:  180&nbsp;<wbr>&nbsp;<wbr></p> <p style="text-indent: 2em">* formatItem (Function):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  为每个要显示的项目使用高级标签.即对结果中的每一行都会调用这个函数,返回值将用LI元素包含显示在下拉列表中. Autocompleter会提供三个参数(row,  i, max): 返回的结果数组, 当前处理的行数(即第几个项目,是从1开始的自然数), 当前结果数组元素的个数即项目的个数. Default: none,  表示不指定自定义的处理函数,这样下拉列表中的每一行只包含一个值.</p> <p style="text-indent: 2em">* formatResult (Function):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  和formatItem类似,但可以将将要输入到input文本框内的值进行格式化.同样有三个参数,和formatItem一样.Default:  none,表示要么是只有数据,要么是使用formatItem提供的值.</p> <p style="text-indent: 2em">* formatMatch (Function):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 对每一行数据使用此函数格式化需要查询的数据格式.  返回值是给内部搜索算法使用的. 参数值row</p> <p style="text-indent: 2em">* extraParams (Object):</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  为后台(一般是服务端的脚本)提供更多的参数.和通常的作法一样是使用一个键值对对象.如果传过去的值是{ bar:4  },将会被autocompleter解析成my_autocomplete_backend.php?q=foo&amp;bar=4 (假设当前用户输入了foo).  Default: {}</p> <p style="text-indent: 2em">* result (handler) Returns: jQuery</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 此事件会在用户选中某一项后触发，参数为：</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> event: 事件对象.  event.type为result.</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> da<wbr>ta: 选中的数据行.</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> formatted:formatResult函数返回的值</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 例如：</p> <p style="text-indent: 2em">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>  $("#singleBirdRemote").result(function(event, da<wbr>ta, formatted) {</p> <p style="text-indent: 2em">//如选择后给其他控件赋值，触发别的事件等等</p> <p style="text-indent: 2em">});</p> <p style="text-indent: 2em">四、注意问题：</p> <p style="text-indent: 2em">1.网上有人说对中文的检索时处理有问题，经过测试此版本没有问题^-^</p> <p style="text-indent: 2em">2.在使用远程地址时，它默认传入的参数是：q（输入值），limit（返回结果的最大值），可以使用extraParams传入其他的参数</p> <p style="text-indent: 2em">3.autocomplete在使用ajax传递参数时，默认使用了get方式传递，也实在是没有找到可以通过参数提交post方式的办法。</p> <p style="text-indent: 2em">解决方式1：在使用ajax的get方式传递中文时，使用new  String(request.getParameter("q").getBytes("iso8859-1"),"utf-8")获得参数值</p> <p style="text-indent: 2em">解决方式2：修改jquery.autocomplete.js代码，把get方式修改为post方式，然后参见之前ajax解决中文乱码的问题的</p> <p style="text-indent: 2em">&nbsp;</p> <p style="text-indent: 2em">转载：<a href="http://blog.sina.com.cn/s/blog_608475eb0100g6qc.html" rel="nofollow">http://blog.sina.com.cn/s/blog_608475eb0100g6qc.html</a></p></div><img src ="http://www.blogjava.net/ljc-java/aggbug/363160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2011-11-08 11:41 <a href="http://www.blogjava.net/ljc-java/articles/363160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件工程师不可不知的10个概念</title><link>http://www.blogjava.net/ljc-java/archive/2011/08/31/357649.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Wed, 31 Aug 2011 08:40:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/archive/2011/08/31/357649.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/357649.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/archive/2011/08/31/357649.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/357649.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/357649.html</trackback:ping><description><![CDATA[<div><span style="color: #323e32; font-family: Verdana, 宋体, sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: #dceccc; ">出色的软件工程师善用设计模式，勤于代码重构，编写单元测试，并对简单有宗教般的追求。除了这些，优秀的软件工程师还要通晓10个概念，这10个概念超越了编程语言与设计模式，软件工程师应当从更广的范围内明白这些道理。<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　10. 关系数据库 (Relational Databases)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　关系数据库因为在大规模 Web 服务上缺乏可扩充性而颇受微词，然而，关系数据库仍然是近20年来计算机技术中最伟大的成就。关系数据库对处理订单，公司数据方面有着出色的表现。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　关系数据库的核心是以记录表示数据，记录存放在数据库表，数据库使用查询语言(SQL)对数据进行搜索与查询，同时，数据库对各个数据表进行关联。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　数据库的标准化技术(normalization)讲的是使用正确的方式对数据进行分存以降低冗余，并加快存取速度。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　9. 安全 (Security)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　随着黑客的崛起与数据敏感性的上升，安全变得非常重要。安全是个广义的概念，涉及验证，授权与信息传输。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　验证是对用户的身份进行检查，如要求用户输入密码。验证通常需要结合 SSL (secure socket layer)进行;授权在公司业务系统中非常重要，尤其是一些工作流系统。最近开发的 OAuth 协议可以帮助 Web 服务将相应信息向相应用户开放。Flickr 便使用这种方式管理私人照片和数据的访问权限。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　另外一个安全领域是网络设防，这关系到操作系统，配置与监控。不仅网络危险重重，任何软件都是。Firefox 被称为最安全的浏览器，仍然需要频频发布安全补丁。要为你的系统编写安全代码就需要明白各种潜在的问题。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　8. 云计算 (Cloud Computing)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　RWW 最近的关于云计算的文章 Reaching For The Sky Through Compute Clouds 讲到了云计算如何改变大规模 Web 应用的发布。大规模的并行，低成本，与快速投入市场。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　并行算法发明以来，首先迎来的是网格计算，网格计算是借助空闲的桌面计算机资源进行并行计算。最著名的例子是 Berkley 大学的&nbsp;SETI@home&nbsp;计划，该计划使用空闲的 CPU 资源分析太空数据。金融机构也大规模实施网格计算进行风险分析。空闲的资源，加上 J2EE 平台的崛起，迎来了云计算的概念：应用服务虚拟化。就是应用按需运行，并可以随着时间和用户规模而实时改变。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　云计算最生动的例子是 Amazon 的 Web 服务，一组可以通过 API 进行调用的应用，如云服务(EC2)，一个用来存储大型媒体文件的数据库(S3)，索引服务(SimpleDB)，序列服务(SQS)。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　7. 并发 (Concurrency)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　并发是软件工程师最容易犯错的地方，这可以理解，因为我们一直遵从线形思维，然而并发在现代系统中非常重要。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　并发是程序中的并行处理，多数现代编程语言包含内置的并发能力，在 Java，指的是线程。关于并发，最经典的例子是&#8220;生产/消费&#8221;模式，生产方生产数据和任务，并放入工作线程消费或执行。并发的复杂性在于，线程需要经常访问共同数据，每个线程都有自己的执行顺序，但需要访问共同数据。Doug Lea 曾写过一个最复杂的并发类，现在是 core Java 的一部分。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　6. 缓存(Caching)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　缓存对现代 Web 程序不可或缺，缓存是从数据库取回，并存放在内存中的数据。因为数据库直接存取的代价非常高，将数据从数据库取回并放在缓存中访问就变得十分必要。比如，你有一个网站，要显示上周的畅销书，你可以从数据将畅销书榜一次性取回放在缓存中，而不必在每次访问时都去数据库读数据。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　缓存需要代价，只有最常用的内容才可以放入缓存。很多现代程序，包括 Facebook，依靠一种叫做 Memcached 的分布式缓存系统，该系统是 Brad Firzpatrick 在工作于 LiveJournal 项目时开发的，Memcached 使用网络中空闲的内存资源建立缓存机制，Memcached 类库在很多流行编程语言，包括 Java 和 PHP 中都有。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　5. 散列法(Hashing)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　Hashing 的目的是加速访问速度。如果数据是序列存储的，从中查询一个项的时间取决于数据列的大小。而散列法对每一个项计算一个数字作为索引，在一个好的 Hashing 算法下，数据查找的速度是一样的。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　除了存储数据，散列法对分布式系统也很重要。统一散列法(uniform hash )用来在云数据库环境下，在不同计算机之间分存数据。Google 的索引服务就是这种方法的体现，每一个 URL 都被散列分布到特定计算机。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　散列函数非常复杂，但现代类库中都有现成的类，重要的是，如何对散列法进行细调以获得最好的性能。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　4. 算法的复杂性 (Algorithmic Complexity)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　关于算法的复杂性，软件工程师需要理解这样几件事。第一，大O标记法(big O notation);第二，你永远都不应该使用嵌套式循环(循环里面套循环)，你应该使用 Hash 表，数组或单一循环;第三，如今优秀类库比比皆是，我们不必过分纠缠于这些库的效能的差别，我们以后还有机会进行细调;最后，</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">不要忽视算法的优雅及性能，编写紧凑的，可读的代码可以让你的算法更简单，更干净。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　3. 分层 (Layering)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　用分层来讨论软件架构是最容易的。John Lakos 曾出版过一本关于大型 C++ 系统的书。Lakos 认为软件包含了层，书中介绍了层的概念，方法是，对每个软件组件，数一下它所依赖的组件数目就可以知道它的复杂程度。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　Lakos 认为，一个好的软件拥有金字塔结构，就是说，软件组件拥有层层积累的复杂度，但每个组件本身必须简单，一个优秀的软件包含很多小的，可重复使用的模块，每个模块有自己的职责。一个好的系统中，组件之间的依赖性不可交叉，整个系统是各种各样的组件堆积起来，形成一个金字塔。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　Lakos 在软件工程的很多方面都是先驱，最著名的是 Refactoring (代码重构)。代码重构指的是，在编程过程中需要不断地对代码进行改造以保证其结构的健壮与灵活。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　2. 惯例与模板 (Conventions and Templates)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　命名惯例和基础模板在编程模式中常被忽视，然而它可能是最强大的方法。命名惯例使软件自动化成为可能，如，Java Beans 框架在 getter 和 setter 方法中，使用简单的命名惯例。del.icio.us 网站的 URL 命名也使用统一的格式，如http://del.icio.us/tag/software&nbsp;会将用户带到所有标签为 software 的页。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　很多社会网络均使用简单命名，如，你的名字是 johnsmith ，那你的头像可能命名为 johnsmith.jpg，而你的 rss 聚合文件的命名很可能是 johnsmith.xml 。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　命名惯例还用于单元测试，如，JUnit 单元测试工具会辨认所有以 test 开头的类。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　我们这里说的模板(templates )指的并不是 C++ 或 Java 语言中的 constructs，我们说的是一些包含变量的模板文件，用户可以替换变量并输出最终结果。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　Cold Fusion 是最先使用模板的程序之一，后来，Java 使用 JSP 实现模板功能。Apache 近来为 Java 开发了非常好用的通用模板, Velocity。PHP 本身就是基于模板的，因为它支持 eval 函数。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　1. 界面(Interfaces)</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　软件工程中最重要的概念是界面。任何软件都是一个真实系统的模型。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; "><br /></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">如何使用简单的用户界面进行模型化至关重要。很多软件系统走这样的极端，缺乏抽象的冗长代码，或者过分设计而导致无谓的复杂。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　在众多软件工程书籍中，Robert Martin 写的《敏捷编程》值得一读。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 5px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; list-style-type: none; list-style-position: initial; list-style-image: initial; word-wrap: normal; word-break: normal; line-height: 18px; ">　　关于模型化，以下方法对你会有帮助。首先，去掉那些只有在将来才可能用得着的方法，代码越精练越好。第二，不要总认为以前的东西是对的，要善于改变。第三，要有耐心并享受过程。</p></span></div><img src ="http://www.blogjava.net/ljc-java/aggbug/357649.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2011-08-31 16:40 <a href="http://www.blogjava.net/ljc-java/archive/2011/08/31/357649.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>介绍几种工作流的模式(转载)</title><link>http://www.blogjava.net/ljc-java/articles/356845.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Fri, 19 Aug 2011 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/articles/356845.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/356845.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/articles/356845.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/356845.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/356845.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="color: #6b6759; font-family: Georgia; font-size: 12px; letter-spacing: 2px; line-height: 20px; background-color: #d2c0ac; "><table class="MsoNormalTable FCK__ShowTableBorders" border="0" cellpadding="0" width="100%" style="line-height: normal; table-layout: auto !important; width: 804px; "><tbody style="line-height: normal; "><tr style="line-height: normal; "><td style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; font-size: 12px; line-height: normal; border-bottom-color: #ece9d8; border-bottom-width: initial; border-bottom-style: initial; border-left-color: #ece9d8; border-left-width: initial; border-left-style: initial; padding-bottom: 0.75pt; background-color: transparent; padding-left: 0.75pt; padding-right: 0.75pt; border-top-color: #ece9d8; border-top-width: initial; border-top-style: initial; border-right-color: #ece9d8; border-right-width: initial; border-right-style: initial; padding-top: 0.75pt; "><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><span style="line-height: normal; color: black; font-size: 10pt; ">原地址：<a href="http://gocom.primeton.com/modules/newbb/item40732_40732.htm?PHPSESSID=b3d40a5147b401adc250801cdef036cf&amp;referer=csdn&amp;utm_campaign=gocom&amp;utm_source=csdn&amp;utm_medium=lks" style="font-size: 12px; color: #6b6759; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://gocom.primeton.com/modules/newbb/item40732_40732.htm?PHPSESSID=b3d40a5147b401adc250801cdef036cf&amp;referer=csdn&amp;utm_campaign=gocom&amp;utm_source=csdn&amp;utm_medium=lks</a></span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><span style="line-height: normal; color: black; font-size: 10pt; ">摘要：介绍几种工作流的模式</span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><span style="line-height: normal; color: black; font-size: 10pt; ">作者：刘航</span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">工作流的基本模式</span></strong></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">1</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">、顺序（</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">Sequence</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）模式</span></strong></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">描述：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">只有当前一个活动结束后，后一个活动才会被触发，即按照预定的任务列表，有序的执行。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><span style="line-height: normal; color: black; font-size: 10pt; "><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/1eed7e62450c8a7eeaf8f821.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span></span><br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">举例：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">对于一个</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">的处理就满足该模式。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/6dfcf0df6e519dd577c63822.jpg" style="line-height: normal; "  alt="" /></span><br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">2</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">、并行（</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">Parallel Split</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）模式</span></strong><span style="line-height: normal; color: black; font-size: 10pt; "></span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">描述：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">一个活动的结束能够触发若干个活动的开始，这些被触发的活动能以并行的方式同时或按任意顺序进行。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><span style="line-height: normal; "><br style="line-height: normal; " /></span><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/76e6120a317a120ae824882c.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span><br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">举例：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">当提交一个</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">时会分别向</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">信息表和</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">日志表中添加相应记录</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/23da5c56a861d06e574e002c.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span></span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">3</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">、同步（</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">Synchronization</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）模式</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; "></span></strong></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">描述：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">如果不考虑超时（一般流程会设定任务执行期限）和异常等情况，流程必须在聚合点等待所有的分支都执行完（到达</span><span style="line-height: normal; color: black; font-size: 10pt; ">And&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">汇聚点）才能激活后继任务，才能正确的往下运行。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/3fe3755b746ed9102934f02d.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span><br style="line-height: normal; " /><br style="line-height: normal; " /></span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">举例：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">支持人员分派的问题由开发人员修改，然后不仅要经过测试人员验证通过还要再次经支持人员验证通过才能</span><span style="line-height: normal; color: black; font-size: 10pt; ">Close</span><span style="line-height: normal; color: black; font-size: 10pt; ">该</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><br style="line-height: normal; " /></span><span style="line-height: normal; color: black; font-size: 10pt; "><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/b61698b35455446e08230228.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span><br style="line-height: normal; " /></span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">4&nbsp;</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">独占式选择（</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">Exclusive Choice</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）模式</span></strong></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><span style="line-height: normal; color: black; font-size: 10pt; ">　　该模式分为显式独占模型（</span><span style="line-height: normal; color: black; font-size: 10pt; ">explic Exclusive Choice&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">）和隐式独占选择模式（</span><span style="line-height: normal; color: black; font-size: 10pt; ">implicit</span><span style="line-height: normal; color: black; font-size: 10pt; ">　</span><span style="line-height: normal; color: black; font-size: 10pt; ">Exclusive Choice</span><span style="line-height: normal; color: black; font-size: 10pt; ">）</span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><span style="line-height: normal; color: black; font-size: 10pt; ">　　</span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">1</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）显式独占选模型（</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">explic Exclusive Choice&nbsp;</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）</span></strong></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">描述：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">当一个活动处理完后，其后有若干个分支流程可供选择，但根据工作流控制数据（</span><span style="line-height: normal; color: black; font-size: 10pt; "><a target="_blank" href="http://gocom.primeton.com/modules/gSpace/about_onetag.php?tagid=73&amp;tagname=workflow&amp;PHPSESSID=bd7df46d3fee159d870ef6d6f4cf8b5f" style="font-size: 12px; color: #6b6759; text-decoration: none; line-height: 20px; font-family: Georgia; "><span style="line-height: normal; color: #006699; ">workflow</span></a></span><span style="line-height: normal; color: black; font-size: 10pt; ">&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">control data</span><span style="line-height: normal; color: black; font-size: 10pt; ">）只允许选择其中某一个分支运行。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><br style="line-height: normal; " /><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/7f14b446c07c54b8b3b7dc2a.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span><br style="line-height: normal; " /></span><span style="line-height: normal; color: black; font-size: 10pt; ">　　如上图所示，虽然在任务</span><span style="line-height: normal; color: black; font-size: 10pt; ">Task A&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">后可以三个不同的活动流程可被选择，但是仅</span><span style="line-height: normal; color: black; font-size: 10pt; ">Task D&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">满足条件，造成后续的流程中，走了</span><span style="line-height: normal; color: black; font-size: 10pt; ">A&#8212;&#8212;D&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">分支，而另外的分支被抛弃。</span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">举例：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">当</span><span style="line-height: normal; color: black; font-size: 10pt; ">PSO</span><span style="line-height: normal; color: black; font-size: 10pt; ">人员提交一个问题时，该问题的类型需要被确定。如果是产品的错误而引起的那么问题类型即为</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">；如果是由于客户的操作失误而引起的那么问题类型即为</span><span style="line-height: normal; color: black; font-size: 10pt; ">ISSUE</span><span style="line-height: normal; color: black; font-size: 10pt; ">；如是对产品的有价值的建议，那么问题的类型即为</span><span style="line-height: normal; color: black; font-size: 10pt; ">ADVICE</span><span style="line-height: normal; color: black; font-size: 10pt; ">；由上可知，当确定问题类型时三种只能选其一。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/9ac719f1968376f10b46e02b.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span><span style="line-height: normal; color: black; font-size: 10pt; ">　　</span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">2</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）隐式独占选模型（</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">implicit Exclusive Choice&nbsp;</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）</span></strong></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">描述：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">同为</span><span style="line-height: normal; color: black; font-size: 10pt; ">XOR&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">模型，隐式和显式的区别不是太大。唯一的不同点就是，隐式独占选模型在可供选择的分支中存在存在若干个分支满足条件，但最终，依然仅有一个分支运行。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><br style="line-height: normal; " /><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/abdf782076002d9e4723e834.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span><br style="line-height: normal; " /></span><span style="line-height: normal; color: black; font-size: 10pt; ">　　如上图所示，存在分支</span><span style="line-height: normal; color: black; font-size: 10pt; ">A&#8212;C&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">和分支</span><span style="line-height: normal; color: black; font-size: 10pt; ">A&#8212;D&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">都满足条件，但最终也依然只能有一个分支被激活。至于哪一个分支被激活，这可能是人为的操作，也可能是某种随即的自动选择。不论哪种方式，人须保证一个分支被激活后，其他分支被抛弃。</span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">举例：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">PSO</span><span style="line-height: normal; color: black; font-size: 10pt; ">的人员在提交问题的时候，他会根据问题的来源将它提交给负责相应区域的支持人员。但是，具体提交给负责该区域的哪一位支持者，就由</span><span style="line-height: normal; color: black; font-size: 10pt; ">PSO</span><span style="line-height: normal; color: black; font-size: 10pt; ">的人员自己决定或系统随机产生。不管如何选择都必须有一位支持人员要接收该问题。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">&nbsp;<span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/3cce20f8058776b39f514634.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span></span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span><span style="line-height: normal; color: black; font-size: 10pt; ">　　不管是显式独占模型（</span><span style="line-height: normal; color: black; font-size: 10pt; ">explic Exclusive Choice&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">）还是隐式独占选择模式（</span><span style="line-height: normal; color: black; font-size: 10pt; ">implicit Exclusive Choice</span><span style="line-height: normal; color: black; font-size: 10pt; ">）他们的执行流程都是一样的。</span></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><span style="line-height: normal; color: black; font-size: 10pt; ">　　</span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">5</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">、简单聚合（</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">Simple Merge</span></strong><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">）模型</span></strong></p><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">描述：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">前面的若干个分支，只要有一个活动被执行（假定不存在两个分支同时被执行），后面的活动就会被触发。当然，一旦某一个分支被通过。则余下的分支则被终止，或者运行到聚合点就结束。</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/0fd885edfd8daad5cf1b3e35.jpg" style="line-height: normal; "  alt="" /><br style="line-height: normal; " /></span><br style="line-height: normal; " />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; ">&nbsp;</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span><strong style="line-height: normal; "><span style="line-height: normal; color: black; font-size: 10pt; ">举例：</span></strong><span style="line-height: normal; color: black; font-size: 10pt; ">如果产品中存在某个</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">那么可能会被不同地方的用户发现，但只要有一个地方的</span><span style="line-height: normal; color: black; font-size: 10pt; ">PSO</span><span style="line-height: normal; color: black; font-size: 10pt; ">人员提出这个问题</span><span style="line-height: normal; color: black; font-size: 10pt; ">BUG</span><span style="line-height: normal; color: black; font-size: 10pt; ">就会得到处理。当其它地方的</span><span style="line-height: normal; color: black; font-size: 10pt; ">PSO</span><span style="line-height: normal; color: black; font-size: 10pt; ">再次提出该问题的时候就不会重复处理了</span><span style="line-height: normal; color: black; font-size: 10pt; "><br style="line-height: normal; " /></span></p></td></tr><tr style="line-height: normal; "><td style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; font-size: 12px; line-height: normal; border-bottom-color: #ece9d8; border-bottom-width: initial; border-bottom-style: initial; border-left-color: #ece9d8; border-left-width: initial; border-left-style: initial; padding-bottom: 0.75pt; background-color: transparent; padding-left: 0.75pt; padding-right: 0.75pt; border-top-color: #ece9d8; border-top-width: initial; border-top-style: initial; border-right-color: #ece9d8; border-right-width: initial; border-right-style: initial; padding-top: 0.75pt; "><p class="MsoNormal" align="left" style="line-height: normal; text-align: left; margin-top: 0cm; margin-right: 0cm; margin-bottom: 0pt; margin-left: 0cm; word-break: break-all; "><span style="line-height: normal; color: black; font-size: 10pt; "><span style="line-height: normal; "><img class="blogimg" border="0" small="0" src="http://hiphotos.baidu.com/xionglian1123/pic/item/aeea1cf5ad1e9518730eec36.jpg" style="line-height: normal; "  alt="" /></span></span></p></td></tr></tbody></table></span><img src ="http://www.blogjava.net/ljc-java/aggbug/356845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2011-08-19 11:47 <a href="http://www.blogjava.net/ljc-java/articles/356845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>给Grails开发者的10个建议(转载)</title><link>http://www.blogjava.net/ljc-java/archive/2011/08/19/356844.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Fri, 19 Aug 2011 03:43:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/archive/2011/08/19/356844.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/356844.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/archive/2011/08/19/356844.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/356844.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/356844.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-family: Arial; font-size: 12px; line-height: 20px; background-color: #d2c0ac; "><p style="line-height: normal; ">from InfoQ &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.infoq.com/cn/news/2009/02/grails-10-tips&amp;usg=AFQjCNEsWTmWC5663oSojc52MAglwtQLpA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.infoq.com/cn/news/2009/02/grails-10-tips</a>&gt;</p><p style="line-height: normal; ">如果要列举近些年来Java领域中最令人激动的事件，Grails的诞生绝对应该榜上有名。在打开Grails官方网站&lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.grails.org/&amp;usg=AFQjCNGDWpJ4NLMjdlfi3rn5gAH-9HVdFA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.grails.org/</a>&gt;时，&nbsp;<br style="line-height: normal; " />你会在浏览器的标题栏上看到这样的内容：&#8220;Grails - 寻找就此结束&#8221;。虽然这句话不见得适用于所有场合，但对于不少从事Java&nbsp;<br style="line-height: normal; " />Web开发的人来说，赞同者恐怕不在少数。由于具备Rails风格的框架、兼容绝大多数Java语法的Groovy动态语言、以业界口碑良好的框架为基&nbsp;<br style="line-height: normal; " />础、对企业现有Java开发资产的保护、Plugin架构等特点，再加上Spring社区的强力介入，Grails行情看涨应该是意料之中的。</p><p style="line-height: normal; ">然而Grails却没有看上去那么简单，在其包装的糖衣之下，有着许多作为Java Web开发者不得不了解的知识。最近，Peter&nbsp;<br style="line-height: normal; " />Delahunty&lt;<a href="http://www.google.com/url?sa=D&amp;q=http://blog.peterdelahunty.com/&amp;usg=AFQjCNGHrDOa5hB7sxQOETdXuguatEdC1w" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://blog.peterdelahunty.com/</a>&gt;&nbsp;<br style="line-height: normal; " />发表了题为Grails开发者需要知道的10个技巧&lt;<a href="http://www.google.com/url?sa=D&amp;q=http://blog.peterdelahunty.com/2009/02/10-ten-tips-for-grails-developer.html&amp;usg=AFQjCNHHsmHmYWFT01458aI0rz8v8cVaHA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://blog.peterdelahunty.com/2009/02/10-ten-tips-for-grails-develop...</a>&gt;&nbsp;<br style="line-height: normal; " />的博文。不要被标题所迷惑了，这里所说的&#8220;技巧&#8221;可不是那些语言层面的&#8220;技巧&#8221;，把它们称为&#8220;建议&#8221;恐怕更合适一些。</p><p style="line-height: normal; ">技巧1：把Grails的书籍买来读读。对此，Peter Delahunty推荐了已出版的《Definitive Guide to Grails 2nd&nbsp;<br style="line-height: normal; " />edition》和《Groovy and Grails Recipes》，以及即将出版的《Grails in Action》。</p><p style="line-height: normal; ">技巧2：学习Groovy，并按照Groovy进行思考。Peter Delahunty通过一个例子说明了Java思维和Groovy思维的不同。</p><p style="line-height: normal; ">这儿有个好例子：</p><p style="line-height: normal; ">传播操作符（spread operator）：*</p><p style="line-height: normal; ">在Java中，要想遍历一组人并收集人名。我可能得这样写：</p><p style="line-height: normal; ">List names = new ArrayList();&nbsp;<br style="line-height: normal; " />for (Iterator iterator = people.iterator(); iterator.hasNext();) {&nbsp;<br style="line-height: normal; " />Person person = (Person) iterator.next();&nbsp;<br style="line-height: normal; " />names.add(person.getName());</p><div class="qt" style="font-family: Arial; word-wrap: break-word; word-break: break-all; visibility: visible !important; zoom: 1 !important; filter: none; font-size: 12px; line-height: normal; display: block; ">}</div>System.out.println(names);&nbsp;<br style="line-height: normal; " /><p style="line-height: normal; ">用Groovy，我会这么写：</p><p style="line-height: normal; ">def names = people*.name&nbsp;<br style="line-height: normal; " />println names</p><p style="line-height: normal; ">呵呵，简单吧。我还可以这样写：</p><p style="line-height: normal; ">def names = people.collect {it.name}&nbsp;<br style="line-height: normal; " />println names</p><p style="line-height: normal; ">在这个建议中，他列举了一些资源：</p><p style="line-height: normal; ">- Groovy官方网站 &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://groovy.codehaus.org/&amp;usg=AFQjCNFVxAFH0a_xYOxU5FKLzdlZNY4FnA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://groovy.codehaus.org/</a>&gt;&nbsp;<br style="line-height: normal; " />- PLEAC &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://pleac.sourceforge.net/pleac_groovy/index.html&amp;usg=AFQjCNGplGB3sfqQAFSBjR4osyQgH8VS9Q" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://pleac.sourceforge.net/pleac_groovy/index.html</a>&gt;</p><p style="line-height: normal; ">以及一些书籍：</p><p style="line-height: normal; ">- Programming Groovy&nbsp;<br style="line-height: normal; " />- Groovy Recipies&nbsp;<br style="line-height: normal; " />- Groovy in action</p><p style="line-height: normal; ">技巧3：了解Grails的各个插件。Peter&nbsp;<br style="line-height: normal; " />Delahunty给出的理由：Grails本身是个插件系统，而且现在已经有大量的插件可供下载。在自行实现之前，不妨看看其中是否有称手的。</p><p style="line-height: normal; ">技巧4：学习Hibernate和Spring。这一点不难理解，既然Grails是建立在这些工具之上的，了解这些工具本身的使用，对于熟练使用Grails 自然大有脾益。</p><p style="line-height: normal; ">技巧5：使单元测试、集成测试和一般测试的自动化。Peter Delahunty在这里推荐了两个Grails的插件：Testing&nbsp;<br style="line-height: normal; " />Plugin&lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.grails.org/Testing%2BPlugin&amp;usg=AFQjCNGJl5dVQlu7O9s83HsWnF56oDgJHA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.grails.org/Testing+Plugin</a>&gt;&nbsp;<br style="line-height: normal; " />和Functional testing plugin&nbsp;<br style="line-height: normal; " />&lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.grails.org/Grails%2BFunctional%2BTesting&amp;usg=AFQjCNEcCQcRvNGJHPrSrKDxYPFSmRR6_g" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.grails.org/Grails+Functional+Testing</a>&gt;。前者将成为Grails&nbsp;<br style="line-height: normal; " />1.1的内置插件。</p><p style="line-height: normal; ">技巧6：使用好的IDE。Peter Delahunty表示，他自己使用的是Intellij，但对于Netbeans也寄予厚望。</p><p style="line-height: normal; ">技巧7：学习并使用HTML W3C标准。&#8220;遵循标准将消除你90%的问题&#8221;，Peter Delahunty如是说。</p><p style="line-height: normal; ">技巧8：看上去不错一定不错。这其实说的是&#8220;面子工程&#8221;，通过提高应用的外观设计来提高应用的竞争力。Peter Delahunty给出了2个资源：</p><p style="line-height: normal; ">- 99designs.com&nbsp;<br style="line-height: normal; " />- 圆角矩形产生器 &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.roundedcornr.com/&amp;usg=AFQjCNHUjanSWW-yywDgd1OShkPkyl8O0Q" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.roundedcornr.com/</a>&gt;</p><p style="line-height: normal; ">技巧9：使用Firefox上的Firebug。对于浏览器端的调试工作，Firebug绝对是一个必备工具。</p><p style="line-height: normal; ">技巧10：跟上Groovy和Grails社区的步伐。在这最后一个建议中，Peter&nbsp;<br style="line-height: normal; " />Delahunty给出了获取Groovy和Grails信息的主要资源链接：</p><p style="line-height: normal; ">- Grails官方网站 &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.grails.org/&amp;usg=AFQjCNGDWpJ4NLMjdlfi3rn5gAH-9HVdFA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.grails.org/</a>&gt;&nbsp;<br style="line-height: normal; " />- Groovy和Grails相关的博客 &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://groovyblogs.org/entries/recent&amp;usg=AFQjCNHRRqk-ta_6q_ebcJ8HmIybBp-mBA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://groovyblogs.org/entries/recent</a>&gt;&nbsp;<br style="line-height: normal; " />- Grails创始人Graeme Rocher的Twitter &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://twitter.com/graemerocher&amp;usg=AFQjCNHzMC7S837ttVx3GPOBY0SlwDdbdA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://twitter.com/graemerocher</a>&gt;&nbsp;<br style="line-height: normal; " />- Groovy项目领导人Guillaume Laforge的Twitter &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://twitter.com/glaforge&amp;usg=AFQjCNEM8evNtn5XZe3qxfJd8kpA_tMHTA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://twitter.com/glaforge</a>&gt;&nbsp;<br style="line-height: normal; " />- Groovyblogs.org的创始人Glen Smith &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://twitter.com/glen_a_smith&amp;usg=AFQjCNEoGy0AJlaWiBaJ-BKpQVhn4kpAmw" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://twitter.com/glen_a_smith</a>&gt;</p><p style="line-height: normal; ">请务必阅读Peter Delahunty的原文&lt;<a href="http://www.google.com/url?sa=D&amp;q=http://blog.peterdelahunty.com/2009/02/10-ten-tips-for-grails-developer.html&amp;usg=AFQjCNHHsmHmYWFT01458aI0rz8v8cVaHA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://blog.peterdelahunty.com/2009/02/10-ten-tips-for-grails-develop...</a>&gt;。对于Grails的新老使用者，你都可以从Peter&nbsp;<br style="line-height: normal; " />Delahunty的建议中有所收获。关于InfoQ中文站Groovy和Grails的其它内容，请访问这里&lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.infoq.com/cn/groovy&amp;usg=AFQjCNEnmj98ciMtu2jt6VdgJ5oKtqj5lA" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.infoq.com/cn/groovy</a>&gt;&nbsp;<br style="line-height: normal; " />和这里 &lt;<a href="http://www.google.com/url?sa=D&amp;q=http://www.infoq.com/cn/grails&amp;usg=AFQjCNHyCmVieZPR4E7f3NaBdXx54JU5bQ" rel="nofollow" target="_blank" style="font-size: 12px; color: #0000cc; text-decoration: none; line-height: 20px; font-family: Georgia; ">http://www.infoq.com/cn/grails</a>&gt;。</p></span><img src ="http://www.blogjava.net/ljc-java/aggbug/356844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2011-08-19 11:43 <a href="http://www.blogjava.net/ljc-java/archive/2011/08/19/356844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实战 Groovy: for each 剖析(转载)</title><link>http://www.blogjava.net/ljc-java/archive/2011/08/04/355737.html</link><dc:creator>小罗</dc:creator><author>小罗</author><pubDate>Thu, 04 Aug 2011 03:50:00 GMT</pubDate><guid>http://www.blogjava.net/ljc-java/archive/2011/08/04/355737.html</guid><wfw:comment>http://www.blogjava.net/ljc-java/comments/355737.html</wfw:comment><comments>http://www.blogjava.net/ljc-java/archive/2011/08/04/355737.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ljc-java/comments/commentRss/355737.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ljc-java/services/trackbacks/355737.html</trackback:ping><description><![CDATA[<div><p> 迭代是编程的基础。您经常会遇到需要进行逐项遍历的内容，比如 <code>List</code>、<code>File</code> 和 JDBC <code>ResultSet</code>。Java 语言几乎总是提供了某种方法帮助您逐项遍历所需的内容，但令人沮丧的是，它并没有给出一种标准方法。Groovy 的迭代方法非常实用，在这一点上，Groovy 编程与 Java 编程截然不同。通过一些代码示例，本文将介绍 Groovy 的万能的 <code>each()</code> 方法，从而将 Java 语言的那些迭代怪癖抛在脑后。 </p> 			<p><a name="N10091">Java 迭代策略</a></p> 			<p> 假设您有一个 Java 编程语言的 <code>java.util.List</code>。清单 1 展示了在 Java 语言中如何使用编程实现迭代： </p> 			<br /><a name="listing1"><strong>清单 1. Java 列表迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="87" width="3229"><tbody><tr><td><pre>import java.util.*;  <br />public class ListTest{<br />&nbsp;public static void main(String[] args){<br />&nbsp;List&lt;String&gt; list = new ArrayList&lt;String&gt;();<br />&nbsp;list.add("Java");<br />&nbsp;list.add("Groovy");<br />&nbsp;list.add("JavaScript");<br />&nbsp;for(Iterator&lt;String&gt; i = list.iterator(); i.hasNext();){<br />&nbsp;String language = i.next();<br />&nbsp;System.out.println("I know " + language);<br />&nbsp;}<br />&nbsp;}<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 由于提供了大部分集合类都可以共享的 <code>java.lang.Iterable</code> 接口，您可以使用相同的方法遍历 <code>java.util.Set</code> 或 <code>java.util.Queue</code>。 </p> 			<div ibm-alt-header="" dw-container-sidebar=""><h2>关于本系列</h2><div> 				 				<p>Groovy 是一款运行在 Java 平台之上的现代编程语言。它能够与现有 Java 代码无缝集成，同时引入了闭包和元编程等出色的新特性。简而言之，Groovy 类似于 21 世纪的 Java 语言。 </p> 				<p>如果要将新工具集成到开发工具箱中，最关键的是理解什么时候需要使用它以及什么时候不适合使用它。Groovy 可以变得非常强大，但前提是它被适当地应用到合适的场景中。因此，<a href="http://www.ibm.com/developerworks/cn/java/j-pg/"> 						<em>实战 Groovy</em> 					</a> 系列旨在展示 Groovy 的实际使用，以及何时和如何成功应用它。 </p> 			</div></div> 			<p> 现在，假设该语言存储在 <code>java.util.Map</code> 中。在编译时，尝试对 <code>Map</code> 获取 <code>Iterator</code> 会导致失败 &#8212; 				<code> Map</code> 并没有实现 <code>Iterable</code> 接口。幸运的是，可以调用 <code>map.keySet()</code> 返回一个 <code>Set</code>，然后就可以继续处理。这些小差异可能会影响您的速度，但不会妨碍您的前进。需要注意的是，<code>List</code>、<code>Set</code> 和 <code>Queue</code> 实现了 <code>Iterable</code>，但是 <code>Map</code> 没有 &#8212; 即使它们位于相同的 <code>java.util</code> 包中。 </p> 			<p> 现在假设该语言存在于 <code>String</code> 数组中。数组是一种数据结构，而不是类。不能对 <code>String</code> 数组调用 <code>.iterator()</code>，因此必须使用稍微不同的迭代策略。您再一次受到阻碍，但可以使用如清单 2 所示的方法解决问题： </p> 			<br /><a name="listing2"><strong>清单 2. Java 数组迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="182" width="416"><tbody><tr><td><pre>public class ArrayTest{<br />&nbsp;public static void main(String[] args){<br />&nbsp;String[] list = {"Java", "Groovy", "JavaScript"};<br />&nbsp;for(int i = 0; i &lt; list.length; i++){<br />&nbsp;String language = list[i];<br />&nbsp;System.out.println("I know " + language);<br />&nbsp;}<br />&nbsp;}<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 但是等一下 &#8212; 使用 Java 5 引入的 for-each 语法怎么样？它可以处理任何实现 <code>Iterable</code> 的类和数组，如清单 3 所示： </p> 			<br /><a name="listing3"><strong>清单 3. Java 语言的 for-each 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="308" width="443"><tbody><tr><td><pre>import java.util.*;<br />&nbsp;public class MixedTest{<br />&nbsp;public static void main(String[] args){<br />&nbsp;List&lt;String&gt; list = new ArrayList&lt;String&gt;();<br />&nbsp;list.add("Java");<br />&nbsp;list.add("Groovy");<br />&nbsp;list.add("JavaScript");<br />&nbsp;for(String language: list){<br />&nbsp;System.out.println("I know " + language);<br />&nbsp;}      <br />String[] list2 = {"Java", "Groovy", "JavaScript"};<br />&nbsp;for(String language: list2){<br />&nbsp;System.out.println("I know " + language);<br />&nbsp;}<br />&nbsp;}<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 因此，您可以使用相同的方法遍历数组和集合（<code>Map</code> 除外）。但是如果语言存储在 <code>java.io.File</code>，那该怎么办？如果存储在 JDBC <code>ResultSet</code>，或者存储在 XML 文档、<code>java.util.StringTokenizer</code> 中呢？面对每一种情况，必须使用一种稍有不同的迭代策略。这样做并不是有什么特殊目的 &#8212; 而是因为不同的 API 是由不同的开发人员在不同的时期开发的 &#8212; 但事实是，您必须了解 6 个 Java 迭代策略，特别是使用这些策略的特殊情况。  </p> 			<p> Eric S. Raymond 在他的 <em>The Art of Unix Programming</em> 一书中解释了  &#8220;最少意外原则&#8221;。他写道，&#8220;要设计可用的接口，最好不要设计全新的接口模型。新鲜的东西总是难以入门；会为用户带来学习的负担，因此应当尽量减少新内 容。&#8221;Groovy 对迭代的态度正是采纳了 Raymond 的观点。在 Groovy 中遍历几乎任何结构时，您只需要使用 <code>each()</code> 这一种方法。 </p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N1015E">Groovy 中的列表迭代</a></p> 			<p> 首先，我将 <a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#listing3">清单 3</a> 中的 <code>List</code> 重构为 Groovy。在这里，只需要直接对列表调用 <code>each()</code> 方法并传递一个闭包，而不是将 <code>List</code> 转换成 <code>for</code> 循环（顺便提一句，这样做并不是特别具有面向对象的特征，不是吗）。 </p> 			<p> 创建一个名为 listTest.groovy 的文件并添加清单 4 中的代码：</p> 			<br /><a name="listing4"><strong>清单 4. Groovy 列表迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="38" width="691"><tbody><tr><td><pre>def list = ["Java", "Groovy", "JavaScript"] list.each{language-&gt;   println language } </pre></td></tr></tbody></table><br /> 			<p> 清单 4 中的第一行是 Groovy 用于构建 <code>java.util.ArrayList</code> 的便捷语法。可以将 <code>println list.class</code> 添加到此脚本来验证这一点。接下来，只需对列表调用 <code>each()</code>，并在闭包体内输出 <code>language</code> 变量。在闭包的开始处使用 <code>language-&gt;</code> 语句命名 <code>language</code> 变量。如果没有提供变量名，Groovy 提供了一个默认名称 <code>it</code>。在命令行提示符中输入 <code>groovy listTest</code> 运行 listTest.groovy。</p> 			<p>清单 5 是经过简化的 <a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#listing4">清单 4</a> 代码版本：</p> 			<br /><a name="listing5"><strong>清单 5. 使用 Groovy 的 <code>it</code> 变量的迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="110" width="502"><tbody><tr><td><pre> // shorter, using the default it variable <br />def list = ["Java", "Groovy", "JavaScript"]<br />&nbsp;list.each{ println it }<br />&nbsp;// shorter still, using an anonymous <br />list ["Java", "Groovy", "JavaScript"].each{ println it } </pre></td></tr></tbody></table><br /> 			<p> Groovy 允许您对数组和 <code>List</code> 交替使用 <code>each()</code> 方法。为了将 <code>ArrayList</code> 改为 <code>String</code> 数组，必须将 <code>as String[]</code> 添加到行末，如清单 6 所示： </p> 			<br /><a name="listing6"><strong>清单 6. Groovy 数组迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="38" width="635"><tbody><tr><td><pre>def list = ["Java", "Groovy", "JavaScript"] as String[] list.each{println it} </pre></td></tr></tbody></table><br /> 			<p> 在 Groovy 中普遍使用 <code>each()</code> 方法，并且 getter 语法非常便捷（<code>getClass()</code> 和 <code>class</code> 是相同的调用），这使您能够编写既简洁又富有表达性的代码。例如，假设您希望利用反射显示给定类的所有公共方法。清单 7 展示了这个例子： </p> 			<br /><a name="listing7"><strong>清单 7. Groovy 反射</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="236" width="582"><tbody><tr><td><pre>def s = "Hello World"<br />&nbsp;println s <br />println s.class<br />&nbsp;s.class.methods.each{println it}<br />&nbsp;//output: <br />$ groovy reflectionTest.groovy<br />&nbsp;Hello World<br />&nbsp;class java.lang.String<br />&nbsp;public int java.lang.String.hashCode()<br />&nbsp;public volatile int java.lang.String.compareTo(java.lang.Object)<br />&nbsp;public int java.lang.String.compareTo(java.lang.String)<br />&nbsp;public boolean java.lang.String.equals(java.lang.Object) ... </pre></td></tr></tbody></table><br /> 			<p> 脚本的最后一行调用 <code>getClass()</code> 方法。<code>java.lang.Class</code> 提供了一个 <code>getMethods()</code> 方法，后者返回一个数组。通过将这些操作串连起来并对 <code>Method</code> 的结果数组调用 <code>each()</code>，您只使用了一行代码就完成了大量工作。 </p> 			<p> 但是，与 Java for-each 语句不同的是，万能的 <code>each()</code> 方法并不仅限于 <code>List</code> 和数组。在 Java 语言中，故事到此结束。然而，在 Groovy 中，故事才刚刚开始。 </p> 			<p><a name="N1021C">Map 迭代</a></p> 			<p> 从前文可以看到，在 Java 语言中，无法直接迭代 <code>Map</code>。在 Groovy 中，这完全不是问题，如清单 8 所示： </p> 			<br /><a name="listing8"><strong>清单 8. Groovy map 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="38" width="725"><tbody><tr><td><pre>def map = ["Java":"server", "Groovy":"server", "JavaScript":"web"] map.each{ println it } </pre></td></tr></tbody></table><br /> 			<p> 要处理名称/值对，可以使用隐式的 <code>getKey()</code> 和 <code>getValue()</code> 方法，或在包的开头部分显式地命名变量，如清单 9 所示： </p> 			<br /><a name="listing9"><strong>清单 9. 从 map 获得键和值</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="182" width="650"><tbody><tr><td><pre>def map = ["Java":"server", "Groovy":"server", "JavaScript":"web"]<br />&nbsp;map.each{<br />&nbsp;println it.key<br />&nbsp;println it.value<br />&nbsp;}  <br />map.each{k,v-&gt;<br />&nbsp;println k<br />&nbsp;println v<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 可以看到，迭代 <code>Map</code> 和迭代其它任何集合一样自然。 </p> 			<p> 在继续研究下一个迭代例子前，应当了解 Groovy 中有关 <code>Map</code> 的另一个语法。与在 Java 语言中调用 <code>map.get("Java")</code> 不一样，可以简化对 <code>map.Java</code> 的调用，如清单 10 所示： </p> 			<br /><a name="listing10"><strong>清单 10. 获得 map 值</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="92" width="590"><tbody><tr><td><pre>def map = ["Java":"server", "Groovy":"server", "JavaScript":"web"]<br />&nbsp;//identical results<br />&nbsp;println map.get("Java")<br />&nbsp;println map.Java </pre></td></tr></tbody></table><br /> 			<p> 不可否认，Groovy 针对 <code>Map</code> 的这种便捷语法非常酷，但这也是在对 <code>Map</code> 使用反射时引起一些常见问题的原因。对 <code>list.class</code> 的调用将生成 <code>java.util.ArrayList</code>，而调用 <code>map.class</code> 返回 <code>null</code>。这是因为获得 map 元素的便捷方法覆盖了实际的 getter 调用。<code>Map</code> 中的元素都不具有 <code>class</code> 键，因此调用实际会返回 <code>null</code>，如清单 11 的示例所示： </p> 			<br /><a name="listing11"><strong>清单 11. Groovy map 和 <code>null</code> 				</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="236" width="485"><tbody><tr><td><pre>def list = ["Java", "Groovy", "JavaScript"]<br />&nbsp;println list.class<br />&nbsp;// java.util.ArrayList<br />&nbsp;def map = ["Java":"server", "Groovy":"server", "JavaScript":"web"]<br />&nbsp;println map.class<br />&nbsp;// null<br />&nbsp;map.class = "I am a map element"<br />&nbsp;println map.class<br />&nbsp;// I am a map element<br />&nbsp;println map.getClass()<br />&nbsp;// class<br />&nbsp;java.util.LinkedHashMap </pre></td></tr></tbody></table><br /> 			<p>这是 Groovy 比较罕见的打破 &#8220;最少意外原则&#8221; 的情况，但是由于从 map 获取元素要比使用反射更加常见，因此我可以接受这一例外。</p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N102A0">String 迭代</a></p> 			<p> 现在您已经熟悉 <code>each()</code> 方法了，它可以出现在所有相关的位置。假设您希望迭代一个 <code>String</code>，并且是逐一迭代字符，那么马上可以使用 <code>each()</code> 方法。如清单 12 所示： </p> 			<br /><a name="listing12"><strong>清单 12. <code>String</code> 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="74" width="446"><tbody><tr><td><pre>def name = "Jane Smith" name.each{letter-&gt;<br />&nbsp;println letter<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 这提供了所有的可能性，比如使用下划线替代所有空格，如清单 13 所示： </p> 			<br /><a name="listing13"><strong>清单 13. 使用下划线替代空格</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="218" width="515"><tbody><tr><td><pre><br />def name = "Jane Smith"<br />&nbsp;println "replace spaces" <br />name.each{<br />&nbsp;if(it == " "){<br />&nbsp;print "_"<br />&nbsp;}else{<br />&nbsp;print it<br />&nbsp;}<br />&nbsp;}<br />&nbsp;// output Jane_Smith </pre></td></tr></tbody></table><br /> 			<p> 当然，在替换一个单个字母时，Groovy 提供了一个更加简洁的替换方法。您可以将清单 13 中的所有代码合并为一行代码：<code>"Jane Smith".replace(" ", "_")</code>。但是对于更复杂的 <code>String</code> 操作，<code>each()</code> 方法是最佳选择。 </p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N102DF">Range 迭代</a></p> 			<p> Groovy 提供了原生的 <code>Range</code> 类型，可以直接迭代。使用两个点分隔的所有内容（比如 <code>1..10</code>）都是一个 <code>Range</code>。清单 14 展示了这个例子： </p> 			<br /><a name="listing14"><strong>清单 14. Range 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="92" width="361"><tbody><tr><td><pre>def range = 5..10 range.each{<br />&nbsp;println it<br />&nbsp;}<br />&nbsp;//output: 5 6 7 8 9 10 </pre></td></tr></tbody></table><br /> 			<p> 				<code>Range</code> 不局限于简单的 <code>Integer</code>。考虑清单 15 在的代码，其中迭代 <code>Date</code> 的 <code>Range</code>： </p> 			<br /><a name="listing15"><strong>清单 15. <code>Date</code> 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="254" width="447"><tbody><tr><td><pre>def today = new Date()<br />&nbsp;def nextWeek = today + 7<br />&nbsp;(today..nextWeek).each{<br />&nbsp;println it<br />&nbsp;} <br /> //output: Thu Mar 12 04:49:35 MDT 2009<br />&nbsp;Fri Mar 13 04:49:35 MDT 2009 <br />Sat Mar 14 04:49:35 MDT 2009 <br />Sun Mar 15 04:49:35 MDT 2009 <br />Mon Mar 16 04:49:35 MDT 2009 <br />Tue Mar 17 04:49:35 MDT 2009 <br />Wed Mar 18 04:49:35 MDT 2009 <br />Thu Mar 19 04:49:35 MDT 2009 </pre></td></tr></tbody></table><br /> 			<p> 可以看到，<code>each()</code> 准确地出现在您所期望的位置。Java 语言缺乏原生的 <code>Range</code> 类型，但是提供了一个类似地概念，采取 <code>enum</code> 的形式。毫不奇怪，在这里 <code>each()</code> 仍然派得上用场。</p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N10332">Enumeration 类型</a></p> 			<p> Java <code>enum</code> 是按照特定顺序保存的随意的值集合。清单 16 展示了 <code>each()</code> 方法如何自然地配合 <code>enum</code>，就好象它在处理 <code>Range</code> 操作符一样： </p> 			<br /><a name="listing16"><strong>清单 16. <code>enum</code> 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="200" width="417"><tbody><tr><td><pre>enum DAY{<br />&nbsp;MONDAY, TUESDAY, WEDNESDAY, THURSDAY,<br />&nbsp;FRIDAY, SATURDAY, SUNDAY<br />&nbsp;}<br />&nbsp;DAY.each{<br />&nbsp;println it<br />&nbsp;}<br />&nbsp;(DAY.MONDAY..DAY.FRIDAY).each{<br />&nbsp;println it<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 在 Groovy 中，有些情况下，<code>each()</code> 这个名称远未能表达它的强大功能。在下面的例子中，将看到使用特定于所用上下文的方法对 <code>each()</code> 方法进行修饰。Groovy <code>eachRow()</code> 方法就是一个很好的例子。 </p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N10368">SQL 迭代</a></p> 			<p> 在处理关系数据库表时，经常会说 &#8220;我需要针对表中的每一行执行操作&#8221;。比较一下前面的例子。您很可能会说 &#8220;我需要对列表中的每一种语言执行一些操作&#8221;。根据这个道理，<code>groovy.sql.Sql</code> 对象提供了一个 <code>eachRow()</code> 方法，如清单 17 所示： </p> 			<br /><a name="listing17"><strong>清单 17. <code>ResultSet</code> 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="308" width="496"><tbody><tr><td><pre>import groovy.sql.*<br />&nbsp;def sql = Sql.newInstance(<br />&nbsp;"jdbc:derby://localhost:1527/MyDbTest;create=true",<br />&nbsp;"username",<br />&nbsp;"password",<br />&nbsp;"org.apache.derby.jdbc.ClientDriver")<br />&nbsp;println("grab a specific field")<br />&nbsp;sql.eachRow("select name from languages"){ row -&gt;<br />&nbsp;println row.name<br />&nbsp;}<br />&nbsp;println("grab all fields")<br />&nbsp;sql.eachRow("select * from languages"){ row -&gt;<br />&nbsp;println("Name: ${row.name}")<br />&nbsp;println("Version: ${row.version}")<br />&nbsp;println("URL: ${row.url}\n")<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 该脚本的第一行代码实例化了一个新的 <code>Sql</code> 对象：设置 JDBC 连接字符串、用户名、密码和 JDBC 驱动器类。这时，可以调用 <code>eachRow()</code> 方法，传递 SQL <code>select</code> 语句作为一个方法参数。在闭包内部，可以引用列名（<code>name</code>、<code>version</code>、<code>url</code>），就好像实际存在 <code>getName()</code>、<code>getVersion()</code> 和 <code>getUrl()</code> 方法一样。 </p> 			<p> 这显然要比 Java 语言中的等效方法更加清晰。在 Java 中，必须创建单独的 <code>DriverManager</code>、<code>Connection</code>、<code>Statement</code> 和 <code>JDBCResultSet</code>，然后必须在嵌套的 <code>try</code>/<code>catch</code>/<code>finally</code> 块中将它们全部清除。 </p> 			<p> 对于 <code>Sql</code> 对象，您会认为 <code>each()</code> 或 <code>eachRow()</code> 都是一个合理的方法名。但是在接下来的示例中，我想您会认为 <code>each()</code> 这个名称并不能充分表达它的功能。 </p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N103E0">文件迭代</a></p> 			<p> 我从未想过使用原始的 Java 代码逐行遍历 <code>java.io.File</code>。当我完成了所有的嵌套的 <code>BufferedReader</code> 和 <code>FileReader</code> 后（更别提每个流程末尾的所有异常处理），我已经忘记最初的目的是什么。 </p> 			<p> 清单 18 展示了使用 Java 语言完成的整个过程： </p> 			<br /><a name="listing18"><strong>清单 18. Java 文件迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="578" width="487"><tbody><tr><td><pre>import java.io.BufferedReader;<br />&nbsp;import java.io.FileNotFoundException;<br />&nbsp;import java.io.FileReader; import java.io.IOException;<br />&nbsp;public class WalkFile {<br />&nbsp;public static void main(String[] args) {<br />&nbsp;BufferedReader br = null;<br />&nbsp;try {<br />&nbsp;br = new BufferedReader(new FileReader("languages.txt"));<br />&nbsp;String line = null;<br />&nbsp;while((line = br.readLine()) != null) {<br />&nbsp;System.out.println("I know " + line);<br />&nbsp;}<br />&nbsp;}<br />&nbsp;catch(FileNotFoundException e) {<br />&nbsp;e.printStackTrace();<br />&nbsp;}<br />&nbsp;catch(IOException e) {<br />&nbsp;e.printStackTrace();<br />&nbsp;}<br />&nbsp;finally {<br />&nbsp;if(br != null) {<br />&nbsp;try {<br />&nbsp;br.close();<br />&nbsp;}             <br />catch(IOException e) {<br />&nbsp;e.printStackTrace();<br />&nbsp;}<br />&nbsp;}<br />&nbsp;}<br />&nbsp;}<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 清单 19 展示了 Groovy 中的等效过程： </p> 			<br /><a name="listing19"><strong>清单 19. Groovy 文件迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="74" width="536"><tbody><tr><td><pre>def f = new File("languages.txt") f.eachLine{language-&gt;<br />&nbsp;println "I know ${language}"<br />} </pre></td></tr></tbody></table><br /> 			<p> 这正是 Groovy 的简洁性真正擅长的方面。现在，我希望您了解为什么我将 Groovy 称为 &#8220;<a href="http://www.ibm.com/developerworks/cn/java/j-pg02179.html">Java 程序员的 DSL</a>&#8221;。 </p> 			<p> 注意，我在 Groovy 和 Java 语言中同时处理同一个 <code>java.io.File</code> 类。如果该文件不存在，那么 Groovy 代码将抛出和 Java 代码相同的 <code>FileNotFoundException</code> 异常。区别在于，Groovy 没有已检测的异常。在 <code>try</code>/<code>catch</code>/<code>finally</code> 块中封装 <code>eachLine()</code> 结构是我自己的爱好 &#8212; 而不是一项语言需求。对于一个简单的命令行脚本中，我欣赏 <a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#listing19">清单 19</a> 中的代码的简洁性。如果我在运行应用服务的同时执行相同的迭代，我不能对这些异常坐视不管。我将在与 Java 版本相同的 <code>try/catch</code> 块中封装 <code>eachLine()</code> 块。 </p> 			<p> 				<code>File</code> 类对 <code>each()</code> 方法进行了一些修改。其中之一就是 <code>splitEachLine(String separator, Closure closure)</code>。这意味着您不仅可以逐行遍历文件，同时还可以将它分为不同的标记。清单 20 展示了一个例子： </p> 			<br /><a name="listing20"><strong>清单 20. 分解文件的每一行 </strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="182" width="757"><tbody><tr><td><pre>// languages.txt<br />&nbsp;// notice the space between the language and the version Java 1.5 Groovy 1.6 JavaScript 1.x<br />&nbsp;// splitTest.groovy <br />def f = new File("languages.txt")<br />&nbsp;f.splitEachLine(" "){words-&gt;<br />&nbsp;words.each{ println it<br />&nbsp;}<br />&nbsp;} <br /> // output Java 1.5 Groovy 1.6 JavaScript 1.x </pre></td></tr></tbody></table><br /> 			<p> 如果处理的是二进制文件，Groovy 还提供了一个 <code>eachByte()</code> 方法。 </p> 			<p> 当然，Java 语言中的 <code>File</code> 并不总是一个文件 &#8212; 有时是一个目录。Groovy 还提供了一些 <code>each()</code> 修改以处理子目录。 </p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N1046C">目录迭代</a></p> 			<p> 使用 Groovy 代替 shell 脚本（或批处理脚本）非常容易，因为您能够方便地访问文件系统。要获得当前目录的目录列表，参见清单 21：</p> 			<br /><a name="listing21"><strong>清单 21. 目录迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="74" width="443"><tbody><tr><td><pre>def dir = new File(".") dir.eachFile{file-&gt;<br />&nbsp;println file<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 				<code>eachFile()</code> 方法同时返回了文件和子目录。使用 Java 语言的 <code>isFile()</code> 和 <code>isDirectory()</code> 方法，可以完成更复杂的事情。清单 22 展示了一个例子： </p> 			<br /><a name="listing22"><strong>清单 22. 分离文件和目录</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="182" width="427"><tbody><tr><td><pre>def dir = new File(".") dir.eachFile{file-&gt;<br />&nbsp;if(file.isFile()){<br />&nbsp;println "FILE: ${file}"<br />&nbsp;}else if(file.isDirectory()){<br />&nbsp;println "DIR:  ${file}"<br />&nbsp;}else{<br />&nbsp;println "Uh, I'm not sure what it is..."<br />&nbsp;}<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 由于两种 Java 方法都返回 <code>boolean</code> 值，可以在代码中添加一个 Java 三元操作符。清单 23 展示了一个例子： </p> 			<br /><a name="listing23"><strong>清单 23. 三元操作符</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="92" width="546"><tbody><tr><td><pre>def dir = new File(".")<br />&nbsp;dir.eachFile{file-&gt;<br />&nbsp;println file.isDirectory() ? "DIR:  ${file}" : "FILE: ${file}"<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 如果只对目录有兴趣，那么可以使用 <code>eachDir()</code> 而不是 <code>eachFile()</code>。还提供了 <code>eachDirMatch()</code> 和 <code>eachDirRecurse()</code> 方法。 </p> 			<p> 可以看到，对 <code>File</code> 仅使用 <code>each()</code> 方法并不能提供足够的含义。典型 <code>each()</code> 方法的语义保存在 <code>File</code> 中，但是方法名更具有描述性，从而提供更多有关这个高级功能的信息。 </p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N104CF">URL 迭代</a></p> 			<p> 理解了如何遍历 <code>File</code> 后，可以使用相同的原则遍历 HTTP 请求的响应。Groovy 为 <code>java.net.URL</code> 提供了一个方便的（和熟悉的）<code>eachLine()</code> 方法。 </p> 			<p> 例如，清单 24 将逐行遍历 ibm.com 主页的 HTML： </p> 			<br /><a name="listing24"><strong>清单 24. URL 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="92" width="416"><tbody><tr><td><pre>def url = new URL("http://www.ibm.com")<br />&nbsp;url.eachLine{line-&gt;<br />&nbsp;println line<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 当然，如果这就是您的目的的话，Groovy 提供了一个只包含一行代码的解决办法，这主要归功于 <code>toURL()</code> 方法，它被添加到所有 <code>Strings</code>：<code>"http://www.ibm.com".toURL().eachLine{ println it }</code>。 </p> 			<p> 但是，如果希望对 HTTP 响应执行一些更有用的操作，该怎么办呢？具体来讲，如果发出的请求指向一个 RESTful Web 服务，而该服务包含您要解析的 XML，该怎么做呢？<code>each()</code> 方法将在这种情况下提供帮助。 </p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N10507">XML 迭代</a></p> 			<p> 您已经了解了如何对文件和 URL 使用 <code>eachLine()</code> 方法。XML 给出了一个稍微有些不同的问题 &#8212; 与逐行遍历 XML 文档相比，您可能更希望对逐个元素进行遍历。 </p> 			<p> 例如，假设您的语言列表存储在名为 languages.xml 的文件中，如清单 25 所示： </p> 			<br /><a name="listing25"><strong>清单 25. languages.xml 文件</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="110" width="431"><tbody><tr><td><pre>&lt;langs&gt;<br />&nbsp;&lt;language&gt;Java&lt;/language&gt;<br />&nbsp;&lt;language&gt;Groovy&lt;/language&gt;<br />&nbsp;&lt;language&gt;JavaScript&lt;/language&gt;<br />&nbsp;&lt;/langs&gt; </pre></td></tr></tbody></table><br /> 			<p> Groovy 提供了一个 <code>each()</code> 方法，但是需要做一些修改。如果使用名为 <code>XmlSlurper</code> 的原生 Groovy 类解析 XML，那么可以使用 <code>each()</code> 遍历元素。参见清单 26 所示的例子： </p> 			<br /><a name="listing26"><strong>清单 26. XML 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="110" width="448"><tbody><tr><td><pre>def langs = new XmlSlurper().parse("languages.xml")<br />&nbsp;langs.language.each{<br />&nbsp;println it<br />&nbsp;}<br />&nbsp;//output Java Groovy JavaScript </pre></td></tr></tbody></table><br /> 			<p> 				<code>langs.language.each</code> 语句从名为 <code>&lt;language&gt;</code> 的 <code>&lt;langs&gt;</code> 提取所有元素。如果同时拥有 <code>&lt;format&gt;</code> 和 <code>&lt;server&gt;</code> 元素，它们将不会出现在 <code>each()</code> 方法的输出中。</p> 			<p> 如果觉得这还不够的话，那么假设这个 XML 是通过一个 RESTful Web 服务的形式获得，而不是文件系统中的文件。使用一个 URL 替换文件的路径，其余代码仍然保持不变，如清单 27 所示： </p> 			<br /><a name="listing27"><strong>清单 27. Web 服务调用的 XML 迭代</strong></a><br /><table border="0" cellpadding="0" cellspacing="0" height="92" width="609"><tbody><tr><td><pre>def langs = new XmlSlurper().parse("http://somewhere.com/languages")<br />&nbsp;langs.language.each{<br />&nbsp;println it<br />&nbsp;} </pre></td></tr></tbody></table><br /> 			<p> 这真是个好方法，<code>each()</code> 方法在这里用得很好，不是吗？</p> 			<p ibm-back-to-top=""><a href="http://www.ibm.com/developerworks/cn/java/j-pg04149.html#ibm-pcon"><br /></a></p><p><a name="N1056B">结束语</a></p> 			<p> 在使用 <code>each()</code> 方法的整个过程中，最妙的部分在于它只需要很少的工作就可以处理大量 Groovy 内容。解了 <code>each()</code> 方法之后，Groovy 中的迭代就易如反掌了。正如 Raymond 所说，这正是关键所在。一旦了解了如何遍历 <code>List</code>，那么很快就会掌握如何遍历数组、<code>Map</code>、<code>String</code>、<code>Range</code>、<code>enum</code>、SQL <code>ResultSet</code>、<code>File</code>、目录和 <code>URL</code>，甚至是 XML 文档的元素。 </p> 			<p> 本文的最后一个示例简单提到使用 <code>XmlSlurper</code> 实现 XML 解析。在下一期文章中，我将继续讨论这个问题，并展示使用 Groovy 进行 XML 解析有多么简单！您将看到 <code>XmlParser</code> 和 <code>XmlSlurper</code> 的实际使用，并更好地了解 Groovy 为什么提供两个类似但又略有不同的类实现 XML 解析。到那时，希望您能发现 Groovy 的更多实际应用。 </p></div><img src ="http://www.blogjava.net/ljc-java/aggbug/355737.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ljc-java/" target="_blank">小罗</a> 2011-08-04 11:50 <a href="http://www.blogjava.net/ljc-java/archive/2011/08/04/355737.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>