﻿<?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-JafeLee-文章分类-Java/J2EE</title><link>http://www.blogjava.net/JafeLee/category/22485.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 06 Sep 2007 21:39:32 GMT</lastBuildDate><pubDate>Thu, 06 Sep 2007 21:39:32 GMT</pubDate><ttl>60</ttl><item><title>Java Tech: Using Variable Arguments (zz)</title><link>http://www.blogjava.net/JafeLee/articles/143257.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Thu, 06 Sep 2007 10:47:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/143257.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/143257.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/143257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/143257.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/143257.html</trackback:ping><description><![CDATA[原文地址：<a href="http://today.java.net/pub/a/today/2004/04/19/varargs.html">http://today.java.net/pub/a/today/2004/04/19/varargs.html</a><br /><br /><p>Welcome to Java Tech. This new column explores all kinds of Java technology in
terms of theory and practicality. For example, one article might investigate
Tiger's generics language feature, whereas another article might apply Java to
the construction of a web shopping cart application or a "smart" computer game
that can beat the pants off many game players. I hope you enjoy the adventure.</p><p>Speaking of Tiger (also known as J2SE 5.0), this article focuses on the new variable arguments language
feature. After examining basic syntax, we'll cover diverse uses for variable
arguments.</p><p>Note: This column is based on J2SE 5. Sun has established an external
version number of 5.0 and an internal version number of
1.5.0 to this release of the Java 2 platform.</p><h2 id="Basic_Syntax_and_Uses">Basic Syntax and Uses</h2><p>Tiger's variable arguments language feature makes it possible to call a method
with a variable number of arguments. Before making that call, the rightmost
parameter in the method's parameter list must conform to the following syntax:</p><pre><code><i>type</i> ... <i>variableName</i></code></pre><p>The ellipsis (<code>...</code>) identifies a variable number of arguments, and
is demonstrated in the following summation method.</p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> sum (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /> numbers)<br />{<br />   </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> total </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />   </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; i </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> numbers.length; i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br />        total </span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);"> numbers [i];<br />   </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> total;<br />}<br /><br /></span></div><p>Call the summation method with as many comma-delimited integer arguments as
you desire -- within the JVM's limits. Some examples: <code>sum (10, 20)</code> and
<code>sum (18, 20, 305, 4)</code>.</p><p>Look closely at the method declaration above, and you'll discover that variable
arguments is implemented in terms of arrays. (<code>numbers.length</code> and
<code>numbers [i]</code> are the giveaways.) It turns out that the ellipsis is
just syntactic sugar for having the compiler create and initialize an array of
same-typed values and pass that array's reference to a method. For example,
the compiler converts the method call <code>sum (10, 20)</code> into an equivalent
<code>sum (new int [] {10, 20})</code> method call.</p><p>Can you change <code>int ... numbers</code> to <code>int [] numbers</code> and
still invoke <code>sum (10, 20)</code>? Answer: no. If you try to do that, the
compiler reports an error. Use <code>sum (new int [] {10, 20})</code> instead.</p><p>Summing a list of integers is one basic use for variable arguments. Computing
the average of a list of floating-point numbers, concatenating a list of
strings into a single string, and finding the maximum/minimum values in lists
of floating-point numbers are other basic uses. The following 
<code>BasicUses.java</code> source code demonstrates these basic uses, to give
you more exposure to variable arguments.</p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><img id="Code_Closed_Image_184617" onclick="this.style.display='none'; Code_Closed_Text_184617.style.display='none'; Code_Open_Image_184617.style.display='inline'; Code_Open_Text_184617.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" height="16" width="11" /><img id="Code_Open_Image_184617" style="display: none;" onclick="this.style.display='none'; Code_Open_Text_184617.style.display='none'; Code_Closed_Image_184617.style.display='inline'; Code_Closed_Text_184617.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" height="16" width="11" /><span id="Code_Closed_Text_184617" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255);">BasicUses.java</span><span id="Code_Open_Text_184617" style="display: none;"><br /><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> BasicUses.java</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> BasicUses<br />{<br />   </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> main (String [] args)<br />   {<br />      System.out.println (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Average: </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                          avg (</span><span style="color: rgb(0, 0, 0);">20.3</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">3.1415</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">32.3</span><span style="color: rgb(0, 0, 0);">));<br />      System.out.println (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Concatenation: </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                          concat (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Hello</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">World</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">));<br />      System.out.println (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Maximum: </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                          max (</span><span style="color: rgb(0, 0, 0);">30</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">22.3</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">9.3</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">173.2</span><span style="color: rgb(0, 0, 0);">));<br />      System.out.println (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Minimum: </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                          min (</span><span style="color: rgb(0, 0, 0);">30</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">22.3</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">9.3</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">173.2</span><span style="color: rgb(0, 0, 0);">));<br />      System.out.println (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Sum: </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                          sum (</span><span style="color: rgb(0, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">30</span><span style="color: rgb(0, 0, 0);">));<br />   }<br />   </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> avg (</span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /> numbers)<br />   {<br />      </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> total </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />      </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; i </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> numbers.length; i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br />           total </span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);"> numbers [i];<br />      </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> total </span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);"> numbers.length;<br />   }<br />   </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> String concat (String <img src="http://www.blogjava.net/images/dot.gif" /> strings)<br />   {<br />      StringBuilder sb </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> StringBuilder ();<br />      </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; i </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> strings.length; i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br />           sb.append (strings [i]);<br />      </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> sb.toString ();<br />   }<br />   </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> max (</span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /> numbers)<br />   {<br />      </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> maximum </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Double.MIN_VALUE;<br />      </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; i </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> numbers.length; i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br />           </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (numbers [i] </span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> maximum)<br />               maximum </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> numbers [i];<br />      </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> maximum;<br />   }<br />   </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> min (</span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /> numbers)<br />   {<br />      </span><span style="color: rgb(0, 0, 255);">double</span><span style="color: rgb(0, 0, 0);"> minimum </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Double.MAX_VALUE;<br />      </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; i </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> numbers.length; i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br />           </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (numbers [i] </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> minimum)<br />               minimum </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> numbers [i];<br />      </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> minimum;<br />   }<br />   </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> sum (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> <img src="http://www.blogjava.net/images/dot.gif" /> numbers)<br />   {<br />      </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> total </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;<br />      </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);"> (</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">; i </span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);"> numbers.length; i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">)<br />           total </span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);"> numbers [i];<br />      </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> total;<br />   }<br />}<br /><br /></span></span></div><p>Look closely at <code>BasicUses.java</code> and you'll discover a second Tiger
innovation: <code>java.lang.StringBuilder</code>. I use that class, instead of
<code>java.lang.StringBuffer</code>, in the concatenation method because
<code>StringBuilder</code>'s lack of synchronization offers better performance
than <code>StringBuffer</code>. (Why call a synchronized method and obtain the
resulting performance hit, no matter how small, when it's not necessary?)</p><h2 id="Tiger_Uses_Variable_Arguments">Tiger Uses Variable Arguments</h2><p>As you've just seen, variable arguments are useful in simple methods. But they
are even more useful in the Tiger SDK. That SDK uses variable arguments in the 
areas of reflection, process building, and formatting (and probably other areas that I have yet to discover.)</p><h5 id="Reflection">Reflection</h5><p><code>java.lang.Class</code> and a few <code>java.lang.reflect</code> classes
(such as <code>Method</code> and <code>Constructor</code>) reveal methods that
employ the new <code>...</code> variable arguments syntax. Examples include
<code>Class</code>'s <code>public Method getMethod(String name, Class ...
parameterTypes)</code> and <code>Method</code>'s <code>public Object
invoke(Object obj, Object ... args)</code>. Those methods are callable, either
in the traditional manner or in the new variable arguments manner. Consider an
example where a classfile represents the class below:</p><pre><code></code><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> SomeClass<br />{<br />   </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> someMethod (String strArg, </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> intArg)<br />   {<br />      System.out.println (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">strArg = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> strArg);<br />      System.out.println (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">intArg = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> intArg);<br />   }<br />}<br /><br /></span></div>Now suppose you want to dynamically load the <code>SomeClass</code> classfile
and reflectively invoke its solitary method. That task can be accomplished, in
the traditional manner, with the code fragment below:</pre><pre><code><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Class [] argTypes </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"><br />{<br />   String.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">,<br />   </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"><br />};<br /><br /></span><span style="color: rgb(0, 128, 0);">/*</span><span style="color: rgb(0, 128, 0);"> Note: Java 1.5's autoboxing language feature lets <br />  you replace "new Integer (20)" with "20". The<br />  compiler converts "20" to "new Integer (20)".<br />  This code fragment assumes an earlier version<br />  of Java -- which is why "new Integer (20)" is <br />  specified instead of "20".<br /></span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />Object [] methodData </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"><br />{<br />   </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">A</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,<br />   </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Integer (</span><span style="color: rgb(0, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">) <br />}; <br />Class c </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Class.forName (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">SomeClass</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />Method m </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> c.getMethod (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">someMethod</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, argTypes);<br />m.invoke (c.newInstance (), methodData);</span></div></code>In contrast, variable arguments let you express the code fragment above more
compactly, as follows:<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Class c </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Class.forName (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">SomeClass</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />Method m </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> c.getMethod (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">someMethod</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, String.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);">.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">);<br />m.invoke (c.newInstance (), </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">A</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">);</span></div>You save keystrokes and the code is much easier to read.</pre><h5 id="Process_Building">Process Building</h5><p>The new <code>java.lang.ProcessBuilder</code> class makes it possible to build
operating system processes and manage a collection of process attributes (the
command, an environment, a working directory, and whether or not the error
stream is redirected). One of that class's constructors and the <code>public
ProcessBuilder command(String ... command)</code> method use the new variable
arguments syntax to simplify the specification of a command for execution and
its arguments. For example, to execute Windows' <code>notepad</code> program,
and have that program load the <i>autoexec.bat</i> batch file from the
root directory (on the current drive), specify the code fragment below:</p><pre><code><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Process p </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ProcessBuilder (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">notepad</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\\autoexec.bat</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">).start ();</span></div></code><br />The constructor specifies the command to execute, along with a variable number
of arguments to pass to the command. The <code>start()</code> method call
starts the command executing and returns a <code>java.lang.Process</code>
reference for retrieving process-exit status (in addition to other tasks).</pre><p>Without variable arguments, you would probably specify the above code fragment 
in the following manner:</p><pre><code><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">String [] commandAndArgs </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"><br />{<br />   </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">notepad</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,<br />   </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\\autoexec.bat</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />};<br />Process p </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ProcessBuilder (commandAndArgs).start ();</span></div></code>Once again, variable arguments makes the code easier to read.</pre><h5 id="Formatting">Formatting</h5><p>Possibly the major reason for including variable arguments (and autoboxing) in
Tiger is the new <code>java.util.Formatter</code> class. In combination with
its <code>java.lang.Appendable</code> helper interface, <code>Formatter</code>
formats data values of arbitrary data types and outputs the formatted results
to arbitrary destinations.</p><p>Unless your application has specialized needs, you won't need to work directly
with <code>Formatter</code> and <code>Appendable</code>. Instead, you'll work
with one of the <code>format</code> methods found in the following classes:
<code>java.io.PrintStream</code>, <code>java.io.PrintWriter</code>, and 
<code>java.lang.String</code>. Behind the scenes, those classes work with the
<code>Formatter</code> class (and sometimes with <code>Appendable</code>, too).</p><p><code>PrintStream</code>, <code>PrintWriter</code>, and <code>String</code>
each present two <code>format</code> methods. One method takes a
<code>java.util.Locale</code> argument, where the other method does not. The
return types vary, as well. <code>PrintStream</code>'s <code>format</code>
methods return <code>PrintStream</code> references, <code>PrintWriter</code>'s
<code>format</code> methods return <code>PrintWriter</code> references, and
<code>String</code>'s <code>format</code> methods return <code>String</code>
references. And finally, <code>String</code>'s <code>format</code> methods are
static methods, whereas the <code>format</code> methods in the other two
classes are instance methods. The following code fragment demonstrates two of these
<code>format</code> methods:</p><pre><code><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">String s </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> String.format (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%.2f</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">1.256</span><span style="color: rgb(0, 0, 0);">);<br />System.out.format (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%05d</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">1234</span><span style="color: rgb(0, 0, 0);">);</span></div></code><code>String</code>'s locale-less <code>format</code> method reveals a pattern
argument, consisting of <code>%.2f</code> ("format a floating-point value such
that there are exactly two digits after the decimal point, and employ rounding
if necessary"), followed by the floating-point value to format:
<code>1.256</code>. The formatted result -- <code>1.26</code> -- returns as a 
<code>String</code>, whose reference assigns to <code>s</code>.</pre><p>Similarly, <code>PrintStream</code>'s locale-less <code>format</code> method
takes a pattern followed by a single value. However, the <code>%05d</code>
pattern states that an integer is to be formatted to a minimum of five digits. If
there are not enough digits, leading zeroes display to the left of the non-zero
digits. Instead of returning the result -- <code>01234</code> -- for storage,
<code>PrintStream</code>'s <code>format</code> outputs <code>01234</code> to a
stream (the standard output stream, in this case).</p><p>Note: <code>java.text.MessageFormat</code> also reveals a <code>format</code>
method with a variable number of arguments. Unlike the previously discussed
<code>format</code> methods, this <code>format</code> method is not a wrapper
for <code>Formatter</code>.</p><h2 id="Cstyle_printf_and_scanf">C-style <code>printf()</code> and <code>scanf()</code></h2><p>Coming from a C background, I equate variable arguments with what are probably
the most popular functions in C's standard library: <code>printf()</code> and
<code>scanf()</code>. (It's a bit silly, but either function pops into my mind
when someone mentions variable arguments.) For the uninitiated, C developers
create formatted output by calling <code>printf()</code>, and obtain formatted
input by calling <code>scanf()</code>.</p><p>My fondness for those functions resulted in considerable pleasure when I found
a pair of <code>printf</code> methods in each of the <code>PrintStream</code>
and <code>PrintWriter</code> classes. It doesn't matter that they exist as
convenience methods delegating to equivalent <code>format</code> methods. It's
still nice to have official Java versions of <code>printf()</code>.</p><p>Official versions of <code>scanf()</code> don't exist: <code>scanf()</code>
relies upon pointers, which Java doesn't support. However, Tiger introduces a
new <code>java.util.Scanner</code> class that makes up for the lack of
<code>scanf()</code>. This class lets you create a simple regular expression-
oriented text scanner, for scanning primitive types and strings from an input
source.</p><p>The following <code>FormattedIO.java</code> source code demonstrates one of the
<code>printf</code> methods and <code>Scanner</code> performing the equivalent
of some commented-out C code.</p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><img id="Code_Closed_Image_184716" onclick="this.style.display='none'; Code_Closed_Text_184716.style.display='none'; Code_Open_Image_184716.style.display='inline'; Code_Open_Text_184716.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" height="16" width="11" /><img id="Code_Open_Image_184716" style="display: none;" onclick="this.style.display='none'; Code_Open_Text_184716.style.display='none'; Code_Closed_Image_184716.style.display='inline'; Code_Closed_Text_184716.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" height="16" width="11" /><span id="Code_Closed_Text_184716" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255);">FormattedIO.java</span><span id="Code_Open_Text_184716" style="display: none;"><br /><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> FormattedIO.java</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.Scanner;<br /></span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> FormattedIO<br />{<br />   </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> main (String [] args)<br />   {<br />      </span><span style="color: rgb(0, 128, 0);">/*</span><span style="color: rgb(0, 128, 0);"><br />         // Execute the equivalent of the following<br />         // C code fragment.<br />         int i;<br />         float f;<br />         char s [50];<br />         printf ("Enter three values -- integer float string: ");<br />         scanf ("%d %f %s", &amp;i, &amp;f, s);<br />         printf ("%d %f %s\n", i, f, s);<br />      </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />      System.out.printf (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Enter three values -- </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                        integer </span><span style="color: rgb(0, 0, 255);">float</span><span style="color: rgb(0, 0, 0);"> string: </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">      Scanner sc </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Scanner (System.in);<br />      </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sc.nextInt ();<br />      </span><span style="color: rgb(0, 0, 255);">float</span><span style="color: rgb(0, 0, 0);"> f </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sc.nextFloat ();<br />      String s </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sc.nextLine ();<br />      System.out.printf (</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">%d %f %s\n</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, i, f, s);<br />   }<br />}<br /><br /></span></span></div><p>After prompting the user to enter three values, <code>FormattedIO</code>
creates a scanner that scans characters from standard input. The program next
calls the methods <code>nextInt()</code>, <code>nextFloat()</code>, and
<code>nextString()</code> to extract an integer, followed by a floating-point
value, followed by a string of characters -- up to, but not including the line
terminator -- from the standard input stream. Finally,
<code>System.out.printf ("%d %f %s\n", i, f, s);</code> formats those values
into a sequence of characters that it sends to the standard output.</p><h2 id="Conclusion">Conclusion</h2><p>Variable arguments are a subtle but quite useful feature in Tiger's arsenal of 
new language features. Uses range from simple methods to reflection, process
building, and formatting. Perhaps the versatility of variable arguments comes
out best in the new <code>printf</code> methods. Although <code>scanf</code>
methods that use variable arguments (in the C sense) are not possible, Tiger's
inclusion of a <code>Scanner</code> class makes up for that deficiency.</p><p>You really didn't think I'd let you get away without doing some homework, did
you? I have a couple of exercises for you to work on. Answers will appear next
month:</p><ol><li><p>Is <code>void foo (String ... args, int x) { }</code> legal Java code? Why
or why not?</p></li><li><p>Create a <code>PrintFDemo</code> application that demonstrates many of the
formatting options made available by <code>Formatter</code>.</p></li></ol><p>Next month, Java Tech enters the realm of zero sum perfect information games,
such as chess.</p><p><em><a href="http://today.java.net/pub/au/174">Jeff Friesen</a> is a freelance software developer and educator specializing in Java technology.  Check out his  site at <a href="http://javajeff.mb.ca/">javajeff.mb.ca</a>.</em></p><img src="http://today.java.net/im/a.gif" alt=" " border="0" height="1" width="1" /><br /><img src ="http://www.blogjava.net/JafeLee/aggbug/143257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-09-06 18:47 <a href="http://www.blogjava.net/JafeLee/articles/143257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASCII码字符表 (转载）</title><link>http://www.blogjava.net/JafeLee/articles/139642.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Sun, 26 Aug 2007 14:20:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/139642.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/139642.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/139642.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/139642.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/139642.html</trackback:ping><description><![CDATA[
		<p>
				<font color="red" size="16">
						<b>
								<font size="3">原文连接：<a href="http://www.zzslxx.com/ldf/asc.htm">http://www.zzslxx.com/ldf/asc.htm</a></font>
								<br />
						</b>
				</font>
		</p>
		<p align="center">
				<font color="red" size="16">
						<b>ASCII码字符表</b>
				</font>
		</p>
		<table id="table1" style="text-align: center;" border="4" bordercolor="#c0c0c0" cellpadding="4" cellspacing="0">
				<tbody>
						<tr>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">10进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">16进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff" nowrap="nowrap">
										<b>
												<font color="red">控制字符</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">10进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">16进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">字符</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">10进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">16进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">字符</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">10进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">16进制</font>
										</b>
								</td>
								<td bgcolor="#00ffff">
										<b>
												<font color="red">字符</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>0</td>
								<td>00</td>
								<td width="63">NUL</td>
								<td bgcolor="green">32</td>
								<td bgcolor="green">20</td>
								<td bgcolor="green">空格</td>
								<td>64</td>
								<td>40</td>
								<td>@</td>
								<td bgcolor="green">96</td>
								<td bgcolor="green">60</td>
								<td bgcolor="green">`</td>
						</tr>
						<tr>
								<td>1</td>
								<td>01</td>
								<td width="63">
										<font face="Wingdings">J</font>
								</td>
								<td bgcolor="green">33</td>
								<td bgcolor="green">21</td>
								<td bgcolor="green">!</td>
								<td>65</td>
								<td>41</td>
								<td>
										<b>
												<font color="red">A </font>
										</b>
								</td>
								<td bgcolor="green">97</td>
								<td bgcolor="green">61</td>
								<td bgcolor="green">
										<b>
												<font color="red">a</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>2</td>
								<td>02</td>
								<td width="63">　</td>
								<td bgcolor="green">34</td>
								<td bgcolor="green">22</td>
								<td bgcolor="green">"</td>
								<td>66</td>
								<td>42</td>
								<td>
										<b>
												<font color="red">B </font>
										</b>
								</td>
								<td bgcolor="green">98</td>
								<td bgcolor="green">62</td>
								<td bgcolor="green">
										<b>
												<font color="red">b</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>3</td>
								<td>03</td>
								<td width="63">
										<span lang="en">
												<font face="Symbol">©</font>
										</span>
								</td>
								<td bgcolor="green">35</td>
								<td bgcolor="green">23</td>
								<td bgcolor="green">#</td>
								<td>67</td>
								<td>43</td>
								<td>
										<b>
												<font color="red">C </font>
										</b>
								</td>
								<td bgcolor="green">99</td>
								<td bgcolor="green">63</td>
								<td bgcolor="green">
										<b>
												<font color="red">c</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>4</td>
								<td>04</td>
								<td width="63">
										<span lang="en">
												<font face="Symbol">¨</font>
										</span>
								</td>
								<td bgcolor="green">36</td>
								<td bgcolor="green">24</td>
								<td bgcolor="green">$</td>
								<td>68</td>
								<td>44</td>
								<td>
										<b>
												<font color="red">D </font>
										</b>
								</td>
								<td bgcolor="green">100</td>
								<td bgcolor="green">64</td>
								<td bgcolor="green">
										<b>
												<font color="red">d</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>5</td>
								<td>05</td>
								<td width="63">
										<span lang="en">
												<font face="Symbol">§</font>
										</span>
								</td>
								<td bgcolor="green">37</td>
								<td bgcolor="green">25</td>
								<td bgcolor="green">%</td>
								<td>69</td>
								<td>45</td>
								<td>
										<b>
												<font color="red">E </font>
										</b>
								</td>
								<td bgcolor="green">101</td>
								<td bgcolor="green">65</td>
								<td bgcolor="green">
										<b>
												<font color="red">e</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>6</td>
								<td>06</td>
								<td width="63">
										<span lang="en">
												<font face="Symbol">ª</font>
										</span>
								</td>
								<td bgcolor="green">38</td>
								<td bgcolor="green">26</td>
								<td bgcolor="green">&amp;</td>
								<td>70</td>
								<td>46</td>
								<td>
										<b>
												<font color="red">F </font>
										</b>
								</td>
								<td bgcolor="green">102</td>
								<td bgcolor="green">66</td>
								<td bgcolor="green">
										<b>
												<font color="red">f</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>7</td>
								<td>07</td>
								<td width="63">Beep</td>
								<td bgcolor="green">39</td>
								<td bgcolor="green">27</td>
								<td bgcolor="green">'</td>
								<td>71</td>
								<td>47</td>
								<td>
										<b>
												<font color="red">G </font>
										</b>
								</td>
								<td bgcolor="green">103</td>
								<td bgcolor="green">67</td>
								<td bgcolor="green">
										<b>
												<font color="red">g</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>8</td>
								<td>08</td>
								<td width="63">
										<font size="2">BackSpace</font>
								</td>
								<td bgcolor="green">40</td>
								<td bgcolor="green">28</td>
								<td bgcolor="green">(</td>
								<td>72</td>
								<td>48</td>
								<td>
										<b>
												<font color="red">H </font>
										</b>
								</td>
								<td bgcolor="green">104</td>
								<td bgcolor="green">68</td>
								<td bgcolor="green">
										<b>
												<font color="red">h</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>9</td>
								<td>09</td>
								<td width="63">Tab</td>
								<td bgcolor="green">41</td>
								<td bgcolor="green">29</td>
								<td bgcolor="green">)</td>
								<td>73</td>
								<td>49</td>
								<td>
										<b>
												<font color="red">I </font>
										</b>
								</td>
								<td bgcolor="green">105</td>
								<td bgcolor="green">69</td>
								<td bgcolor="green">
										<b>
												<font color="red">i</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>10</td>
								<td>0A</td>
								<td width="63">换行</td>
								<td bgcolor="green">42</td>
								<td bgcolor="green">2A</td>
								<td bgcolor="green">*</td>
								<td>74</td>
								<td>4A</td>
								<td>
										<b>
												<font color="red">J </font>
										</b>
								</td>
								<td bgcolor="green">106</td>
								<td bgcolor="green">6A</td>
								<td bgcolor="green">
										<b>
												<font color="red">j</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>11</td>
								<td>0B</td>
								<td width="63">　</td>
								<td bgcolor="green">43</td>
								<td bgcolor="green">2B</td>
								<td bgcolor="green">+</td>
								<td>75</td>
								<td>4B</td>
								<td>
										<b>
												<font color="red">K </font>
										</b>
								</td>
								<td bgcolor="green">107</td>
								<td bgcolor="green">6B</td>
								<td bgcolor="green">
										<b>
												<font color="red">k</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>12</td>
								<td>0C</td>
								<td width="63">　</td>
								<td bgcolor="green">44</td>
								<td bgcolor="green">2C</td>
								<td bgcolor="green">,</td>
								<td>76</td>
								<td>4C</td>
								<td>
										<b>
												<font color="red">L </font>
										</b>
								</td>
								<td bgcolor="green">108</td>
								<td bgcolor="green">6C</td>
								<td bgcolor="green">
										<b>
												<font color="red">l</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>13</td>
								<td>0D</td>
								<td width="63">回车</td>
								<td bgcolor="green">45</td>
								<td bgcolor="green">2D</td>
								<td bgcolor="green">-</td>
								<td>77</td>
								<td>4D</td>
								<td>
										<b>
												<font color="red">M </font>
										</b>
								</td>
								<td bgcolor="green">109</td>
								<td bgcolor="green">6D</td>
								<td bgcolor="green">
										<b>
												<font color="red">m</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>14</td>
								<td>0E</td>
								<td width="63">&#xE;</td>
								<td bgcolor="green">46</td>
								<td bgcolor="green">2E</td>
								<td bgcolor="green">.</td>
								<td>78</td>
								<td>4E</td>
								<td>
										<b>
												<font color="red">N </font>
										</b>
								</td>
								<td bgcolor="green">110</td>
								<td bgcolor="green">6E</td>
								<td bgcolor="green">
										<b>
												<font color="red">n</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>15</td>
								<td>0F</td>
								<td width="63">&#xF;</td>
								<td bgcolor="green">47</td>
								<td bgcolor="green">2F</td>
								<td bgcolor="green">/</td>
								<td>79</td>
								<td>4F</td>
								<td>
										<b>
												<font color="red">O </font>
										</b>
								</td>
								<td bgcolor="green">111</td>
								<td bgcolor="green">6F</td>
								<td bgcolor="green">
										<b>
												<font color="red">o</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>16</td>
								<td>10</td>
								<td width="63">
										<font face="Wingdings 3">}</font>
								</td>
								<td bgcolor="green">48</td>
								<td bgcolor="green">30</td>
								<td bgcolor="green">
										<b>
												<font color="red">0 </font>
										</b>
								</td>
								<td>80</td>
								<td>50</td>
								<td>
										<b>
												<font color="red">P </font>
										</b>
								</td>
								<td bgcolor="green">112</td>
								<td bgcolor="green">70</td>
								<td bgcolor="green">
										<b>
												<font color="red">p</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>17</td>
								<td>11</td>
								<td width="63">&#x11;</td>
								<td bgcolor="green">49</td>
								<td bgcolor="green">31</td>
								<td bgcolor="green">
										<b>
												<font color="red">1 </font>
										</b>
								</td>
								<td>81</td>
								<td>51</td>
								<td>
										<b>
												<font color="red">Q </font>
										</b>
								</td>
								<td bgcolor="green">113</td>
								<td bgcolor="green">71</td>
								<td bgcolor="green">
										<b>
												<font color="red">q</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>18</td>
								<td>12</td>
								<td width="63">&#x12;</td>
								<td bgcolor="green">50</td>
								<td bgcolor="green">32</td>
								<td bgcolor="green">
										<b>
												<font color="red">2 </font>
										</b>
								</td>
								<td>82</td>
								<td>52</td>
								<td>
										<b>
												<font color="red">R </font>
										</b>
								</td>
								<td bgcolor="green">114</td>
								<td bgcolor="green">72</td>
								<td bgcolor="green">
										<b>
												<font color="red">r</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>19</td>
								<td>13</td>
								<td width="63">&#x13;</td>
								<td bgcolor="green">51</td>
								<td bgcolor="green">33</td>
								<td bgcolor="green">
										<b>
												<font color="red">3 </font>
										</b>
								</td>
								<td>83</td>
								<td>53</td>
								<td>
										<b>
												<font color="red">S </font>
										</b>
								</td>
								<td bgcolor="green">115</td>
								<td bgcolor="green">73</td>
								<td bgcolor="green">
										<b>
												<font color="red">s</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>20</td>
								<td>14</td>
								<td width="63">&#x14;</td>
								<td bgcolor="green">52</td>
								<td bgcolor="green">34</td>
								<td bgcolor="green">
										<b>
												<font color="red">4 </font>
										</b>
								</td>
								<td>84</td>
								<td>54</td>
								<td>
										<b>
												<font color="red">T </font>
										</b>
								</td>
								<td bgcolor="green">116</td>
								<td bgcolor="green">74</td>
								<td bgcolor="green">
										<b>
												<font color="red">t</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>21</td>
								<td>15</td>
								<td width="63">
										<span lang="en">
												<font face="Batang">§</font>
										</span>
								</td>
								<td bgcolor="green">53</td>
								<td bgcolor="green">35</td>
								<td bgcolor="green">
										<b>
												<font color="red">5 </font>
										</b>
								</td>
								<td>85</td>
								<td>55</td>
								<td>
										<b>
												<font color="red">U </font>
										</b>
								</td>
								<td bgcolor="green">117</td>
								<td bgcolor="green">75</td>
								<td bgcolor="green">
										<b>
												<font color="red">u</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>22</td>
								<td>16</td>
								<td width="63">　</td>
								<td bgcolor="green">54</td>
								<td bgcolor="green">36</td>
								<td bgcolor="green">
										<b>
												<font color="red">6 </font>
										</b>
								</td>
								<td>86</td>
								<td>56</td>
								<td>
										<b>
												<font color="red">V </font>
										</b>
								</td>
								<td bgcolor="green">118</td>
								<td bgcolor="green">76</td>
								<td bgcolor="green">
										<b>
												<font color="red">v</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>23</td>
								<td>17</td>
								<td width="63">　</td>
								<td bgcolor="green">55</td>
								<td bgcolor="green">37</td>
								<td bgcolor="green">
										<b>
												<font color="red">7 </font>
										</b>
								</td>
								<td>87</td>
								<td>57</td>
								<td>
										<b>
												<font color="red">W </font>
										</b>
								</td>
								<td bgcolor="green">119</td>
								<td bgcolor="green">77</td>
								<td bgcolor="green">
										<b>
												<font color="red">w</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>24</td>
								<td>18</td>
								<td width="63">
										<font face="Wingdings 3">#</font>
								</td>
								<td bgcolor="green">56</td>
								<td bgcolor="green">38</td>
								<td bgcolor="green">
										<b>
												<font color="red">8 </font>
										</b>
								</td>
								<td>88</td>
								<td>58</td>
								<td>
										<b>
												<font color="red">X </font>
										</b>
								</td>
								<td bgcolor="green">120</td>
								<td bgcolor="green">78</td>
								<td bgcolor="green">
										<b>
												<font color="red">x</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>25</td>
								<td>19</td>
								<td width="63">
										<font face="Wingdings 3">$</font>
								</td>
								<td bgcolor="green">57</td>
								<td bgcolor="green">39</td>
								<td bgcolor="green">
										<b>
												<font color="red">9 </font>
										</b>
								</td>
								<td>89</td>
								<td>59</td>
								<td>
										<b>
												<font color="red">Y </font>
										</b>
								</td>
								<td bgcolor="green">121</td>
								<td bgcolor="green">79</td>
								<td bgcolor="green">
										<b>
												<font color="red">y</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>26</td>
								<td>1A</td>
								<td width="63">&#x1A;</td>
								<td bgcolor="green">58</td>
								<td bgcolor="green">3A</td>
								<td bgcolor="green">:</td>
								<td>90</td>
								<td>5A</td>
								<td>
										<b>
												<font color="red">Z </font>
										</b>
								</td>
								<td bgcolor="green">122</td>
								<td bgcolor="green">7A</td>
								<td bgcolor="green">
										<b>
												<font color="red">z</font>
										</b>
								</td>
						</tr>
						<tr>
								<td>27</td>
								<td>1B</td>
								<td width="63">&#x1B;</td>
								<td bgcolor="green">59</td>
								<td bgcolor="green">3B</td>
								<td bgcolor="green">;</td>
								<td>91</td>
								<td>5B</td>
								<td>[</td>
								<td bgcolor="green">123</td>
								<td bgcolor="green">7B</td>
								<td bgcolor="green">{</td>
						</tr>
						<tr>
								<td>28</td>
								<td>1C</td>
								<td width="63">
										<span lang="en">
												<font face="Symbol">ë</font>
										</span>
								</td>
								<td bgcolor="green">60</td>
								<td bgcolor="green">3C</td>
								<td bgcolor="green">&lt;</td>
								<td>92</td>
								<td>5C</td>
								<td>\</td>
								<td bgcolor="green">124</td>
								<td bgcolor="green">7C</td>
								<td bgcolor="green">|</td>
						</tr>
						<tr>
								<td>29</td>
								<td>1D</td>
								<td width="63">
										<span lang="en">
												<font face="Wingdings 2">¿</font>
										</span>
								</td>
								<td bgcolor="green">61</td>
								<td bgcolor="green">3D</td>
								<td bgcolor="green">=</td>
								<td>93</td>
								<td>5D</td>
								<td>]</td>
								<td bgcolor="green">125</td>
								<td bgcolor="green">7D</td>
								<td bgcolor="green">}</td>
						</tr>
						<tr>
								<td>30</td>
								<td>1E</td>
								<td width="63">
										<span lang="en">
												<font face="Wingdings 3">?</font>
										</span>
								</td>
								<td bgcolor="green">62</td>
								<td bgcolor="green">3E</td>
								<td bgcolor="green">&gt;</td>
								<td>94</td>
								<td>5E</td>
								<td>^</td>
								<td bgcolor="green">126</td>
								<td bgcolor="green">7E</td>
								<td bgcolor="green">~</td>
						</tr>
						<tr>
								<td>31</td>
								<td>1F</td>
								<td width="63">
										<span lang="en">
												<font face="Wingdings 3">?</font>
										</span>
								</td>
								<td bgcolor="green">63</td>
								<td bgcolor="green">3F</td>
								<td bgcolor="green">?</td>
								<td>95</td>
								<td>5F</td>
								<td>_</td>
								<td bgcolor="green">127</td>
								<td bgcolor="green">7F</td>
								<td bgcolor="green"></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/JafeLee/aggbug/139642.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-08-26 22:20 <a href="http://www.blogjava.net/JafeLee/articles/139642.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中文乱码解决方案和经验(转载）</title><link>http://www.blogjava.net/JafeLee/articles/133740.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Wed, 01 Aug 2007 01:52:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/133740.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/133740.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/133740.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/133740.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/133740.html</trackback:ping><description><![CDATA[
		<strong>原文链接：不详<br /><br />1.字节和unicode </strong>
		<br />java内核是unicode的，就连class文件也是，但是很多媒体，包括文
件/流的保存方式是使用字节流的。因此java要对这些字节流经行转化。char是unicode的，而byte是字节。java中byte/char互
转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度，可以用来告诉你，你用的convertor。其中两个很常用
的静态函数是 <br /><code>public static ByteToCharConverter getDefault(); <br />public static ByteToCharConverter getConverter(String encoding); <br /></code>如果你不指定converter，则系统会自动使用当前的encoding,gb平台上用gbk,en平台上用8859_1。 <br />byte ——〉char： <br />"你"的gb码是：0xc4e3 ,unicode是0x4f60 <br /><code>String encoding = "gb2312"; <br />byte b[] = {(byte)'\u00c4',(byte)'\u00e3'}; <br />ByteToCharConverter converter = ByteToCharConverter.getConverter(encoding); <br />char c[] = converter.convertAll(b); <br />for (int i = 0; i &lt; c.length; i++) { <br />System.out.println(Integer.toHexString(c[i])); <br />} <br /></code>结果是什么？0x4f60 <br />如果encoding ="8859_1"，结果又是什么？0x00c4,0x00e3 <br />如果代码改为 <br /><code>byte b[] = {(byte)'\u00c4',(byte)'\u00e3'}; <br />ByteToCharConverter converter = ByteToCharConverter. getDefault(); <br />char c[] = converter.convertAll(b); <br />for (int i = 0; i &lt; c.length; i++) { <br />System.out.println(Integer.toHexString(c[i])); <br />} <br /></code>结果将又是什么？根据平台的编码而定。 <br /><br /><code>char ——〉byte： <br />String encoding = "gb2312"; <br />char c[] = {'\u4f60'}; <br />CharToByteConverter converter = CharToByteConverter.getConverter(encoding); <br />byte b[] = converter.convertAll(c); <br />for (int i = 0; i &lt; b.length; i++) { <br />System.out.println(Integer.toHexString(b[i])); <br />} <br /></code>结果是什么？0x00c4,0x00e3 <br />如果encoding ="8859_1"，结果又是什么？0x3f <br />如果代码改为 <br /><code>String encoding = "gb2312"; <br />char c[] = {'\u4f60'}; <br />CharToByteConverter converter = CharToByteConverter.getDefault(); <br />byte b[] = converter.convertAll(c); <br />for (int i = 0; i &lt; b.length; i++) { <br />System.out.println(Integer.toHexString(b[i])); <br />} <br /></code>结果将又是什么？根据平台的编码而定。 <br />很多中文问题就是从这两个最简单的类派生出来的。而却有很多类不直接支持把encoding输入，这给我们带来诸多不便。很多程序难得用encoding了，直接用default的encoding，这就给我们移植带来了很多困难。 <br /><br /><strong>2.utf-8 </strong><br />utf-8是和unicode一一对应的，其实现很简单 <br />7位的unicode: 0 _ _ _ _ _ _ _ <br />11位的unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />16位的unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />21位的unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />大多数情况是只使用到16位以下的unicode: <br />"你"的gb码是：0xc4e3 ,unicode是0x4f60 <br />0xc4e3的二进制： <br />1100 ，0100 ，1110 ，0011 <br />由于只有两位我们按照两位的编码来排，但是我们发现这行不通，因为第７位不是0因此，返回"?" <br />0x4f60的二进制： <br />0100 ，1111 ，0110 ，0000 <br />我们用utf-8补齐，变成： <br />1110 ，0100 ，1011 ，1101 ，1010 ，0000 <br />e4--bd-- a0 <br />于是返回：0xe4,0xbd,0xa0。 <br /><br /><strong>3.string和byte[] </strong><br />string其实核心是char[],然而要把byte转化成string，必须经过编码。string.length()其实就是char数组的长度，如果使用不同的编码，很可能会错分，造成散字和乱码。 <br />例如： <br /><code>String encoding = “”; <br />byte [] b={(byte)'\u00c4',(byte)'\u00e3'}; <br />String str=new String(b,encoding);　　 <br /></code>如果encoding=8859_1，会有两个字，但是encoding=gb2312只有一个字这个问题在处理分页是经常发生 。 <br /><br /><strong>4.Reader,Writer / InputStream,OutputStream </strong><br />Reader和Writer核心是char，InputStream和OutputStream核心是byte。但是Reader和Writer的主要目的是要把char读/写InputStream/OutputStream。 <br />例如： <br />文件test.txt只有一个"你"字，0xc4,0xe3 <br /><code>String encoding = "gb2312"; <br />InputStreamReader reader = new InputStreamReader(new FileInputStream( <br />"text.txt"), encoding); <br />char c[] = new char[10]; <br />int length = reader.read(c); <br />for (int i = 0; i &lt; length; i++) { <br />System.out.println(c[i]); <br />} <br /></code>结果是什么？你 <br />如果encoding ="8859_1"，结果是什么？??两个字符，表示不认识。 <br />反过来的例子自己做。 <br /><br /><strong>5.我们要对java的编译器有所了解 </strong>： <br />javac ?encoding <br />我们常常没有用到encoding这个参数。其实encoding这个参数对于跨平台的操作是很重要的。如果没有指定encoding，则按照系统的默认encoding,gb平台上是gb2312，英文平台上是iso8859_1。 <br />java
的编译器实际上是调用sun.tools.javac.main的类，对文件进行编译，这个类有compile函数中间有一个encoding的变量,-
encoding的参数其实直接传给encoding变量。编译器就是根据这个变量来读取java文件的，然后把用utf-8形式编译成class文件。
<br />例子代码： <br /><code>String str = "你"; <br />FileWriter writer = new FileWriter("text.txt"); <br />write.write(str); <br />writer.close(); <br /><br /></code>如果用gb2312编译，你会找到e4 bd a0的字段 ； <br />如果用8859_1编译， 00c4 00e3的二进制： <br />0000，0000 ，1100，0100 ，0000，0000 ，1110，0011 <br />因为每个字符都大于7位，因此用11位编码： <br />1100，0001，1000，0100，1100，0011，1010，0011 <br />c1-- 84--　c3--　 a3 <br />你会找到c1 84 c3 a3 。 <br /><br />但是我们往往忽略掉这个参数，因此这样往往会有跨平台的问题： <br />样例代码在中文平台上编译，生成zhclass <br />样例代码在英文平台上编译，输出enclass <br />(1).　 zhclass在中文平台上执行ok,但是在英文平台上不行 <br />(2). enclass在英文平台上执行ok,但是在中文平台上不行 <br />原因： <br />(1).
在中文平台上编译后，其实str在运行态的char[]是0x4f60,　在中文平台上运行，filewriter的缺省编码是gb2312,因此
chartobyteconverter会自动用调用gb2312的converter,把str转化成byte输入到fileoutputstream
中，于是0xc4,0xe3放进了文件。 <br />但是如果是在英文平台下，chartobyteconverter的缺省值是8859_1, filewriter会自动调用8859_1去转化str,但是他无法解释，因此他会输出"?" <br />(2). 在英文平台上编译后，其实str在运行态的char[]是0x00c4 0x00e3, 在中文平台上运行，中文无法识别，因此会出现??； <br />在英文平台上，0x00c4--&gt;0xc4,0x00e3-&gt;0xe3，因此0xc4,0xe3被放进了文件。 <br /><br /><strong>6. 其它原因： </strong>&lt;%@ page contentType="text/html; charset=GBK" %&gt; <br />设置浏览器的显示编码，如果response的数据是utf8编码，显示将是乱码，但是乱码和上述原因还不一样。 <br /><br /><strong>7. 发生编码的地方 </strong>： <br /> 从数据库到java程序 byte——〉char <br /> 从java程序到数据库 char——〉byte <br /> 从文件到java程序 byte——〉char <br /> 从java程序到文件 char——〉byte <br /> 从java程序到页面显示 char——〉byte <br /> 从页面form提交数据到java程序byte——〉char <br /> 从流到java程序byte——〉char <br /> 从java程序到流char——〉byte <br /><br />谢志钢的解决方法： <br />我是使用配置过滤器的方法解决中文乱码的： <br /><br /><code>＜web-app&gt; <br />＜filter&gt; <br />＜filter-name&gt;RequestFilter&lt;/filter-name&gt; <br />＜filter-class&gt;net.golden.uirs.util.RequestFilter&lt;/filter-class&gt; <br />＜init-param&gt; <br />＜param-name&gt;charset&lt;/param-name&gt; <br />＜param-value&gt;gb2312&lt;/param-value&gt; <br />＜/init-param&gt; <br />＜/filter&gt; <br />＜filter-mapping&gt; <br />＜filter-name&gt;RequestFilter&lt;/filter-name&gt; <br />＜url-pattern&gt;*.jsp&lt;/url-pattern&gt; <br />＜/filter-mapping&gt; <br />＜/web-app&gt; <br /><br /><br />public void doFilter(ServletRequest req, ServletResponse res, <br />FilterChain fChain) throws IOException, ServletException { <br />HttpServletRequest request = (HttpServletRequest) req; <br />HttpServletResponse response = (HttpServletResponse) res; <br />HttpSession session = request.getSession(); <br />String userId = (String) session.getAttribute("userid"); <br />req.setCharacterEncoding(this.filterConfig.getInitParameter("charset")); // 设置字符集？ <br />实际上是设置了byte ——〉char的encoding <br />try { <br />if (userId == null || userId.equals("")) { <br />if (!request.getRequestURL().toString().matches( <br />".*/uirs/logon/logon(Controller){0,1}\\x2Ejsp$")) { <br />session.invalidate(); <br />response.sendRedirect(request.getContextPath() + <br />"/uirs/logon/logon.jsp"); <br />} <br />} <br />else { // 看看是否具有信息上报系统的权限 <br />if (!net.golden.uirs.util.UirsChecker.check(userId, "信息上报系统", <br />net.golden.uirs.util.UirsChecker.ACTION_DO)) { <br />if (!request.getRequestURL().toString().matches( <br />".*/uirs/logon/logon(Controller){0,1}\\x2Ejsp$")) { <br />response.sendRedirect(request.getContextPath() + <br />"/uirs/logon/logonController.jsp"); <br />} <br />} <br />} <br />} <br />catch (Exception ex) { <br />response.sendRedirect(request.getContextPath() + <br />"/uirs/logon/logon.jsp"); <br />} <br />fChain.doFilter(req, res); <br />} </code><img src ="http://www.blogjava.net/JafeLee/aggbug/133740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-08-01 09:52 <a href="http://www.blogjava.net/JafeLee/articles/133740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 驯服 Tiger: 线程中的默认异常处理 作者：John Zukowski </title><link>http://www.blogjava.net/JafeLee/articles/133417.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Mon, 30 Jul 2007 12:03:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/133417.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/133417.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/133417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/133417.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/133417.html</trackback:ping><description><![CDATA[
		<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
		<span style="color: rgb(0, 0, 0);">
		</span>原文链接：<a href="http://blog.csdn.net/ARTHAS1982/archive/2004/08/30/89065.aspx">http://blog.csdn.net/ARTHAS1982/archive/2004/08/30/89065.aspx</a><br /><br /><p><span class="atitle2"><span class="astitle">驯服 Tiger: </span><span class="atitle">线程中的默认异常处理</span></span></p><p><span class="atitle2">如何处理未捕获的异常</span><br /></p><p><a href="http://www-900.ibm.com/developerWorks/cn/java/j-tiger08104/#author1"><name>John Zukowski</name></a> （<a href="mailto:jaz@zukowski.net">jaz@zukowski.net</a>） <br />总裁, JZ Ventures, Inc.<br />2004 年 8 月 </p><blockquote><abstract-extended>跟踪无法预期的运行时异常可能是一件又慢又费力的事情，只获得默认线程名称和堆栈跟踪通常是不够的。在<i xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">驯服 Tiger</i> 这一期专栏中，Java 开发人员 John Zukowski 向您展示了如何通过替代默认行为来定制输出。他还对比了通过细分 <code>ThreadGroup</code> 定制输出的老方法与通过提供自己的 <code>UncaughtExceptionHandler</code> 定制输出的新方法。 </abstract-extended></blockquote><p>虽然我们不想创建在无法预期时抛出运行时异常的程序，但这种情况还是会发生——尤其是第一次运行复杂程序时。通常是使用默认行为、打印堆栈溢出和结束线程的生命来处理这些异常。</p><p>从哪里发现默认行为？每个线程都属于一个由 <code>java.lang.ThreadGroup</code>
类表示的线程组。顾名思义，线程组允许您将线程组合在一起。您可能是为了方便而将线程组合，例如，一个线程池中的所有线程都属于组
X，而另一个池的所有线程则属于组 Y，或者是为了访问控制而将线程进行组合。组 X 中的线程无权访问或改变组 Y
中的线程，除非它们都在同一线程组内（或在一个子组内）。</p><p>在 Tiger 之前，<code>ThreadGroup</code> 类提供了一种处理未捕获异常的方法：<code>ThreadGroup</code> 的 <code>uncaughtException()</code> 方法。如果异常不是 <code>ThreadDeath</code>，则将线程的名称和堆栈回溯（stack backtrace）发送到 <code>System.err</code>。但是 Tiger 添加了另一种方法：<code>Thread.UncaughtExceptionHandler</code> 接口。细分 <code>ThreadGroup</code> 或安装该新接口的实现都允许您更改默认行为。我们将对 Tiger 之前和之后提供的方法都进行研究。</p><p><a name="1.0"><span class="atitle2">使用 ThreadGroup 的定制行为</span></a><br />发生未捕获的异常时，默认行为是将堆栈溢出打印输出到系统错误（<code>System.err</code>）中，如清单 1 中所示。不需要使用任何命令参数来启动程序。</p><a name="list1"><b>清单 1. 线程溢出示例<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">     </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">   SimpleDump<br />{<br />     </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);">   </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);">   </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);">  main(String args[])<br />    {<br />        System.out.println(args[ </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);"> ]);<br />    }<br />}</span></div><br /></b></a><p>不使用任何参数运行该程序将生成清单 2 中的输出。尽管它不是一个很长的堆栈跟踪，但它是一个完整的堆栈跟踪。</p><a name="list2"><b>清单 2. 默认线程溢出输出</b></a><br /><table bgcolor="#cccccc" border="1" cellpadding="5" cellspacing="0" width="100%"><tbody><tr><td><pre><code>Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0   <br />at SimpleDump.main(SimpleDump.java:3)</code></pre></td></tr></tbody></table><p>正如 Java 平台的许多东西一样，如果不喜欢默认行为，您可以对其进行更改。在 Java 平台的 Tiger 版以前的版本中，不能替代所有线程的默认行为，但是可以创建一个新的 <code>ThreadGroup</code>，并更改在该组内创建的任何线程的默认行为。您可以重写 <code>uncaughtException(Thread t, Throwable e)</code> 方法来定制该行为。然后，当发生未预料的运行时异常时，该线程组内创建的任何线程都将获得新的行为。不过，最好是修复基础问题，我将提供一个简单的示例，说明更改默认行为所必需的步骤。清单 3 展示了将执行代码放入新线程的调整过的测试程序：</p><a name="list3"><b>清单 3. 调整过的线程溢出示例</b></a><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> WindowDump<br />{<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> main(String args[]) </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> Exception<br />    {<br />        ThreadGroup group </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> LoggingThreadGroup(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Logger</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />        </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Thread(group, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">myThread</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">) {<br />            </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> run()<br />            {<br />                System.out.println(</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">);<br />            }<br />        }.start();<br />    }<br />}</span></div><br /><p><code>LoggingThreadGroup</code> 类是一个新的内容，清单 4 中显示了它的定义。为了进行说明，通过重写 <code>uncaughtException()</code> 方法实现的特殊行为将在一个弹出窗口中显示该异常，这项操作是在特殊 <code>Handler</code> 的帮助下使用 Java Logging API 来完成的。</p><a name="list4"><b>清单 4. LoggingThreadGroup 的定义</b></a><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.logging.</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">;<br /><br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> LoggingThreadGroup </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> ThreadGroup<br />{<br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> Logger logger;<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> LoggingThreadGroup(String name)<br />    {<br />        </span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">(name);<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> uncaughtException(Thread t, Throwable e)<br />    {<br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (logger </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)<br />        {<br />            logger </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Logger.getLogger(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">example</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />            Handler handler </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> LoggingWindowHandler.getInstance();<br />            logger.addHandler(handler);<br />        }<br />        logger.log(Level.WARNING, t.getName(), e);<br />    }<br />}</span></div><br /><p>这里创建的定制 <code>Handler</code> 的类型为 <code>LoggingWindowHandler</code>，该类型的定义在清单 5 中。处理程序使用了一个支持类 <code>LoggingWindow</code>，该类将异常显示在屏幕上。<a href="http://www-900.ibm.com/developerWorks/cn/java/j-tiger08104/#list6" xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" trackclick="no">清单 6</a> 中显示了该类的定义。<code>Handler</code> 的 <code>public void publish(LogRecord record)</code> 方法实现了一些重要操作。其余操作大部分只与配置有关。</p><a name="list5"><b>清单 5. LoggingWindowHandler 的定义</b></a><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.util.logging.</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">;<br /><br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> LoggingWindowHandler </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> Handler<br />{<br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> LoggingWindow window;<br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> LoggingWindowHandler handler;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> LoggingWindowHandler()<br />    {<br />        configure();<br />        window </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> LoggingWindow(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Logging window<img src="http://www.blogjava.net/images/dot.gif" /></span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">400</span><span style="color: rgb(0, 0, 0);">, </span><span style="color: rgb(0, 0, 0);">200</span><span style="color: rgb(0, 0, 0);">);<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">synchronized</span><span style="color: rgb(0, 0, 0);"> LoggingWindowHandler getInstance()<br />    {<br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (handler </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)<br />        {<br />            handler </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> LoggingWindowHandler();<br />        }<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> handler;<br />    }<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> * Get any configuration properties set </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> configure()<br />    {<br />        LogManager manager </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> LogManager.getLogManager();<br />        String className </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> getClass().getName();<br />        String level </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> manager.getProperty(className </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.level</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />        setLevel((level </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(0, 0, 0);">?</span><span style="color: rgb(0, 0, 0);"> Level.INFO : Level.parse(level));<br />        String filter </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> manager.getProperty(className </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.filter</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />        setFilter(makeFilter(filter));<br />        String formatter </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> manager.getProperty(className </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">.formatter</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />        setFormatter(makeFormatter(formatter));<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Filter makeFilter(String name)<br />    {<br />        Filter f </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br />        </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"><br />        {<br />            Class c </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Class.forName(name);<br />            f </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (Filter) c.newInstance();<br />        }<br />        </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (Exception e)<br />        {<br />            </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (name </span><span style="color: rgb(0, 0, 0);">!=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">)<br />            {<br />                System.err.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Unable to load filter: </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> name);<br />            }<br />        }<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> f;<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Formatter makeFormatter(String name)<br />    {<br />        Formatter f </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br />        </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"><br />        {<br />            Class c </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> Class.forName(name);<br />            f </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (Formatter) c.newInstance();<br />        }<br />        </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (Exception e)<br />        {<br />            f </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> SimpleFormatter();<br />        }<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> f;<br />    } <br />    <br />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> Overridden abstract Handler methods</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> close()<br />    {<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> flush()<br />    {<br />    }<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> * If record is loggable, format it and add it to window </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> publish(LogRecord record)<br />    {<br />        String message </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">;<br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> (isLoggable(record))<br />        {<br />            </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"><br />            {<br />                message </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> getFormatter().format(record);<br />            }<br />            </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (Exception e)<br />            {<br />                reportError(</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">, e, ErrorManager.FORMAT_FAILURE);<br />                </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">;<br />            }<br />            </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"><br />            {<br />                window.addLogInfo(message);<br />            }<br />            </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (Exception e)<br />            {<br />                reportError(</span><span style="color: rgb(0, 0, 255);">null</span><span style="color: rgb(0, 0, 0);">, e, ErrorManager.WRITE_FAILURE);<br />            }<br />        }<br />    }<br />}</span></div><br xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /><br xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /><a name="list6"><b>清单 6. LoggingWindow 的定义</b></a><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.awt.</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">;<br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> javax.swing.</span><span style="color: rgb(0, 0, 0);">*</span><span style="color: rgb(0, 0, 0);">;<br /><br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> LoggingWindow </span><span style="color: rgb(0, 0, 255);">extends</span><span style="color: rgb(0, 0, 0);"> JFrame<br />{<br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> JTextArea textArea;<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> LoggingWindow(String title, </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> width, </span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> height)<br />    {<br />        </span><span style="color: rgb(0, 0, 255);">super</span><span style="color: rgb(0, 0, 0);">(title);<br />        EventQueue.invokeLater(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Runnable() {<br />            </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> run()<br />            {<br />                setSize(width, height);<br />                textArea </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> JTextArea();<br />                JScrollPane pane </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> JScrollPane(textArea);<br />                textArea.setEditable(</span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">);<br />                getContentPane().add(pane);<br />                setVisible(</span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">);<br />            }<br />        });<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> addLogInfo(</span><span style="color: rgb(0, 0, 255);">final</span><span style="color: rgb(0, 0, 0);"> String data)<br />    {<br />        EventQueue.invokeLater(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Runnable() {<br />            </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> run()<br />            {<br />                textArea.append(data);<br />            }<br />        });<br />    }<br />}</span></div><br /><p>执行 <a href="http://www-900.ibm.com/developerWorks/cn/java/j-tiger08104/#list3" xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" trackclick="no">清单 3</a> 中的 <code>WindowDump</code> 程序将出现图 1 中的屏幕。因为没有从 <code>Logger</code> 中删除控制台处理程序，所以堆栈溢出仍将出现在控制台上。</p><p><a name="IDAMKJ2C"><b>图 1. 记录的堆栈跟踪</b></a><br /><img alt="记录的堆栈跟踪" src="http://www-900.ibm.com/developerWorks/cn/java/j-tiger08104/stack.jpg" xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" height="200" width="400" /></p><p>发生运行时异常时，可能要做许多工作来更改发生的问题。该代码的大部分都是 Logging Handler，但是，要执行更改，就必须细分 <code>ThreadGroup</code>，重写 <code>uncaughtException()</code>，然后在该线程组中执行您的线程。不过，让我们通过只安装 <code>Thread.UncaughtExceptionHandler</code>，来看一看 Tiger 的处理方式。</p><p><a name="2.0"><span class="atitle2">使用 UncaughtExceptionHandler 的定制行为</span></a><br />对于 Tiger，<code>Thread</code> 类定义中添加了一个新的公共内部类 <code>UncaughtExceptionHandler</code>，更完整的名称为 <code>Thread.UncaughtExceptionHandler</code>（其他类访问内部类时需要使用完整名称）。接口的定义是一个方法，如图 7 中所示：</p><a name="list7"><b>清单 7. UncaughtExceptionHandler 的定义</b></a><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">interface</span><span style="color: rgb(0, 0, 0);"> UncaughtExceptionHandler <br />{    <br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> uncaughtException(Thread, Throwable);<br />}</span></div><br /><p>您可能没有注意到，清单 7 中的方法与我们前面重写的 <code>ThreadGroup</code> 的方法相同。实际上，现在由 <code>ThreadGroup</code> 类实现该接口。</p><p>新的内部类可以帮助我们了解下列两对新方法，并有助于我们在 <code>Thread</code> 中使用它们：</p><ul xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><li><code>getUncaughtExceptionHandler()</code> 和 <code>setUncaughtExceptionHandler()</code>。 </li><li><code>getDefaultUncaughtExceptionHandler()</code> 和 <code>setDefaultUncaughtExceptionHandler()</code>。 </li></ul><p>第一对方法是 <code>getUncaughtExceptionHandler()</code> 和 <code>setUncaughtExceptionHandler()</code>，它们允许您为当前线程及其后代定制行为，从而允许二十或更多的线程拥有自己的定制行为。不过，您更可能使用第二对方法 <code>getDefaultUncaughtExceptionHandler()</code> 和 <code>setDefaultUncaughtExceptionHandler()</code>。如果使用第二对方法设置默认处理程序，那么没有自己的异常处理程序的所有线程都将使用默认处理程序。</p><p>听起来好像很简单。为了进行说明，清单 8 转换了 <a href="http://www-900.ibm.com/developerWorks/cn/java/j-tiger08104/#list3" xmlns:dw="http://www.ibm.com/developerWorks/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" trackclick="no">清单 3</a> 中的 <code>ThreadGroup</code> 友好的程序，使用新的 <code>UncaughtExceptionHandler</code> 接口：</p><a name="list8"><b>清单 8. UncaughtExceptionHandler 示例</b></a><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> HandlerDump<br />{<br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">static</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> main(String args[]) </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> Exception<br />    {<br />        Thread.UncaughtExceptionHandler handler </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> LoggingThreadGroup(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">Logger</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br />        Thread.currentThread().setUncaughtExceptionHandler(handler);<br />        System.out.println(</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">/</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">);<br />    }<br />}</span></div><br /><p>该程序只是将 <code>LoggingThreadGroup</code> 重用为 <code>UncaughtExceptionHandler</code>，并没有创建新的处理程序实现。请注意，与原来的代码相比，新代码要简洁得多。</p><p><a name="3.0"><span class="atitle2">其他线程更改</span></a><br /><code>Thread</code> 类不仅支持使用 Tiger 添加的未捕获异常处理程序，它还支持使用 <code>getAllStackTraces()</code> 获得所有有效线程的堆栈跟踪，或者支持使用 <code>getStackTrace()</code> 来只获得当前线程的堆栈跟踪。这两种堆栈跟踪都返回类型为 <code>java.lang.StackTraceElement</code> 的对象，<code>java.lang.StackTraceElement</code> 是 Java 1.4 平台中添加的一个类，它可以让您生成自己的堆栈跟踪。同时，Java 5 平台新添加的功能是一个惟一线程标识符（可以使用 <code>getId()</code> 获得该标识符）和一个新的 <code>Thread.State</code> 类，以及与该类相关的 <code>getThreadState()</code> 方法。最后一个线程更改是一个状态枚举表，该表是用来监视系统状态，而不是用来同步状态的。</p><p><a name="4.0"><span class="atitle2">结束语</span></a><br />像
添加未捕获的异常处理程序这样的简单库更改，可以极大地增加原代码的可理解性。虽然在线程组级别上，新的库代码的功能与原来库代码的相同，但新模型中的易
用性和灵活性远远超出了将代码调整为更新的方式所需的时间。当然，老方法仍然可以使用，但最好将代码更新为最新的库功能。</p><img src ="http://www.blogjava.net/JafeLee/aggbug/133417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-30 20:03 <a href="http://www.blogjava.net/JafeLee/articles/133417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>System.getProperty()参数大全 (转载)</title><link>http://www.blogjava.net/JafeLee/articles/132966.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Sat, 28 Jul 2007 05:14:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/132966.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/132966.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/132966.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/132966.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/132966.html</trackback:ping><description><![CDATA[原文地址：<a href="http://hi.baidu.com/forecho/blog/item/e7854f162310dc4b20a4e9d6.html">http://hi.baidu.com/forecho/blog/item/e7854f162310dc4b20a4e9d6.html</a><br /><br /><table summary="Shows property keys and associated values" height="648" width="748"><tbody><tr><td><code><font face="新宋体">java.version</font></code></td><td><font color="#ff0000">Java Runtime Environment version</font></td></tr><tr><td><code><font face="新宋体">java.vendor</font></code></td><td><font color="#ff0000">Java Runtime Environment vendor</font></td></tr><tr><td><code><font face="新宋体">java.vendor.url</font></code></td><td><font color="#ff0000">Java vendor URL</font></td></tr><tr><td><code><font face="新宋体">java.home</font></code></td><td><font color="#ff0000">Java installation directory</font></td></tr><tr><td><code><font face="新宋体">java.vm.specification.version</font></code></td><td><font color="#ff0000">Java Virtual Machine specification version</font></td></tr><tr><td><code><font face="新宋体">java.vm.specification.vendor</font></code></td><td><font color="#ff0000">Java Virtual Machine specification vendor</font></td></tr><tr><td><code><font face="新宋体">java.vm.specification.name</font></code></td><td><font color="#ff0000">Java Virtual Machine specification name</font></td></tr><tr><td><code><font face="新宋体">java.vm.version</font></code></td><td><font color="#ff0000">Java Virtual Machine implementation version</font></td></tr><tr><td><code><font face="新宋体">java.vm.vendor</font></code></td><td><font color="#ff0000">Java Virtual Machine implementation vendor</font></td></tr><tr><td><code><font face="新宋体">java.vm.name</font></code></td><td><font color="#ff0000">Java Virtual Machine implementation name</font></td></tr><tr><td><code><font face="新宋体">java.specification.version</font></code></td><td><font color="#ff0000">Java Runtime Environment specification version</font></td></tr><tr><td><code><font face="新宋体">java.specification.vendor</font></code></td><td><font color="#ff0000">Java Runtime Environment specification vendor</font></td></tr><tr><td><code><font face="新宋体">java.specification.name</font></code></td><td><font color="#ff0000">Java Runtime Environment specification name</font></td></tr><tr><td><code><font face="新宋体">java.class.version</font></code></td><td><font color="#ff0000">Java class format version number</font></td></tr><tr><td><code><font face="新宋体">java.class.path</font></code></td><td><font color="#ff0000">Java class path</font></td></tr><tr><td><code><font face="新宋体">java.library.path</font></code></td><td><font color="#ff0000">List of paths to search when loading libraries</font></td></tr><tr><td><code><font face="新宋体">java.io.tmpdir</font></code></td><td><font color="#ff0000">Default temp file path</font></td></tr><tr><td><code><font face="新宋体">java.compiler</font></code></td><td><font color="#ff0000">Name of JIT compiler to use</font></td></tr><tr><td><code><font face="新宋体">java.ext.dirs</font></code></td><td><font color="#ff0000">Path of extension directory or directories</font></td></tr><tr><td><code><font face="新宋体">os.name</font></code></td><td><font color="#ff0000">Operating system name</font></td></tr><tr><td><code><font face="新宋体">os.arch</font></code></td><td><font color="#ff0000">Operating system architecture</font></td></tr><tr><td><code><font face="新宋体">os.version</font></code></td><td><font color="#ff0000">Operating system version</font></td></tr><tr><td><code><font face="新宋体">file.separator</font></code></td><td><font color="#ff0000">File separator ("/" on UNIX)</font></td></tr><tr><td><code><font face="新宋体">path.separator</font></code></td><td><font color="#ff0000">Path separator (":" on UNIX)</font></td></tr><tr><td><code><font face="新宋体">line.separator</font></code></td><td><font color="#ff0000">Line separator ("\n" on UNIX)</font></td></tr><tr><td><code><font face="新宋体">user.name</font></code></td><td><font color="#ff0000">User's account name</font></td></tr><tr><td><code><font face="新宋体">user.home</font></code></td><td><font color="#ff0000">User's home directory</font></td></tr><tr><td><code><font face="新宋体">user.dir</font></code></td><td><font color="#ff0000">User's current working directory</font></td></tr></tbody></table><br /><img src ="http://www.blogjava.net/JafeLee/aggbug/132966.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-28 13:14 <a href="http://www.blogjava.net/JafeLee/articles/132966.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是接口回调？（转载）</title><link>http://www.blogjava.net/JafeLee/articles/131550.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Fri, 20 Jul 2007 12:20:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/131550.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/131550.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/131550.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/131550.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/131550.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 标签：向上转型接口回调　																																																								版权声明：原创作品，允许转载，转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://zhangjunhd.blog.51cto.com/113473/20198												...&nbsp;&nbsp;<a href='http://www.blogjava.net/JafeLee/articles/131550.html'>阅读全文</a><img src ="http://www.blogjava.net/JafeLee/aggbug/131550.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-20 20:20 <a href="http://www.blogjava.net/JafeLee/articles/131550.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐一些不错的杂志：Free Development Magazines(zz)</title><link>http://www.blogjava.net/JafeLee/articles/131479.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Fri, 20 Jul 2007 06:48:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/131479.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/131479.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/131479.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/131479.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/131479.html</trackback:ping><description><![CDATA[
		<a href="/hongjunli/archive/2007/07/18/131147.html">http://www.blogjava.net/hongjunli/archive/2007/07/18/131147.html</a>
		<br />
		<br />
		<div class="postText">
				<p>
						<strong>General Technology Interest<br /></strong>
				</p>
				<ul style="margin-top: 0in;" type="disc">
						<li>Name: <strong>eWeek - The Enterprise Weekly</strong><br />Publisher: Ziff-Davis<br />Frequency: Weekly<br />Sign Up Page: <a href="http://www.omeda.com/ziff/ewk/ewk.cgi?&amp;t=whback&amp;p=lz3home">http://www.omeda.com/ziff/ewk/ewk.cgi?&amp;t=whback&amp;p=lz3home</a><br /></li>
						<li>Name: <strong>InformationWeek</strong><br />Publisher: CMP United Business Media<br />Frequency: Monthly<br />Sign Up Page: <a href="http://informationweeksubscriptions.com/customerservice/">http://informationweeksubscriptions.com/customerservice/</a><br /></li>
				</ul>
				<p>
						<strong>Tool Specific<br /></strong>
				</p>
				<ul style="margin-top: 0in;" type="disc">
						<li>Name: <strong>Eclipse Review</strong><br />Publisher: BZ Media<br />Frequency: Quarterly<br />Sign Up Page: <a href="http://www.eclipsereview.com/subscribe.htm">http://www.eclipsereview.com/subscribe.htm</a></li>
				</ul>
				<br />
				<ul style="margin-top: 0in;" type="disc">
						<li>Name: <strong>Eclipse Magzine</strong></li>
				</ul>
				<p>         Publisher: Software &amp; Support Media<br />         Frequency: Monthly<br />         Sign Up Page: <a href="http://eclipse-magazin.de/">http://eclipse-magazin.de/</a><br /><br /></p>
				<ul style="margin-top: 0in;" type="disc">
						<li>Name: <strong>Visual Studio Magazine</strong><br />Publisher: Fawcette Technical Publications<br />Frequency: Monthly<br />Sign Up Page: <a href="http://www.ftponline.com/vsm/">http://www.ftponline.com/vsm/</a> (lower left of page)<br /></li>
				</ul>
				<p>
						<strong>Industry Specific<br /></strong>
				</p>
				<ul style="margin-top: 0in;" type="disc">
						<li>Name: <strong>GameDeveloper</strong><br />Publisher: CMP United Business Media<br />Frequency: Monthly<br />Sign Up Page: <a href="http://www.gdmag.com/freeyear">http://www.gdmag.com/freeyear</a><br /></li>
				</ul>
				<p>
						<strong>Best Practices<br /></strong>
				</p>
				<ul style="margin-top: 0in;" type="disc">
						<li>Name: <strong>Software Test &amp; Performance</strong><br />Publisher: BZ Media<br />Frequency: Monthly<br />Sign Up Page: <a href="http://www.stpmag.com/subscribe.htm">http://www.stpmag.com/subscribe.htm</a><br /></li>
						<li>Name: <strong>Software Development</strong><br />Publisher: CMP United Business Media<br />Frequency: Monthly<br />Sign Up Page: <a href="http://sdsubs.com/customerservice/">http://sdsubs.com/customerservice/</a><br /></li>
						<li>Name: <strong>Dr. Dobb's Journal</strong><br />Publisher: CMP United Business Media<br />Frequency: Monthly<br />Sign Up Page: <a href="http://www.ddj.com/subscriber/">http://www.ddj.com/subscriber/</a><br /></li>
				</ul>
				<p>
						<strong>Language Specific<br /></strong>
				</p>
				<ul style="margin-top: 0in;" type="disc">
						<li>Name: <strong>JavaPro</strong><br />Publisher: Fawcette Technical Publications<br />Frequency: Monthly<br />Sign Up Page: <a href="http://www.ftponline.com/javapro/">http://www.ftponline.com/javapro/</a><br />Note: Went to sign up for free subscription and received an under construction error.<br /></li>
						<li>Name: <strong>Oracle Magazine</strong><br />Publisher: Oracle Corporation<br />Frequency: Bimonthly<br />Sign Up Page: <a href="http://slackermanager.tradepub.com/free/orm/prgm.cgi">http://slackermanager.tradepub.com/free/orm/prgm.cgi</a></li>
				</ul>
				<p>
						<strong>Electronic Newsletters<br /></strong>
				</p>
				<ul>
						<li>Name: <strong>SitePoint Tribune, Tech Times, Design View, Community Crier<br /></strong></li>
				</ul>
				<blockquote>Publisher: <a href="http://sitepoint.com/">SitePoint</a><br />Frequency: Online<br />Sign Up Page: <a href="http://www.sitepoint.com/newsletter/archives.php" rel="nofollow">http://www.sitepoint.com/newsletter/archives.php</a></blockquote>
				<p class="zoundry_bw_tags">
						<!-- Tag links generated by Zoundry Blog Writer. Do not manually edit. http://www.zoundry.com -->
						<span class="ztags">
								<span class="ztagspace">Technorati</span> : <a class="ztag" href="http://technorati.com/tag/Free%20Development%20Magazines" rel="tag">Free Development Magazines</a></span>
				</p>
		</div>
		<br />
<img src ="http://www.blogjava.net/JafeLee/aggbug/131479.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-20 14:48 <a href="http://www.blogjava.net/JafeLee/articles/131479.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Core Java Bug List of Seventh Edition Volume 1 (JDK 5.0)</title><link>http://www.blogjava.net/JafeLee/articles/131213.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Thu, 19 Jul 2007 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/131213.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/131213.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/131213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/131213.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/131213.html</trackback:ping><description><![CDATA[
		<h3>Seventh Edition Volume 1 <span style="font-weight: bold;"></span>(JDK     5.0)<span style="font-weight: bold;"></span><a name="CJ7V1"></a><img alt="" src="http://www.horstmann.com/corejava/cj7v1.jpg" style="width: 189px; height: 250px;" /></h3>
		<dl>
				<dt>[2] Page xvi</dt>
				<dd>In the seventh line from the bottom, change "bugs fixes" to "bug       fixes".<br /></dd>
				<dt>[6] Page 18</dt>
				<dd>Change "You can download them from       <tt>http://www.phptr.com/corejava</tt>." to "You can download them from       <tt>http://<strong>horstmann</strong>.com/corejava</tt>."</dd>
				<dt>[4] Page 25</dt>
				<dd>In the NOTE, change "Environnment" to "Environment".<br /></dd>
				<dt>[6] Page 36</dt>
				<dd>Change “it simply displays the string <tt>We will not use       'Hello, World'!</tt>” to “it simply displays the string       <tt>We will not use 'Hello, World!'</tt>” (i.e. move the ! inside       the quotes to match the program at the top of the page)</dd>
				<dt>[5] Page 40</dt>
				<dd>After "..you use a <tt>p</tt>, not an <tt>e</tt>, to denote the       exponent." add: "The exponent is specified in decimal and denotes a       power of two."</dd>
				<dt>Page 40</dt>
				<dd>Change <tt>NEGATIVE_ INFINITY</tt> to <tt>NEGATIVE_INFINITY</tt>       (without a space)</dd>
				<dt>[4] Page 41</dt>
				<dd>Change "an unused 2048 byte-range" to "a range of 2048 unused       values"<br /></dd>
				<dt>[6] Page 56</dt>
				<dd>Change "Point your web browser to the <tt>docs/api/index.html</tt>       subdirectory of your JDK installation." to "Point your web browser to       the <tt>index.html</tt> file in the <tt>docs/api</tt> subdirectory of       your JDK installation."</dd>
				<dt>[6] Page 62, 123, 125, 465, 629, 630, 631, 640, 641, 642, 649,       681,</dt>
				<dd>Change "Boolean" to "<tt>boolean</tt>" (in monospace)</dd>
				<dt>[5] Page 62</dt>
				<dd>Remove the line "<tt>^</tt> Converts to upper case <tt>0XCAFE</tt>".       (This option was present in the Java 5 release candidate, but it was       later dropped.)</dd>
				<dt>[6] Page 63</dt>
				<dd>Change "You use two a two-letter format..." to "You use a two-letter       format..."</dd>
				<dt>[4] Page 64</dt>
				<dd>Last line of Table 3-7 (continued): Change <span style="font-family: monospace;">E</span> to <span style="font-family: monospace;">Q</span>.<br /></dd>
				<dt>[2] Page 80 BigIntegerTest.java line 8</dt>
				<dd>Change <span style="font-family: monospace;">Scanner.create</span>       to <span style="font-family: monospace;">new Scanner</span></dd>
				<dt>[4] Page 85</dt>
				<dd>Change <tt>System.out.print(" " + a[i]);</tt> to       <tt>System.out.print(" " + a<strong>rgs</strong>[i]);</tt></dd>
				<dt>[4] Page 86</dt>
				<dd>Change "Initially that is just <tt>r</tt> itself, but ..." to       "Initially that is just <tt>r + 1</tt>, but..."<br /></dd>
				<dt>[4] Page 89 CompoundInterest.java line 5</dt>
				<dd>Change <span style="font-family: monospace;">final int       STARTRATE</span> to <span style="font-family: monospace;">final <span style="font-weight: bold;">double</span> STARTRATE</span><br /></dd>
				<dt>[6] Page 95</dt>
				<dd>Change
"Encapsulation (sometimes called data hiding) is a key concept in
working with objects. Formally, encapsulation is nothing more than
combining data and behavior in one package and hiding the
implementation of the data from the user of the object." to
"Encapsulation (sometimes called <strong>information</strong> hiding)
is a key concept in working with objects. Formally, encapsulation is
nothing more than combining data and behavior in one package and hiding
the implementation <strong>details</strong> from the user of the object."</dd>
				<dt>[4] Page 95</dt>
				<dd>Change "When you invoke a message on an object" to "When you invoke       a <strong>method</strong> on an object"<br /></dd>
				<dt>[6] Page 96</dt>
				<dd>Change
"Thus, a class depends on another class if its methods manipulate
objects of that class." to "Thus, a class depends on another class if
its methods <strong>use or</strong> manipulate objects of that       class."</dd>
				<dt>[4] Page 104-106 CalendarTest.java</dt>
				<dd>The
program prints an unsatisfactory calendar in locales whose first day of
the week is not Sunday. (In most parts of the world, the first day of
the week is considered Monday--after all, Saturday and Sunday are the
week<span style="font-style: italic;">end</span>.) The following       changes take care of this:<br /><ul><li>Remove the header <span style="font-family: monospace;">Sun</span><tt><span style="">Mon           Tue Wed Thu Fri Sat</span></tt> on page 104</li><li>In the program listing, replace lines 18 and 19 with<br /><pre> // get first day of week (Sunday in the U.S.)<br /> int firstDayOfWeek = d.getFirstDayOfWeek();</pre></li><li>In lines 22 and 49, replace <span style="font-family: monospace;">Calendar.SUNDAY</span> with <span style="font-family: monospace;">firstDayOfWeek</span></li><li>Add the following four lines before the <span style="font-family: monospace;">}</span> in line 44. (The first line           is blank)<br /><pre><br /> // start a new line at the start of the week<br /> if (weekday == firstDayOfWeek)<br /> System.out.println();<br /></pre></li><li>Remove lines 36 through 39</li></ul></dd>
				<dt>[4] Page 105</dt>
				<dd>Change "For each day, we print a space if the day is &lt; 10, then       the day, and then a <tt>*</tt> if the day equals the current day." to       "The current day is marked with a <tt>*</tt>."<br /></dd>
				<dt>[6] Page 106</dt>
				<dd>In the Note, remove "and the hard-wired assumption that the week       starts on a Sunday"</dd>
				<dt>[6] Page 121</dt>
				<dd>Change "demonstate" to "demonstrate"</dd>
				<dt>[6] Page 128, 129</dt>
				<dd>Change "Booleans" to "<tt>boolean</tt> values" (note monospace)</dd>
				<dt>[6] Page 135</dt>
				<dd>Remove the sentence "The sole purpose of package nesting is to       manage unique names."</dd>
				<dt>[6] Page 141</dt>
				<dd>Change
"Recall that you can import public classes only from other packages."
to "Recall that you can import only public classes from other packages."</dd>
				<dt>[4] Page 141</dt>
				<dd>In the third line from the bottom, change "packages" to       "package".<br /></dd>
				<dt>[4] Page 143</dt>
				<dd>In the last line, change "set the warning border" to "set the       warning string".<br /></dd>
				<dt>[6] Page 147</dt>
				<dd>Change
"If you like, you can place hyperlinks to other classes or methods
anywhere in any of your comments." to "If you like, you can place
hyperlinks to other classes or methods anywhere in any of your <tt>javadoc</tt> comments."</dd>
				<dt>[6] Page 155</dt>
				<dd>Remove "(that is, when i is 1 or 2)" and "(when i is 0)" , so that       the remaining clause is "either <tt>Employee</tt> or       <tt>Manager</tt>".</dd>
				<dt>[6] Page 165</dt>
				<dd>Change
"In particular, move common fields and methods (whether abstract or
not) to the abstract superclass." to "Move common fields and methods
(whether abstract or not) to the superclass (whether abstract or not)."</dd>
				<dt>[6] Page 172</dt>
				<dd>In the numbered list, add 4. before "Compare the classes of       <tt>this</tt> and <tt>otherObject</tt>." Increment the following       numbers.</dd>
				<dt>[4] Page 172</dt>
				<dd>Remove "Judging from this evidence. . ." until the end of the       note.<br /></dd>
				<dt>[4] Page 173</dt>
				<dd>In Table 5-1, change the Hash Code column from 140207504 / 140013338       / 884756206 to 69609650 / 69496448 / -2141031506</dd>
				<dt>[4] Page 174</dt>
				<dd>In Table 5-2, change 3030 to 2556 (2x)<br /></dd>
				<dt>[6] Page 179</dt>
				<dd>Change the last word on the page from "classed" to "called"</dd>
				<dt>[6] Page 180/181</dt>
				<dd>Change "relocation/tions/ting" to "re<strong>a</strong>llocation/tions/ting"       (3x)</dd>
				<dt>[6] Page 181</dt>
				<dd>Change
"(This is different from, and, of course, never larger than, the array
list’s capacity.)" to "(This is of course never larger than the array
list’s capacity.)"</dd>
				<dt>[6] Page 188</dt>
				<dd>Change "returns a new <tt>Integer</tt> object initialized to the       integer’s value, assuming the specified <tt>String</tt>       represents" to "returns a new <tt>Integer</tt> object initialized to the       integer whose digits are contained in the string <tt>s</tt>. The string       must represent" (2x)</dd>
				<dt>[4] Page 189</dt>
				<dd>Change<br /><pre>System.out.printf("%d %d", new Object[] { new Integer(d), "widgets" } );<br /></pre>to<br /><pre>System.out.printf("%d %<strong>s</strong>", new Object[] { new Integer(<strong>n</strong>), "widgets" } );</pre></dd>
				<dt>[6] Page 191</dt>
				<dd>Remove "We discuss reflection in the next section."</dd>
				<dt>Page 193</dt>
				<dd>Change "all fields, operations, and constructors" to "all fields,       <strong>methods</strong>, and constructors"</dd>
				<dt>[6] Page 198</dt>
				<dd>Change the last line from<pre>while (cl != Object.class);</pre>to<pre>while (cl != null);</pre></dd>
				<dt>[6] Page 199</dt>
				<dd>Remove line 3 (<tt>import java.text.*;</tt>)</dd>
				<dt>[6] Page 201</dt>
				<dd>Change "<tt>arrayCopy</tt>" to "<tt>array<strong>c</strong>opy</tt>"</dd>
				<dt>[6] Page 203/204</dt>
				<dd>Change "fundamental" to "primitive" (2x)</dd>
				<dt>[4] Page 206</dt>
				<dd>Change<br /><pre><tt>System.out.printf("%10.4f | %10.4f%n" + y, x, y);</tt></pre>to<tt><br /></tt><pre><tt>System.out.printf("%10.4f | %10.4f%n", x, y);</tt></pre></dd>
				<dt>[4] Page 207</dt>
				<dd>Remove code lines 42 and 43.<br /></dd>
				<dt>[4] Page 215</dt>
				<dd>Change the first <tt>java.lang.Comparable</tt> API header to       <tt>java.lang.Comparable&lt;T&gt;</tt>. Remove the second       <tt>java.lang.Comparable&lt;T&gt;</tt> header.<br /></dd>
				<dt>[4] Page 220 and 221<br /></dt>
				<dd>In the <tt>clone</tt> methods, change<br /><pre>return super.clone();<br /></pre>to<br /><pre>return (Employee) super.clone();</pre></dd>
				<dt>Page 221</dt>
				<dd>Change<pre>public Object clone() throws CloneNotSupportedException</pre>to<pre>public <strong>Employee</strong> clone() throws CloneNotSupportedException</pre></dd>
				<dt>[6] Page 228</dt>
				<dd>Change “Because the <tt>TalkingClock</tt> defines no       constructors” to “Because the <tt>TimePrinter</tt> class       defines no constructors”</dd>
				<dt>[4] Page 231</dt>
				<dd>In the NOTE, change <br /><pre>java ReflectionTest 'TalkingClock$TimePrinter'</pre>to <br /><pre>java ReflectionTest TalkingClock\$TimePrinter<br /></pre>(that is, remove the quotes and add a backslash). Both methods work, but       the change matches the preceding text.<br /></dd>
				<dt>[6] Page 233</dt>
				<dd>Change “Note that the <tt>TimePrinter</tt>
class no longer needs to store a beep instance variable. It simply
refers to the parameter variable of the method that contains the class
definition.” to “Note that the <tt>TalkingClock</tt> class       no longer needs to store a <tt>beep</tt> instance field. The       <tt>actionPerformed</tt> method of the <tt>TimePrinter</tt> class simply       refers to the <tt>beep</tt> parameter variable of the <tt>start</tt>       method.”</dd>
				<dt>[4] Page 233 (2x) and 235 (1x)<br /></dt>
				<dd>Change <br /><pre>Timer t = new Timer(1000, listener)<br /></pre>to<br /><pre>Timer t = new Timer(interval, listener)</pre></dd>
				<dt>[4] Page 254</dt>
				<dd>Change <tt>/**import java.awt.*</tt> to <tt>import       java.awt.*</tt></dd>
				<dt>[6] Page 251</dt>
				<dd>Change <tt>frame.show();</tt> to       <tt>frame.setVisible(true);</tt></dd>
				<dt>Page 281</dt>
				<dd>Change <tt>javax.swing.ImageIO</tt> to       <tt>javax.imageio.ImageIO</tt></dd>
				<dt>[4] Page 330</dt>
				<dd>In the API note for <tt>getActionMap</tt>, change "keystrokes to       action keys" to "arbitrary objects to <tt>Action</tt> objects".<br /> In       the API note for <tt>getInputMap</tt>, change "action keys to action       objects" to "keystrokes to arbitrary objects"<br /></dd>
				<dt>[4] Page 330</dt>
				<dd>Change <tt>released ctrl Y</tt> to <tt>ctrl released       Y</tt><br /></dd>
				<dt>[4] Page 343</dt>
				<dd>Change "Each user interface has a wrapper class..." to "Each user       interface <strong>component</strong> has a wrapper class...".</dd>
				<dt>[4] Page 349</dt>
				<dd>Change "Finally, you add the individual buttons" to "Finally, you       add the panel"</dd>
				<dt>[4] Page 349</dt>
				<dd>The word <tt>add</tt> in "using the <tt>add</tt> method you have       seen before" is in the wrong font.<br /></dd>
				<dt>[4] Page 353</dt>
				<dd>In the first API note, change <tt>int cols</tt> to <tt>int       col<strong>umn</strong>s</tt><br /></dd>
				<dt>[4] Page 360</dt>
				<dd>Remove code lines 66 - 68<br /></dd>
				<dt>[4] Page 400</dt>
				<dd>Change the four code lines starting with <br /><pre><tt>JSpinner timeSpinner</tt></pre></dd>
				<dd>to<br /><pre><tt>JSpinner timeSpinner = new JSpinner(new </tt><br />      SpinnerDateModel(new Date(), null, null, Calendar.HOUR)<br />      { <br />         public void setCalendarField(int field) {} <tt><br />      });</tt><br /></pre></dd>
				<dt>[4] Page 402</dt>
				<dd>Change code lines 75 - 78 to<br /><tt>      JSpinner timeSpinner = new       JSpinner(new <br />                         SpinnerDateModel(new Date(), null, null, Calendar.HOUR)<br />                   {       <br />                            public void setCalendarField(int field) {} <br />                         });</tt><br /></dd>
				<dt>[4] Page 405</dt>
				<dd>In the explanation for the <tt>maximum</tt> parameter of the       <tt>javax.swing.SpinnerDateModel</tt> constructor, change "The maximum       valid value, or <tt>null</tt> if no lower bound..." to "The maximum       valid value, or <tt>null</tt> if no <strong>upper</strong> bound..."</dd>
				<dt>[4] Page 412</dt>
				<dd>In the second line from the bottom, change <tt>JPopup</tt> to       <tt>JPopupMenu</tt>.<br /></dd>
				<dt>[4] Page 422</dt>
				<dd>Below line 28, add a line<br /><pre>add(panel, BorderLayout.CENTER);</pre></dd>
				<dt>[4] Page 432</dt>
				<dd>Change <br /><pre>panel.add(style, bold);</pre></dd>
				<dd>to</dd>
				<dd>
						<pre>panel.add(component, constraints);<br /></pre>
				</dd>
				<dt>[6] Page 443</dt>
				<dd>The bulleted list is wrong (with different errors in two printings).       Here is the correct version:<ul><li>Connecting the <strong>west</strong> side of the <strong>component</strong> with the           <strong>west</strong> side of the <strong>container</strong>;</li><li>Traversing the width of the component;</li><li>Connecting the <strong>east</strong> side of the <strong>component</strong> with the           <strong>west</strong> side of the <strong>container</strong>.</li></ul></dd>
				<dt>[4] Page 444</dt>
				<dd>Change <br /><pre>Spring.max(layout.getConstraints(faceLabel).getWidth(),<br />Spring.max(layout.getConstraints(sizeLabel).getWidth()));<br /></pre>to<br /><pre>Spring.max(layout.getConstraints(faceLabel).getWidth(),<br />layout.getConstraints(sizeLabel).getWidth()));</pre>(i.e., remove the second <tt>Spring.Max(</tt>)<br /></dd>
				<dt>[4] Page 447</dt>
				<dd>Change "...to the given side of the <tt>start</tt> container" to       "...to the given side of the <tt>start</tt><strong>component</strong>"</dd>
				<dt>[4] Page 457</dt>
				<dd>Change "The icon is a warning icon" to "The icon is a       <strong>question</strong> icon". Change <tt>WARNING_MESSAGE</tt> to       <strong><tt>QUESTION</tt></strong><tt>_MESSAGE</tt><br /></dd>
				<dt>[6] Page 509</dt>
				<dd>Change
“NOTE: The strings used when you define the parameters with the param
tag and those used in the getParameter method must match exactly. In
particular, both are case sensitive.” to “NOTE: A case-insensitive
comparison is used when matching the <tt>name</tt>       attribute value in the <tt>param</tt> tag and the argument of the       <tt>getParameter</tt> method.”</dd>
				<dt>[6] Page 522, 524</dt>
				<dd>Change<pre>public Enumeration getApplets() { return null; } </pre>to<pre>public Enumeration&lt;Applet&gt; getApplets() { return null; } </pre>and<pre>public Iterator getStreamKeys() { return null; }</pre>to<pre>public Iterator&lt;String&gt; getStreamKeys() { return null; }</pre></dd>
				<dt>Page 527</dt>
				<dd>Change<pre>Main-Class: com/mycompany/mypkg/MainAppClass</pre>to<pre>Main-Class: com.mycompany.mypkg.MainAppClass</pre></dd>
				<dt>[6] Page 547</dt>
				<dd>Change<pre>defaultSettings.put("color.red", "0 50 50");</pre>to<pre>defaultSettings.put("color.red", "0");</pre></dd>
				<dt>[4] Page 567</dt>
				<dd>Change <tt>se.setCause(e)</tt> to       <tt>se.<strong>init</strong>Cause(e)</tt><br /></dd>
				<dt>[4] Page 571</dt>
				<dd>Change the numbers after <tt>StackTraceTest.java:</tt> from 8 23 / 8       14 23 / 8 14 14 23 to 17 33 / 17 23 33 / 17 23 23 33<br /></dd>
				<dt>[6] Page 602</dt>
				<dd>Change<pre>java -Dcom.sun.management.jmxremote MyProgram.java</pre>to<pre>java -Dcom.sun.management.jmxremote MyProgram</pre></dd>
				<dt>[6] Page 604</dt>
				<dd>Change <tt>void addXxxListener(XxxEvent)</tt> to <tt>void       addXxxListener(<strong>XxxListener</strong>)</tt>.</dd>
				<dt>[4] Page 615</dt>
				<dd>Change "displays all instance fields of the <tt>evt</tt> variable"       to "displays all instance fields of the <tt>ev<strong>en</strong>t</tt>       variable"</dd>
				<dt>[4] Page 630</dt>
				<dd>In the second line of Table 12-2, change       b<sub>17</sub>a<sub>16</sub>a<sub>15</sub>... to       b<sub>17</sub><strong>b</strong><sub>16</sub>a<sub>15</sub>...</dd>
				<dt>[6] Page 632</dt>
				<dd>Change
“The advantage of having the RandomAccessFile class implement both
DataInput and DataOutput is that this lets you use or write methods
whose argument types are the DataInput and DataOutput interfaces.” to
“The <tt>RandomAccessFile</tt> class       implements both <tt>DataInput</tt> and <tt>DataOutput</tt>. It is a good       idea to use these interfaces for method parameters.”</dd>
				<dt>[4] Page 634</dt>
				<dd>Change <tt>Set&lt;String, CharSet&gt;</tt> to       <tt><strong>Map</strong>&lt;String, CharSet&gt;</tt>.</dd>
				<dt>[5] Page 639</dt>
				<dd>In the API description for <tt>CharBuffer decode(ByteBuffer       buffer)</tt>, change "decodes the given character sequence ..." to       "decodes the given <strong>byte</strong> sequence"</dd>
				<dt>[4] Page 658</dt>
				<dd>In the second line from the bottom, change <tt>long int nbytes</tt>       to <tt>long nbytes</tt>.<br /></dd>
				<dt>[4] Page 660<br /></dt>
				<dd>Lines 76, 77 of the code should be<br /><tt>      Raises the salary of this       employee.<br />       @param byPercent the       percentage of the raise</tt><br /></dd>
				<dt>[4] Page 667</dt>
				<dd>Change "The <tt>java.util.Date</tt> class defines its own       <tt>readObject</tt>/<tt>writeObject</tt> methods" to "The serializable       <tt>java.util.Date</tt> class defines its own       <tt>writeObject</tt> method". (The wording in the book was       correct, but it confused some readers into thinking that <tt>Date</tt>       is externalizable.)<br /></dd>
				<dt>[4] Page 688</dt>
				<dd>In the documentation for <tt>createNewFile</tt>, change       "automatically creates" to "<strong>atom</strong>ically creates".</dd>
				<dt>[4] Page 713</dt>
				<dd>In the second line of the section <strong>Generic Code and the Virtual       Machine</strong>, change "was even able compile" to "was even able <strong>to</strong>       compile". <br /></dd>
				<dt>[4] Page 719</dt>
				<dd>In the third line from the top, change <tt>new       Pair&lt;String&gt;(10)</tt> to <tt>new       Pair&lt;String&gt;<strong>[</strong>10<strong>]</strong></tt></dd>
				<dt>[4] Page 720</dt>
				<dd>In the tenth line from the bottom, change <br /></dd>
				<dd>
						<pre>
								<tt>Pair&lt;Employee&gt; = ArrayAlg...</tt>
						</pre>
				</dd>
				<dd>to <br /><pre>Pair&lt;Employee&gt; <strong>result</strong> = ArrayAlg...</pre></dd>
				<dt>[6] Page 723</dt>
				<dd>Change<br /><tt>void set(? super Manager)<br />? super Manager       get()<br /></tt>to<br /><tt>void set<strong>First</strong>(? super Manager)<br />?       super Manager get</tt><tt><strong>First</strong></tt><tt>()</tt></dd>
				<dt>[6] Page 723</dt>
				<dd>Change "with any <tt>Manager</tt> object (or a subtype such as       <tt>Executive</tt>), but not with an <tt>Employee</tt>" to "with any       value of type <tt>Manager</tt>, <tt>Employee</tt>, or <tt>Object</tt>,       but not with a subtype value such as <tt>Executive</tt>."</dd>
				<dt>[6] Page 726</dt>
				<dd>Change
“Of course, in this case, we were not compelled to use a wildcard—there
is nothing wrong with using a type parameter, as in the <tt>swapHelper</tt> method.” to “Of course, in this       case, we were not compelled to use a wildcard. We could have directly       implemented <tt>&lt;T&gt; void swap(Pair&lt;T&gt; p)</tt> as a generic       method without wildcards.”</dd>
				<dt>[4] Page 735</dt>
				<dd>Add an entry<br /><table style="text-align: left; width: 50%;" border="1" cellpadding="2" cellspacing="2"><tbody><tr><td style="vertical-align: top;"><span style="font-family: monospace;">enum</span></td><td style="vertical-align: top;">an enumerated type</td><td style="vertical-align: top;">3</td></tr></tbody></table></dd>
				<dt>[6] Page 743</dt>
				<dd>Change "<tt>Boolean</tt>, 42, 46, 186, 735" to two entries       "<tt>boolean</tt>, 42, 46, 735" and "<tt>Boolean</tt>, 186"</dd>
				<dt>[6] Page 760</dt>
				<dd>Change "true or false, <em>see</em><tt>Boolean</tt>" to "true or       false, <em>see</em><tt>boolean</tt>"</dd>
		</dl>
		<h3>Seventh Edition Volume 2 <span style="font-weight: bold;"></span>(JDK     5.0)<span style="font-weight: bold;"></span><a name="CJ7V2"></a><br /></h3>
		<dl>
				<dt>[3] Page xvii</dt>
				<dd>In the second line from the bottom, change <strong>Example 5-8</strong> to       <strong>Example 5-12</strong><br /></dd>
				<dt>[4] Page 3</dt>
				<dd>Change "inside the <tt>move</tt> method of the <tt>Ball</tt> class."       to "inside the <tt>addBall</tt> method of the <tt>BounceFrame</tt>       class".</dd>
				<dt>Page 12 BounceThread.java</dt>
				<dd>Remove these lines:<pre>203. public static final int STEPS = 1000;<br />204. public static final int DELAY = 3;</pre></dd>
				<dt>[3] Page 19</dt>
				<dd>Change "of its parent thread, that is, the thread that started it"       to "of the thread that constructed it"<br /></dd>
				<dt>[2] Page 30</dt>
				<dd>Change
"You must make sure that the thread cannot be interrupted between the
test and the insertion." to "You must make sure that <strong>no       other thread can modify the balance</strong> between the test and the       <strong>transfer action</strong>."</dd>
				<dt>[2] Page 40</dt>
				<dd>Remove the first four lines after <em><strong>Synchronized Blocks</strong></em>       "However, a Java object ... only one condition". <br /></dd>
				<dt>[2] Page 41</dt>
				<dd>Apply boldface to <tt>synchronized (lock)</tt> and remove it from       <tt>System.out.println(. . .)</tt><br /></dd>
				<dt>[2] Page 42</dt>
				<dd>Change $1,200 to $200 and $1,300 to $300</dd>
				<dt>[2] Page 43</dt>
				<dd>In Figure 1-6, change 1200 to 200 and 1300 to 300<br /></dd>
				<dt>[3] Page 49</dt>
				<dd>Change "The call <tt>Object head = q.poll(...)</tt> returns       <tt>true</tt> for 100 milliseconds ..." to "The call <tt>Object head =       q.poll(...)</tt> tries for 100 milliseconds ..."<br /></dd>
				<dt>[2] Page 64</dt>
				<dd>In the code just above the API notes, change <tt>taks.size()</tt> to       <tt>tasks.size()</tt>.</dd>
				<dt>[4] Page 100</dt>
				<dd>In the API notes for the <tt>remove</tt> method of       <tt>java.util.List&lt;E&gt;</tt>, change "removes and returns an element       at the specified position" to "removes and returns <strong>the</strong> element at       the specified position"</dd>
				<dt>[4] Page 100</dt>
				<dd>In the API notes for <tt>java.util.List&lt;E&gt;</tt>, add the       following before <tt>E set(int i, E element)</tt>:<ul><li><tt>E get(int i)</tt><br />returns the element at the specified           position.</li></ul></dd>
				<dt>Page 110</dt>
				<dd>Change "construct a tree set" and "constructs a tree set" to       "constructs a priority queue".</dd>
				<dt>[3] Page 130 Code line 98</dt>
				<dd>Change <br /><pre>return offset &lt; elements.length;</pre>to<br /><pre>return offset &lt; count; </pre></dd>
				<dt>[4] Page 152, 153 ThreadedEchoServer.java</dt>
				<dd>Remove lines 43, 86. Change the following lines:<pre>22. Runnable r = new ThreadedEchoHandler(incoming);<br />44. public ThreadedEchoHandler(Socket i)<br />47. incoming = i;</pre></dd>
				<dt>[4] Page 166</dt>
				<dd>In the API note of <tt>void setConnectTimeout(int       timeout)</tt>/<tt>int getConnectTimeout()</tt>, change "...the       <tt>read</tt> method of the associated input stream..." to "...the       <strong><tt>connect</tt></strong> method of the associated input stream...". In       the API note of <tt>void setReadTimeout(int timeout)</tt>/<tt>int       getReadTimeout()</tt>, change "...the <tt>connect</tt> method of the       associated input stream..." to "...the <strong><tt>read</tt></strong> method of       the associated input stream...".</dd>
				<dt>Page 175</dt>
				<dd>The <tt>Scanner</tt> class wraps the       <tt>InterruptedIOException</tt>. For greater clarity,       change<br /><tt>Scanner in = new Scanner(s.getInputStream()); String       line = in.nextLine();</tt><br />to <br /><tt>InputStream in =       s.getInputStream();</tt><tt>// </tt>read from <tt>in<br /></tt></dd>
				<dt>[2] Page 229</dt>
				<dd>Change "gets a description of all tables in a catalog..." to       "<strong>returns</strong> a description of all tables in a catalog..."</dd>
				<dt>[2] Page 229</dt>
				<dd>Change "The <tt>catalog</tt> and <tt>schema</tt> parameters..." to       "The <tt>catalog</tt> and <tt>schema<strong>Pattern</strong></tt>       parameters..."</dd>
				<dt>[3] Page 240</dt>
				<dd>Change<br /><pre>stat.releaseSavepoint(svpt) <br /></pre>to<br /><pre><strong>conn</strong>.releaseSavepoint(svpt)</pre></dd>
				<dt>[2] Page 244</dt>
				<dd>In the last two rectangles in the bottom row of Figure 4-9, change       <tt>ou=people</tt> to <tt>ou=<strong>groups</strong></tt><br /></dd>
				<dt>[4] Page 281</dt>
				<dd>
						<tt>Product.java</tt>
is the wrong version. The companion code has the correct version, but
it is too long to fit in its entirety. Use this abbreviated version:<pre>import java.rmi.*;<br /><br />public interface Product extends Remote<br />{ <br />   /**<br />      Gets the description of this product.<br />      @return the product description<br />   */<br />   String getDescription() throws RemoteException;<br /><br />   final int MALE = 1;<br />   final int FEMALE = 2;<br />   final int BOTH = MALE + FEMALE;<br />}<br /></pre></dd>
				<dt>[4] Page 282</dt>
				<dd>
						<tt>ProductImpl.java</tt>
is the wrong version. The companion code has the correct version, but
it is too long to fit in its entirety. Use this abbreviated version:<pre>import java.rmi.*;<br />import java.rmi.server.*;<br /><br />public class ProductImpl extends UnicastRemoteObject implements Product<br />{ <br />   public ProductImpl(String n, int s, int age1, int age2, String h) throws RemoteException<br />   {  <br />      name = n;<br />      ageLow = age1;<br />      ageHigh = age2;<br />      sex = s;<br />      hobby = h;<br />   }<br /><br />   public boolean match(Customer c)<br />   {  <br />      if (c.getAge() &lt; ageLow || c.getAge() &gt; ageHigh)<br />         return false;<br />      if (!c.hasHobby(hobby)) return false;<br />      if ((sex &amp; c.getSex()) == 0) return false;<br />      return true;<br />   }<br /><br />   public String getDescription() throws RemoteException<br />   {  <br />      return "I am a " + name + ". Buy me!";<br />   }<br /><br />   private String name, hobby;<br />   private int ageLow, ageHigh, sex;<br />}<br /></pre></dd>
				<dt>[3] Page 293</dt>
				<dd>Change<br /><pre>name = (String) data.get();; <br /></pre>to<br /><pre>name = (String) data.get();</pre></dd>
				<dt>[4] Page 294, 295</dt>
				<dd>
						<tt>ProductImpl.java</tt>
is the wrong version. The companion code has the correct version, but
it is too long to fit in its entirety. Use this abbreviated version:<pre>import java.io.*;<br />import java.rmi.*;<br />import java.rmi.activation.*;<br /><br />public class ProductImpl<br />   extends Activatable<br />   implements Product<br />{ <br />   /**<br />      Constructs a product implementation<br />      @param id the activation id<br />      @param data the marshalled construction parameter (containing the product name)<br />   */<br />   public ProductImpl(ActivationID id, MarshalledObject data) <br />      throws RemoteException, IOException, ClassNotFoundException<br />   {  <br />      super(id, 0);<br />      name = (String) data.get();<br />      System.out.println("Constructed " + name);<br />   }<br /><br />   public String getDescription() throws RemoteException<br />   {  <br />      return "I am a " + name + ". Buy me!";<br />   }<br /><br />   private String name;<br />}<br /></pre></dd>
				<dt>[4] Page 296</dt>
				<dd>Change<pre>static Remote register(ActivationDescriptor desc)</pre>to<pre>static Remote register(<strong>ActivationDesc</strong> desc)</pre></dd>
				<dt>[4] Page 311</dt>
				<dd>Change<pre>System.out.println(orb.object_to_string(impl));</pre>to<pre>System.out.println(orb.object_to_string(<strong>ref</strong>));</pre></dd>
				<dt>[2] Page 334</dt>
				<dd>Remove the line <br /><pre>JLabel label = new JLabel();</pre></dd>
				<dt>[4] Page 391</dt>
				<dd>Add <tt>return this;</tt> as the last line of       <tt>getTableCellRendererComponent</tt> so that the code looks like       this:<pre>class ColorTableCellRenderer extends JPanel implements TableCellRenderer<br />{<br />   public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,<br />      boolean hasFocus, int row, int column)<br />   {<br />      setBackground((Color) value);<br />      if (hasFocus)<br />         setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));<br />      else<br />         setBorder(null);<br /><strong>return this;</strong><br />   }<br />}</pre></dd>
				<dt>[2] Page 425</dt>
				<dd>Change "on the CD" to "in the companion code"</dd>
				<dt>[3] Page 439</dt>
				<dd>In Fig. 6-48, change the callout "minimize icon" to "maximize       icon"<br /></dd>
				<dt>[4] Page 443</dt>
				<dd>Change “The <tt>JDesktopPane</tt>
class has no method to return the selected frame. Instead, you must
traverse all frames ...” to “Traverse all frames ...”. (Actually, you
can get the selected frame by calling <tt>JDesktopPane.getSelectedFrame</tt>, but we need its       <em>index</em>.)</dd>
				<dt>[4] Page 462</dt>
				<dd>Change "... drawn by the <tt>CubicCurve3D</tt> class ..." to "...       drawn by the <tt>CubicCurve<strong>2D</strong></tt> class ..."</dd>
				<dt>[3] Page 462</dt>
				<dd>Change "between 2180 and 180" to "between -180 and 180"<br /></dd>
				<dt>Page 600</dt>
				<dd>Change DndConstants to DnDConstants</dd>
				<dt>[3] Page 664</dt>
				<dd>Example 8-10: ChartBean2BeanInfo.java has the wrong file. The       correct file is<br /><pre>package com.horstmann.corejava;<br /><br />import java.awt.*;<br />import java.beans.*;<br /><br />/**<br /> The bean info for the chart bean, specifying the <br /> icons and the customizer.<br />*/<br />public class ChartBean2BeanInfo extends SimpleBeanInfo<br />{ <br /> public BeanDescriptor getBeanDescriptor()<br /> { <br /> return new BeanDescriptor(ChartBean2.class, ChartBean2Customizer.class);<br /> }<br /><br /> public Image getIcon(int iconType)<br /> { <br /> String name = "";<br /> if (iconType == BeanInfo.ICON_COLOR_16x16) name = "COLOR_16x16";<br /> else if (iconType == BeanInfo.ICON_COLOR_32x32) name = "COLOR_32x32";<br /> else if (iconType == BeanInfo.ICON_MONO_16x16) name = "MONO_16x16";<br /> else if (iconType == BeanInfo.ICON_MONO_32x32) name = "MONO_32x32";<br /> else return null;<br /> return loadImage("ChartBean2_" + name + ".gif");<br /> }<br />}<br /><br /></pre></dd>
				<dt>[4] Page 705</dt>
				<dd>Change
http://bugs.sun.com/developer/bugParade/bugs/4030988.html to
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4030988</dd>
				<dt>[4] Page 772</dt>
				<dd>Change<pre>int outputSize= cipher.getOutputSize(inLength);</pre>to<pre>int outputSize= cipher.getOutputSize(<strong>blockSize</strong>);</pre></dd>
				<dt>[3] Page 788</dt>
				<dd>In the fourth line from the bottom, change "the <tt>java.text</tt>       class" to "the <tt>java.text</tt><strong>package</strong>"</dd>
				<dt>[3] Page 807</dt>
				<dd>In the 4th line from the bottom (excluding the CAUTION note), change       <tt>10.0E7</tt> to <tt>10.0E<strong>8</strong></tt>.<br /></dd>
				<dt>[4] Page 811</dt>
				<dd>Change <tt>java -encoding Big5 Myfile.java</tt> to <tt><strong>javac</strong>       -encoding Big5 Myfile.java</tt>.</dd>
				<dt>[2] Page 833</dt>
				<dd>In line 17 of the code for HelloNative.h, change <tt>ifdef</tt> to       <tt>#ifdef</tt></dd>
				<dt>[3] Page 836</dt>
				<dd>Change <br /> ... a format string <tt>"%w.pf"</tt> ...<br />       to<br /> ... a format string       <tt>"%</tt><em>w</em><tt>.</tt><em>p</em><tt>f"</tt> ...<br /> (<em>w</em> and       <em>p</em> should be Roman italic)<br /></dd>
				<dt>[2] Page 861</dt>
				<dd>Change<br /><pre>jint ThrowNew(JNIEnv *env, jclass clazz, const char msg[])</pre>to<br /><pre>jint ThrowNew(JNIEnv *env, jclass cl, const char msg[])</pre></dd>
				<dt>[3] Page 878</dt>
				<dd>Change <tt>GetSuperClass</tt> to <tt>GetSuper<strong>c</strong>lass</tt></dd>
				<dt>[3] Page 927</dt>
				<dd>Change "XML Style Sheet Transformations" to "Extensible Stylesheet       Language Transformations"<br /></dd>
				<dt>[4] Page 935</dt>
				<dd>In Figure 12-8, change the rightmost “XML Document” to       “Transformed Document (HTML, text, ...)”</dd>
		</dl>
		<p>Thanks
to Joe Abounader, Jerry Agin, Stefan Alfbo, Stefan Badstübner, Alan
Bellanger, Bob Boritz, Eric Cauchon, Davide Cecchetto, Jerry Chen,
Philip Copp, Sandu Crasteti, Bernard Desruisseaux, Edward H. Fabrega,
Gabriel Florit, Angelo Furfaro, Dan Gamel, Mahesh Gopalan, Derek
Haines, Patrick J. Henry, Roger House, Elliott Hughes, Alessandro
Iacopini, Jon Kendall, Sven Kirsimäe, Jim Jennings, Geert Kloosterman,
Jeffrey Knauth, Jason Leasure, Mark Lawrence, Joyce Lee, James
Litchfield, Bingwei Liu, Simon Margulies, Miguel Martinez, Charlie
Mason, Mick McCarthy, Carlos Montejo, Nick Morrott, Michele Nesta,
Elizabeth Norval, Evelyn Obaid, Peter Olsen, Petr Panteleyev, Andrei
Radu, Terry Roe, Avi Schwartz, Jeff Schwarz, Burak Sevindi, Juan Silva,
Russell Smith, Jigar Shah, William So, Thomas Stark, Mel Sumrell, Yves
Thorrez, Joe Toomey, <a href="http://www.mjyonline.com/">Michael J. Young</a>,     Michael Zeidler, and (your name might go here) for their bug reports!</p>
		<br />
		<br />
		<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1695004</p>
<img src ="http://www.blogjava.net/JafeLee/aggbug/131213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-19 10:20 <a href="http://www.blogjava.net/JafeLee/articles/131213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java1.5泛型指南中文版（转载）</title><link>http://www.blogjava.net/JafeLee/articles/130279.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Sat, 14 Jul 2007 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/130279.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/130279.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/130279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/130279.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/130279.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文出处：http://blog.csdn.net/explorers/archive/2005/08/15/454837.aspxJava1.5泛型指南中文版(Java1.5 Generic Tutorial)英文版pdf下载链接：http://java.sun.com/j2se/1.5/pdf/generics-tutoria...&nbsp;&nbsp;<a href='http://www.blogjava.net/JafeLee/articles/130279.html'>阅读全文</a><img src ="http://www.blogjava.net/JafeLee/aggbug/130279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-14 15:30 <a href="http://www.blogjava.net/JafeLee/articles/130279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java Native Method初涉（转载）</title><link>http://www.blogjava.net/JafeLee/articles/129774.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Thu, 12 Jul 2007 02:45:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/129774.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/129774.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/129774.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/129774.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/129774.html</trackback:ping><description><![CDATA[原文出处：<a href="http://blog.csdn.net/hapylong/archive/2007/05/24/1624039.aspx">http://blog.csdn.net/hapylong/archive/2007/05/24/1624039.aspx</a><br /><br /><font size="2">  今天花了两个小时把一份关于什么是Native Method的英文文章好好了读了一遍，以下是我依据原文的理解。<br /><br />一. 什么是Native Method<br />  
简单地讲，一个Native Method就是一个java调用非java代码的接口。一个Native
Method是这样一个java的方法：该方法的实现由非java语言实现，比如C。这个特征并非java所特有，很多其它的编程语言都有这一机制，比如
在C＋＋中，你可以用extern "C"告知C＋＋编译器去调用一个C的函数。<br />   "A native method is a Java method whose implementation is provided by non-java code."<br />   在定义一个native method时，并不提供实现体（有些像定义一个java interface），因为其实现体是由非java语言在外面实现的。，下面给了一个示例：    <br />    public class IHaveNatives<br />    {<br />      native public void Native1( int x ) ;<br />      native static public long Native2() ;<br />      native synchronized private float Native3( Object o ) ;<br />      native void Native4( int[] ary ) throws Exception ;<br />    } <br />    这些方法的声明描述了一些非java代码在这些java代码里看起来像什么样子（view）.<br />   
标识符native可以与所有其它的java标识符连用，但是abstract除外。这是合理的，因为native暗示这些方法是有实现体的，只不过这些
实现体是非java的，但是abstract却显然的指明这些方法无实现体。native与其它java标识符连用时，其意义同非Native
Method并无差别，比如native static表明这个方法可以在不产生类的实例时直接调用，这非常方便，比如当你想用一个native
method去调用一个C的类库时。上面的第三个方法用到了native
synchronized，JVM在进入这个方法的实现体之前会执行同步锁机制（就像java的多线程。）<br />    一个native
method方法可以返回任何java类型，包括非基本类型，而且同样可以进行异常控制。这些方法的实现体可以制一个异常并且将其抛出，这一点与java
的方法非常相似。当一个native
method接收到一些非基本类型时如Object或一个整型数组时，这个方法可以访问这非些基本型的内部，但是这将使这个native方法依赖于你所访
问的java类的实现。有一点要牢牢记住：我们可以在一个native
method的本地实现中访问所有的java特性，但是这要依赖于你所访问的java特性的实现，而且这样做远远不如在java语言中使用那些特性方便和
容易。<br />    native
method的存在并不会对其他类调用这些本地方法产生任何影响，实际上调用这些方法的其他类甚至不知道它所调用的是一个本地方法。JVM将控制调用本地
方法的所有细节。需要注意当我们将一个本地方法声明为final的情况。用java实现的方法体在被编译时可能会因为内联而产生效率上的提升。但是一个
native final方法是否也能获得这样的好处却是值得怀疑的，但是这只是一个代码优化方面的问题，对功能实现没有影响。<br />    如果一个含有本地方法的类被继承，子类会继承这个本地方法并且可以用java语言重写这个方法（这个似乎看起来有些奇怪），同样的如果一个本地方法被fianl标识，它被继承后不能被重写。<br />  
本地方法非常有用，因为它有效地扩充了jvm.事实上，我们所写的java代码已经用到了本地方法，在sun的java的并发（多线程）的机制实现中，许
多与操作系统的接触点都用到了本地方法，这使得java程序能够超越java运行时的界限。有了本地方法，java程序可以做任何应用层次的任务。<br /><br /><br />二.为什么要使用Native Method<br />   java使用起来非常方便，然而有些层次的任务用java实现起来不容易，或者我们对程序的效率很在意时，问题就来了。<br />   与java环境外交互：<br />  
有时java应用需要与java外面的环境交互。这是本地方法存在的主要原因，你可以想想java需要与一些底层系统如操作系统或某些硬件交换信息时的情
况。本地方法正是这样一种交流机制：它为我们提供了一个非常简洁的接口，而且我们无需去了解java应用之外的繁琐的细节。<br />   与操作系统交互：<br />  
JVM支持着java语言本身和运行时库，它是java程序赖以生存的平台，它由一个解释器（解释字节码）和一些连接到本地代码的库组成。然而不管怎
样，它毕竟不是一个完整的系统，它经常依赖于一些底层（underneath在下面的）系统的支持。这些底层系统常常是强大的操作系统。通过使用本地方
法，我们得以用java实现了jre的与底层系统的交互，甚至JVM的一些部分就是用C写的，还有，如果我们要使用一些java语言本身没有提供封装的操
作系统的特性时，我们也需要使用本地方法。<br />    Sun's Java<br />   
Sun的解释器是用C实现的，这使得它能像一些普通的C一样与外部交互。jre大部分是用java实现的，它也通过一些本地方法与外界交互。例如：类
java.lang.Thread 的
setPriority()方法是用java实现的，但是它实现调用的是该类里的本地方法setPriority0()。这个本地方法是用C实现的，并被
植入JVM内部，在Windows 95的平台上，这个本地方法最终将调用Win32 SetPriority()
API。这是一个本地方法的具体实现由JVM直接提供，更多的情况是本地方法由外部的动态链接库（external dynamic link
library）提供，然后被JVM调用。<br /><br /><br />三.JVM怎样使Native Method跑起来：<br />   
我们知道，当一个类第一次被使用到时，这个类的字节码会被加载到内存，并且只会回载一次。在这个被加载的字节码的入口维持着一个该类所有方法描述符的
list，这些方法描述符包含这样一些信息：方法代码存于何处，它有哪些参数，方法的描述符（public之类）等等。<br />   
如果一个方法描述符内有native，这个描述符块将有一个指向该方法的实现的指针。这些实现在一些DLL文件内，但是它们会被操作系统加载到java程
序的地址空间。当一个带有本地方法的类被加载时，其相关的DLL并未被加载，因此指向方法实现的指针并不会被设置。当本地方法被调用之前，这些DLL才会
被加载，这是通过调用java.system.loadLibrary()实现的。<br />   <br />   最后需要提示的是，使用本地方法是有开销的，它丧失了java的很多好处。如果别无选择，我们可以选择使用本地方法。<br /></font><br /><img src ="http://www.blogjava.net/JafeLee/aggbug/129774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-12 10:45 <a href="http://www.blogjava.net/JafeLee/articles/129774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中native方法的使用（转载）</title><link>http://www.blogjava.net/JafeLee/articles/129773.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Thu, 12 Jul 2007 02:44:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/129773.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/129773.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/129773.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/129773.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/129773.html</trackback:ping><description><![CDATA[原文出处：<a href="http://blog.csdn.net/hapylong/archive/2007/05/24/1624120.aspx">http://blog.csdn.net/hapylong/archive/2007/05/24/1624120.aspx</a><br /><p><font size="2">Java不是完美的，Java的不足除了体现在运行速度上要比传统的C++慢许多之外，Java无法直接访问到操作系统底层（如系统硬件等)，为此Java使用native方法来扩展Java程序的功能。<br />　　可以将native方法比作Java程序同Ｃ程序的接口，其实现步骤：<br />　　１、在Java中声明native()方法，然后编译；<br />　　２、用javah产生一个.h文件；<br />　　３、写一个.cpp文件实现native导出方法，其中需要包含第二步产生的.h文件（注意其中又包含了JDK带的jni.h文件）；<br />　　４、将第三步的.cpp文件编译成<nobr>动态</nobr>链接库文件；<br />　　５、在Java中用System.loadLibrary()方法加载第四步产生的动态链接库文件，这个native()方法就可以在Java中被访问了。 </font></p><p><font size="2"> </font></p><div class="postTitle"><font size="2">JAVA本地方法适用的情况 </font></div><div class="postText"><p><font size="2">1.为了使用<nobr>底层</nobr>的<nobr>主机</nobr>平台的某个<nobr>特性</nobr>，而这个特性不能通过JAVA API访问</font></p><p><font size="2">2.为了访问一个老的系统或者使用一个已有的库，而这个系统或这个库不是用JAVA编写的</font></p><p><font size="2">3.为了加快程序的性能，而将一段时间敏感的代码作为本地方法实现。</font></p><p><font size="2"> </font></p><p><font size="2">首先写好JAVA文件<br /> /*<br />  * Created on 2005-12-19 Author shaoqi<br />  */<br /> package com.hode.hodeframework.modelupdate;</font></p><p><font size="2"> public class CheckFile<br /> {<br />     public native void displayHelloWorld();</font></p><p><font size="2">     static<br />     {<br />  System.loadLibrary("test");<br />     }</font></p><p><font size="2">     public static void main(String[] args) {<br />        new CheckFile().displayHelloWorld(); <br />     }<br /> }<br />然后根据写好的文件编译成CLASS文件<br />然后在classes或bin之类的class<nobr>根目录</nobr>下执行javah -jni com.hode.hodeframework.modelupdate.CheckFile，<br /> 就会在根目录下得到一个com_hode_hodeframework_modelupdate_CheckFile.h的文件<br />然后根据头文件的内容编写com_hode_hodeframework_modelupdate_CheckFile.c文件<br /> #include "CheckFile.h"<br /> #include <jni.h></jni.h><br /> #include <stdio.h></stdio.h></font></p><p><font size="2"> JNIEXPORT void JNICALL Java_com_hode_hodeframework_modelupdate_CheckFile_displayHelloWorld(JNIEnv *env, jobject obj)<br /> {<br />     printf("Hello world!\n");<br />     return;<br /> }<br />之后<nobr>编译</nobr>生成DLL文件如“test.dll”，名称与System.loadLibrary("test")中的名称一致<br /> vc的编译方法：cl -I%java_home%\include -I%java_home%\include\win32 -LD com_hode_hodeframework_modelupdate_CheckFile.c -Fetest.dll<br />最后在运行时加参数-Djava.library.path=[dll存放的路径]</font></p></div><br /><img src ="http://www.blogjava.net/JafeLee/aggbug/129773.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-12 10:44 <a href="http://www.blogjava.net/JafeLee/articles/129773.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java native 修饰符/保留字 (转载）</title><link>http://www.blogjava.net/JafeLee/articles/129766.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Thu, 12 Jul 2007 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/129766.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/129766.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/129766.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/129766.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/129766.html</trackback:ping><description><![CDATA[原文出处：<a href="http://www.80x86.cn/article.asp?id=1448">http://www.80x86.cn/article.asp?id=1448</a><br /><br />简单的说, native的方法是java调用java外部实验室的函数, 所以, 使用了native, 函数你不用实现, 只要一个 ; 就可以了<br />下面一个详细的介绍<br /><h3 align="center"><font color="#000000"><font size="+2">CONTENTS<a name="CONTENTS"></a></font></font></h3><ul><li><a href="http://www.80x86.cn/article.asp?id=1448#WhatIsaNativeMethod">What Is a Native Method?</a></li><li><a href="http://www.80x86.cn/article.asp?id=1448#UsesforNativeMethods">Uses for Native Methods</a></li><li><a href="http://www.80x86.cn/article.asp?id=1448#BenefitsandTradeOffs">Benefits and Trade-Offs</a></li><li><a href="http://www.80x86.cn/article.asp?id=1448#HowDoesThisMagicWork">How Does This Magic Work?</a></li><li><a href="http://www.80x86.cn/article.asp?id=1448#Summary">Summary</a></li></ul><hr /><p>The goal for this chapter is to introduce you to Java's native
methods. If you are new to Java, you may not know what native methods
are, and even if you are an experienced Java developer, you may not
have had a reason to learn more about native methods. At the conclusion
of this chapter you should have a better understanding of what native
methods are, when and why you may want to use them, and the
consequences of using them. You should also have a basic understanding
of how native methods work. You will then be more than ready to tackle
the next three chapters, which dive into the nitty-gritty details of
Java's Native Methods. </p><h2><a name="WhatIsaNativeMethod"><b><font color="#ff0000" size="5">What Is a Native  Method?</font></b></a></h2><p>Simply put, a native method is the Java interface to non-Java code.
It is Java's link to the "outside world." More specifically, a native
method is a Java method whose implementation is provided by non-Java
code, most likely C (see Figure 30.1). This feature is not special to
Java. Most languages provide some mechanism to call routines written in
another language. In C++, you must use the <tt>extern "C" </tt><font face="MCPdigital-I" size="1">stmt</font> to signal that  the C++ compiler is making a call to C functions. It is common to see the  qualifier <tt>pascal</tt>
in many C compilers to signal that the calling convention should be
done in a Pascal convention, rather than a C convention. FORTRAN and
Pascal have similar facilities, as do most other languages. </p><p><a href="http://www.80x86.cn/f30-1.gif"><b>Figure 30.1 : </b><i>A native method is a Java method  whose implementation is provided by non-java code.</i></a></p><p>In Java, this is done via native methods. In your Java class, you
mark the methods you wish to implement outside of Java with the <tt>native</tt> method  modifier-much like you would use the<tt> public</tt> or <tt>static</tt>
modifiers. Then, rather than supplying the method's body, you simply
place a semicolon in its place. As an example, the following class
defines a variety of native methods: </p><blockquote><tt>public class IHaveNatives<br />{<br /></tt> <tt> native public void  Native1( int x ) ;<br />  native static public long Native2()  ;<br /></tt> <tt> native synchronized private float Native3( Object o )  ;<br />  native void Native4( int[] ary ) throws Exception ;<br />}</tt></blockquote><p>This sample class shows a number of possible native methods. As you
may have noticed, native methods look much like any other Java method,
except a single semicolon is in the place of the method body.
Naturally, the body of the method is implemented outside of Java. What
you basically define is the interface into this <i>external</i> method. This method declaration describes the Java view of  some foreign code.  </p><p>The only thing special about this declaration is that the keyword  <tt>native</tt> is used as a modifier. Every other Java method modifier can be  used along with <tt>native</tt>, except <tt>abstract</tt>. This is logical,  because the <tt>native</tt> modifier implies that an implementation exists, and  the <tt>abstract</tt>
modifier insists that there is no implementation. Your native methods
can be static methods, thus not requiring the creation of an object (or
instance of a class). This is often convenient when using native
methods to access an existing C-based library. Naturally, native
methods can limit their visibility with the <tt>public</tt>, <tt>private</tt>, <tt>private  protected</tt>, <tt>protected</tt>, or unspecified <i>default </i>access. Native  methods can also be <tt>synchronized</tt> (<a href="http://www.80x86.cn/ch7.htm">see Chapter 7</a>,  "Concurrency and Synchronization"). In the case of a <tt>synchronized</tt>
native method, the Java VM will perform the monitor locking prior to
entering the native method implementation code. So, as in Java, the
developer is not burdened with doing the actual monitor locking and
unlocking. </p><p>The example uses a variety (although not all) of types. This is
because a native method can be passed any Java type. There is no
special procedure within the Java code to pass data to the native
method. However, the developer of native methods must be careful that
his native methods behave properly when manipulating Java datatypes.
Native methods do not undergo the same kinds of checking as a Java
method, and they can easily corrupt a Java datatype if care is not
taken (<a href="http://www.80x86.cn/ch31.htm">see Chapter 31</a>, "The Native Method  Interface").  </p><p>A native method can accept and return any of the Java
types-including class types. Of course, the power of exception handling
is also available to native methods. The implementation of the native
method can create and throw exceptions similar to a Java method. When a
native method receives complex types, such as class types (such as <tt>Object</tt> in the example) or array types (such as the  <tt>int[]</tt>
in the example), it has access to the contents of those types. However,
the method used to access the contents may vary depending on the Java
implementation being used. The major point to remember is that you can
access all the Java features from your native implementation code, but
it may be implementation-dependent and will surely not be as convenient
or easy as it can be done from Java. </p><p>The presence of native methods does not affect how other classes
call those methods. The caller does not even realize it is calling a
native method, so no special code is generated, and the calling
convention is the same as for any other method-the calling depends on
the method being virtual or static. The Java virtual machine will
handle all the details to make the call in the native method
implementation. One minor exception may be with the methods marked with
the <tt>final</tt> modifier. The Java implementation may take advantage of a  <tt>final</tt> method and choose to inline its code. It would be doubtful that  this could be achieved with a native <tt>final</tt>
method, but this is an optimization issue, not one of functionality.
When a class containing native methods is subclassed, the subclass will
inherit the native method and also will have the capability of
overriding the native method-even with a Java method (that is, the
overridden method can be implemented in Java). If a native method is
also marked with the <tt>final</tt> modifier, a subclass is still prevented  from overriding it.  </p><p>Native methods are very powerful, because they effectively extend
the Java virtual machine. In fact, your Java code already uses native
methods. In the current implementation from Sun, native methods are
used in many places to interface to the underlying operating system.
This enables a Java program to go beyond the confines of the Java
Runtime. With native methods, a Java program can virtually do any
application level task. </p><h2><a name="UsesforNativeMethods"><b><font color="#ff0000" size="5">Uses for Native  Methods</font></b></a></h2><p>Java is a wonderful language to use. However, there are times when
you either must interface with existing code, can't express the task in
Java, or need the absolute best performance. </p><h3><b>Accessing Outside the Java Environment</b></h3><p>There are times where a Java application (or applet) <i>must</i>
communicate with the environment outside of Java. This is, perhaps, the
main reason for the existence of native methods. For starters, the Java
implementation will need to communicate with the underlying system.
That underlying system may be an operating system such as Solaris or
Win32, or it may be a Web browser, or it may be custom hardware, such
as a PDA, Set-top-device, and so forth. Regardless of what is under
Java, there must be a mechanism to communicate with that system. At
some point in a Java program, there will be that point where Java meets
the outside world, an interface between Java and non-Java worlds.
Native methods provide a simple clean approach to providing this
interface without burdening the rest of the Java application with
special knowledge. </p><h4><b>Accessing the Operating System</b></h4><p>The Java virtual machine describes a system that the Java program
can rely on to be there. This virtual machine supports the Java
Language and its runtime library. It may be composed of an interpreter
or can be libraries linked to native code. Regardless of its form, it
is not a complete system and often relies on an existing system
underneath to provide a lot of support. More than likely, a
full-fledged operating system, such as Solaris or Win32, resides
beneath it. The use of native methods enables the Java Runtime to be
written in Java yet have access to the underlying operating system, or
even the parts of the Java virtual machine that may be written in a
language such as C. Further, if a Java feature does not encapsulate an
operating system feature needed by an application, native methods can
be used to access this feature. </p><h4><b>Embedded Java</b></h4><p>It is conceivable to see a Java virtual machine embedded inside
another program. Several WWW browsers come to mind. Perhaps this
enclosing program is not implemented in Java. The Java Runtime may need
to access the enclosing program for services to support the Java
environment. Once again, native methods provide a clean interface for
this access to the surrounding program. Furthermore, the vendor of the
program may wish to expose some features of the program to a Java
applet. The vendor would simply need to create a set of Java classes
containing native methods, which provide the interface for the Java
application into the program. The native method implementation would
then be the "glue" between the Java applet and the internals of the
enclosing program. </p><h4><b>Custom Hardware</b></h4><p>Another important possible application of native methods being used
to access a non-Java world is providing Java programs access to custom
hardware. Perhaps a Java virtual machine is running within a PDA or
Set-Top-Device. A lot of what would normally be in an operating system
may exist in hardware or software embedded in ROM, or other custom chip
sets. Another possibility is that a computer may be equipped with a
dedicated graphics card. It would be ideal to have Java make use of the
graphics hardware. A set of Java classes with native methods defined
would provide the Java program access to these features. </p><h4><b>Sun's Java</b></h4><p>In the current implementation from Sun, the Java interpreter is
written in C and can thus talk to the outside environment as any normal
C program can. A majority of the Java Runtime is written in Java and
may make calls into the interpreter or directly to the outside
environment, all via native methods. The application deals mostly with
the Java Runtime, but it may also talk to the outside environment via
native methods. For example in the class <tt>java.lang.Thread</tt> the <tt>setPriority()</tt> method is implemented in  Java but calls the method <tt>setPriority0()</tt>, which is a native method in  the <tt>Thread</tt>
class. This native method is implemented in C and resides within the
Java virtual machine itself. On the Windows 95 platform this native
method will then call (eventually) the Win32 <tt>SetPriority()</tt>
API. This is an example where the native method implementation was
provided by the Java virtual machine directly. In most cases the native
method implementation resides in an external dynamic link library
(discussed in a following section), but the call still goes through the
Java virtual machine. </p><h3><b>Performance</b></h3><p>Another major reason for native methods is performance. The Java
language trades some performance for features like its dynamic nature,
garbage collecting, and safety. Some Java implementations, like the
current crop, may be interpreters, which also add extra overhead. The
lost performance can be small as the implementation technology for Java
systems improve, but until then and even after there may always be a
small performance overhead for certain functionality a Java program may
need. This functionality can be pushed down into a native method. That
native method can then be implemented efficiently at the native lower
level of the system on which the Java virtual machine is running. Once
at the native implementation level, the developer can use the
best-suited language, such as C or even assembler. In this way, maximum
performance can be achieved in those specific areas while the bulk of
the application is done within the safe and robust Java virtual
machine. One area where you may choose to implement some parts of an
application in native methods is time-intensive computations, such as
graphics rendering, simulation models, and so forth. </p><h3><b>Accessing Existing Libraries</b></h3><p>The fact that Java is targeted at the production of platform-neutral
code means that the current implementations may not access system
features that you may need. An example is a database engine. If you
need to, you can use the native method facility to provide your own
interface to such libraries. Further, you may want to use Java to write
applications that use existing in-house libraries. Again, the use of
native methods enables you to make such an interface. This enables you
to leverage off your existing code base as well as gradually introduce
Java-based applications among your other applications coded in an older
language. </p><h2><a name="BenefitsandTradeOffs"><b><font color="#ff0000" size="5">Benefits and  Trade-Offs</font></b></a></h2><p>The presense of native methods offers many benefits, the biggest
being the extension of Java power. However, there is always a downside
to all good things, and native methods definitely have their downsides.
Depending on what the goals of your application are, the downsides may
not be that terrible. Foremost is the fact that, by definition, the use
of native methods defeats several of Java's main goals: platform
neutrality, system safety, and security. </p><p>Some of Java's attractive features help minimize the downsides,
however. The best feature of all is that Java is such a nice language
to develop in you won't want to use native methods unless you have to. </p><h3><b>Platform Neutrality</b></h3><p>Because a native method is implemented in a foreign language, the
platform neutrality is limited to the language being used. Most likely,
native methods are implemented in C or C++. Although those languages
have standards, these standards leave a lot of room for
implementation-defined attributes (even compilers on the same system
may differ), so your mileage may vary. If the native method accesses
the underlying system, you are tying your implementation to that
system. For example, the file systems of UNIX and Win32 have some
differences. There may even be differences between flavors of UNIX and
Win32 (Win95 and WinNT are not identical). Once again, you may
sacrifice your platform neutrality with your native method. This may
cause you to have to support a limited number of platforms (rather than
<i>all</i> Java platforms). Further, for each platform you choose to
support, you may (probably will) have to implement several flavors of
the native method. </p><p>The Java language and runtime provide a number of features that make
applications more robust and safe. Java's memory management,
synchronization features, and lack of address manipulation help prevent
common programming mistakes from slipping through the development and
testing phases of your product. However, once you drop out of Java into
a native method, you are, once again, at the mercy of the language and
system in which you are implementing the native method. If your native
method implemented in C chooses to manipulate an address directly, you
risk corrupting some part of memory, perhaps even the Java virtual
machine itself. </p><h3><b>Security Concerns</b></h3><p>Additionally, the Java Language provides features to aid in the
writing of secure applications. A Java virtual machine is much more
capable of detecting an "evil" Java program than an application in
other languages. Once you drop into a native method, the Java virtual
machine can no longer verify, catch, or prevent the program from
violating the security of the environment in which the Java virtual
machine is running. This is the reason a Java-enabled Web browser
typically does not allow a nontrusted native method to be called. In
today's browsers, a trusted native method must be present on the local
system in a certain location to be executed from an <i>arriving</i>
applet (in other words, one loaded from a remote site). For more
information on security, in general, see Part 6, "Security." For more
information on how security applies to native methods, see <a href="http://www.80x86.cn/ch33.htm">Chapter 33</a>, "Securing Your Native Method  Libraries."  </p><h3><b>System Safety</b></h3><p>Another potential hazard is the fact that a native method is not
isolated. When a native method is entered, it not only accesses the
environment outside the Java virtual machine, it also freely accesses
the Java virtual machine directly. This is a necessary evil. It gives
the native method quite a bit of power and flexibility, because it may
need access to information kept within the virtual machine to do its
job. This flexibility, however, exposes the internals of the Java
virtual machine to the native method. </p><h3><b>Dependence on the Java Implementation</b></h3><p>It should be obvious that the implementation of native methods is
also dependent on the Java implementation itself. This means that the
native methods you write today for use with the Sun implementation of
Java may not work with a Java implementation from another vendor. </p><p>The interface used for the Java virtual machine to call out to
native methods and the interface that native methods use to access the
internal functions and data structures of the Java virtual machine are
not, currently, defined by either the Java Language Specification or
the Java Virtual Machine Specification. A lot of native methods call
back into the Java virtual machine for instantiating new objects,
calling Java methods, throwing Java Exceptions, and so forth. Further,
the method used to lay out Java types is also not defined. So, although
your native method of today knows how to access the fields of an
object, this could be different on the Java virtual machine of
tomorrow. This oversight can be greatly helped if a standard API is
defined for both how a Java program interacts with a native method and
how a native method accesses data within the Java virtual machine. Even
after such an API, implementation-defined behavior will likely still be
present. </p><h3><b>Java to the Rescue!</b></h3><p>Recall that Java helps to minimize the damage of native methods.
When you find yourself in the position that you must use native
methods, you can take advantage of Java's features to help isolate the
usage and perhaps maintain a fair amount of Java's advantages. </p><h4><b>The Java Class System</b></h4><p>Because Java narrows the use of native facilities to within the
confines of a method, it does not affect the design of the program. A
program is still a collection of classes and all classes still
communicate with each other via their defined interface-that is, the
classes' methods. Thus the callers of native methods do not know they
are calling native methods. Because methods are discrete operations on
the data of a specific object, they tend to be small chunks of code.
This implies that native methods tend to be conceptually small, easily
managed, pieces of code. </p><h4><b>Java Still Works for You</b></h4><p>Java will still perform a variety of duties-such as parameter
checking, stack checking, synchronization, and so forth-before entering
the actual native code. It greatly aids the developer in writing
correct native methods. A native method is capable of creating new
objects and calling Java methods, and it can even cause exceptions to
be thrown. In the current implementation from Sun, an exception can be
created by a native method and registered for throwing. When Java
virtual machine gains control back from the native method, usually
because of that method returning, the exception will then be thrown. </p><p>It's a good idea to make your native methods as small as possible
and have them do a specific task. Do the work that needs to be done and
pass the information back into the Java method. It's also wise to have
your Java classes make the native methods private, then provide a
public Java method that will call the private native method. This
enables the Java method to perform error checks and other data
manipulations, freeing your actual native method implementation to
focus on its simple task. </p><h2><a name="HowDoesThisMagicWork"><b><font color="#ff0000" size="5">How Does This  Magic Work?</font></b></a></h2><p>Much of the magic of making native methods work is provided in the
next three chapters. This section provides an introduction, which
neglects many of the details but should give you a good frame of
reference for understanding the following chapters. If you don't really
want to use native methods, but just want a basic understanding this
discussion should satisfy your needs. </p><h3><b>Sun's Implementation</b></h3><p>Due to the lack of a well-defined interface between a Java
implementation and its surrounding environment, the details of writing
native methods will most likely be specific to the implementation of
the Java system you are using. The next sections are based on the
implementation provided by Sun on the Solaris-Sparc and Win32-Intel
platforms. </p><h4><b>Using Dynamic Linking</b></h4><p>Sun's Java implementation interfaces to native methods by using the
dynamic linking capabilities of the underlying operation system. The
Java virtual machine is a complete program, which is already compiled
for its respective platform. The nature of Java enables it easily to
absorb a Java class and execute its behavior. However, for a compiled
native method, things are not so simple. Somehow, the Java virtual
machine must be taught how to call this native method. This is done by
relying on the implementation of native methods to reside in a dynamic
link library, which the operating system magically loads and links into
the process that is running the Java virtual machine. On the Solaris
platform, such a library is often called <i>shared objects</i>, or <i>shared  libraries</i>, or simply <i>dot-so's (.so's)</i>. On Win32 platforms, they are  called <i>dynamic link libraries</i><i>(DLLs)</i>. This chapter uses DLL to  refer to both.  </p><p>Both Solaris and Win32 provide the necessary capabilities to achieve
this dynamic linking. The dynamic linking facilities of both Solaris
and Win32 are similar in concept, but differ in their details. This
chapter does not attempt to describe the two in detail; however, if you
wish to do native method programming, you should understand the
mechanism used by your platform. On Solaris, you can begin by viewing
the manual page on the <tt>dlopen()</tt>  system call, and its relatives. On Win32, start with the help file on  <tt>LoadLibrary()</tt> and its relatives. Further, you should understand the  calling conventions and linking convention used by your compiler.  </p><p>Sometime before a native method is invoked, the Java virtual machine
must be told to find, load, and link the necessary DLLs, which contain
the native method implementations. This is conveniently achieved by
using the static method <tt>java.lang.System.loadLibrary( "mystuff" )</tt>.
It is worth noting here that the name passed is not the actual filename
of the DLL. Java maps the passed name into an expected filename,
appropriate for the underlying system, of the DLL. In the call
described previously, the string <tt>"mystuff"</tt> is mapped to a DLL
named libmystuff.so on Solaris and mystuff.dll on Win32. If you run the
Java program under a debugger, Java conveniently maps the same name <tt>"mystuff"</tt> to <tt>libmystuff_g.so</tt> and <tt>mystuff_g.dll</tt>.
This enables you to supply two versions of the DLL-one with debug
symbols, one without. Java magically finds the right one, dependent on
whether you run under a debugger or not. </p><h4><b>Defining the Calling Convention</b></h4><p>In, essence, Sun defines the method its Java virtual machine will
use to call external functions. In order to dynamically link and call
the implementation of a native method successfully, the Java virtual
machine must know several details. It must know the name of the
function within the DLL (the implementation of the native method) to
locate the symbol and its entry point. It also must know how to call
that function (its return type, number of parameters, and types of
parameters). The Java virtual machine expects the functions to be coded
in C using the calling conventions appropriate for the underlying
architecture (and compiler). </p><p>In simple terms, this means the actual function calls Java makes
into the DLL must be known names; if you are trying to get Java to call
into your existing library, unless your functions magically match the
names Java expects (unlikely), you will usually have glue code, which
sits between Java and your real functions. Java will call the glue
functions<i>,</i> which in turn call in your functions. Alternatively,
you can modify your functions to use the names and parameters Java
expects, thus eliminating this extra call; however, in practice this is
not always feasible, especially when calling existing libraries. Figure
30.2 shows the most likely scenarios of how your code will be
segmented. </p><p><a href="http://www.80x86.cn/f30-2.gif"><b>Figure 30.2 : </b><i>Java's use of Dynamic Link  Libraries.</i></a></p><p>The Sun JDK provides a tool, named <tt>javah</tt>, to help you create your  native method implementation functions. The developer of native methods runs  <tt>javah</tt>, passing it the name of a class. <tt>javah</tt>
emits both a header file (.h) and a code file (.c) containing
information about each native method and relevant type declarations.
The .h file will contain the prototypes of the functions Java will
call, and thus expect to find in the DLL. The .c file will contain
stubs for each function. Thus, the developer needs to fill in only the
details of the functions in the c file and build the DLL appropriately.
</p><h4><b>How the Virtual Machine Makes It Work</b></h4><p>When a class is first used by Java, its class descriptor is loaded into  memory. The <i>class descriptor</i>
can be thought of as a directory for all services provided by the
class-there is only one class descriptor loaded, regardless of how many
instances of that class exist. Among its entries is a list of <i>method descriptors,</i>
which contain information specific to methods, including where the code
is, what parameters they take, and method modifiers. </p><p>If a method descriptor has its native modifier set, the block will
include a pointer to the function that implements that native method.
This function resides in some DLL but will be loaded into the Java
processes address space by the operating system. At the time the class
descriptor with native methods is loaded, the associated DLL does not
have to be loaded, and thus the function pointer will not be set.
Sometime prior to a native method being called, the associated DLL
should be loaded. This is done via a call to <tt>java.system.loadLibrary()</tt>.
When this call is made, Java will find and load the DLL but will still
not resolve symbols; the resolution phase is delayed until the point of
use. At the time of a call to a native method, Java will first check to
see whether the native method implementation function has already been
resolved-that is, its pointer is not <tt>null</tt>. If it has been
previously resolved, the call is performed; otherwise, the resolution
of the symbols is attempted. The resolution is performed by making an
operating system call to see whether the symbol exists in the caller's
address space. This includes the Java process and any DLLs loaded on
its behalf. On Win32, this is done via a <tt>GetProcAddress()</tt> and on Solaris via a <tt>dlsym()</tt> call.   </p><p>If the symbols are correctly resolved, the call is performed as if
the Java virtual machine was making a standard C call to its own
internal functions. If the resolution fails, the exception <tt>java.lang.UnsatisfiedLinkError</tt> will  be thrown at the point of the native method call.  </p><h2><a name="Summary"><b><font color="#ff0000" size="5">Summary</font></b></a></h2><p>You should now have a basic understanding of how native methods
enable a Java program to access the outside environment. Whether that
consists of an operating system, a browser, or your own existing
libraries, your Java code can reach them. It should now be clear that
native methods do not come without some cost. You lose a lot of the
benefits of the Java language. When there is no choice, however, native
methods are there to be used. With the basic understanding of how
native methods work you should be ready to tackle the next chapters,
which provide more in-depth examples of native methods in action, as
well as more tips and tricks to help you. </p><img src ="http://www.blogjava.net/JafeLee/aggbug/129766.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-12 10:35 <a href="http://www.blogjava.net/JafeLee/articles/129766.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Get Acquainted with the New Advanced Features of JUnit 4</title><link>http://www.blogjava.net/JafeLee/articles/127712.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Mon, 02 Jul 2007 16:02:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/127712.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/127712.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/127712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/127712.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/127712.html</trackback:ping><description><![CDATA[
		<table border="0" cellpadding="0" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<div class="articleTitle">Get Acquainted with the New Advanced Features of JUnit 4</div>
										<div class="articleDek">
												<br />Learn
how to migrate from JUnit 3.8 to JUnit 4. Discover version 4's new
features, including extensive use of annotations, and find out the
status on IDE integration. <div><div class="articleAuthor">
						
							by
							Antonio Goncalves
						
						
						
						
						</div></div></div>
								</td>
						</tr>
						<tr>
								<td>
										<img src="http://www.devx.com/assets/dropcaps/3573.gif" />oes anybody need an introduction on JUnit? No? OK, so I'll assume that you know this <a href="http://www.junit.org/index.htm" target="_blank">Java unit testing framework</a>
created by Kent Beck and Erich Gamma and skip the introduction. Instead
I will focus on the migration process from JUnit 3.8 to the latest
version, JUnit 4, and its integration in IDEs and Ant.
<p>JUnit 4 is a completely different API from the versions that came
before it and depends on new features of Java 5.0 (annotations, static
import…). As you'll see, JUnit 4 is <a href="http://www.instrumentalservices.com/index.php?option=com_content&amp;task=view&amp;id=45&amp;Itemid=52" target="_blank">simpler</a>, richer, and easier to use and introduces more flexible initialization and cleanup, timeouts, and parameterized test cases.
</p><p>
Nothing beats a bit of code for clarification. I'll use an example that
I can use to illustrate different test cases throughout the article: a
calculator. The sample calculator is very simple, inefficient, and even
has a few bugs; it only manipulates integers and stores the result in a
static variable. Substract method does not return a valid result,
multiply is not implemented yet, and it looks like there is a bug on
the squareRoot method: It loops infinitely. These bugs will help
illustrate the efficiency of the tests in JUnit 4. You can switch this
calculator on and off and you can clear the result. Here is the code:
</p><pre><code><br />package calc;<br /><br />public class Calculator {<br /><br />    private static int result;          // Static variable where the result is stored<br /><br />    public void add(int n) {<br />        result = result + n;<br />    }<br /><br />    public void substract(int n) {<br />        result = result - 1;          //Bug : should be result = result - n<br />    }<br /><br />    public void multiply(int n) {}     //Not implemented yet<br /><br />    public void divide(int n) {<br />        result = result / n;<br />    }<br /><br />    public void square(int n) {<br />        result = n * n;<br />    }<br /><br />    public void squareRoot(int n) {<br />        for (; ;) ;                    //Bug : loops indefinitely<br />    }<br /><br />    public void clear() {               // Cleans the result<br />        result = 0;<br />    }<br /><br />    public void switchOn() {          // Swith on the screen, display "hello", beep<br />        result = 0;                    // and do other things that calculator do nowadays<br />    }<br /><br />    public void switchOff() { }	     // Display "bye bye", beep, switch off the screen<br /><br />    public int getResult() {<br />        return result;<br />    }<br />}<br /></code></pre><p><br /><br /></p></td>
						</tr>
				</tbody>
		</table>
		<table border="0" cellpadding="0" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<br />
								</td>
						</tr>
						<tr>
								<td>
										<b>Migrating a Test Class</b>
										<br />Now
I'll take a simple test class already written in JUnit 3.8 and migrate
it to JUnit 4. This class has some flaws: It does not test all the
business methods and it looks like there is a bug in the testDivide
method (8/2 is not equal to 5). Because the implementation of multiply
is not ready, its test is written but ignored. <p>
The differences between the two frameworks are highlighted in bold (see Table 1). 
</p><p><b>Table 1. CaculatorTest in JUnit 3.8 and JUnit 4</b><br /></p><table bordercolordark="white" bordercolorlight="black" border="1" cellspacing="0"><tbody><tr><td align="left" bgcolor="#99ccff" valign="top"><b>JUnit 3.8
</b></td><td align="left" bgcolor="#99ccff" valign="top"><b>JUnit 4
</b></td></tr><tr><td align="left" bgcolor="white" valign="top"><pre><code>package junit3; <br /><br />import calc.Calculator; <br />import <b>junit.framework</b>.TestCase; <br /><br /><br /><br /><br />public class CalculatorTest <b>extends TestCase</b> {<br /><br />  private static Calculator calculator = <br />             new Calculator();<br /><br />  @Override<br /><b>protected</b> void <b>setUp</b>() {<br />      calculator.clear();<br />  }<br /><br /><br />  public void <b>testAdd</b>() {<br />    calculator.add(1); <br />    calculator.add(1); <br />    assertEquals(calculator.getResult(), 2); <br />  }<br /><br /><br />  public void <b>testSubtract</b>() {<br />    calculator.add(10); <br />    calculator.subtract(2); <br />    assertEquals(calculator.getResult(), 8); <br />  }<br /><br /><br />  public void <b>testDivide</b>() {<br />    calculator.add(8); <br />    calculator.divide(2); <br /><b>assert calculator.getResult() == 5;</b><br />  }<br /><br />  public void testDivideByZero()  {<br />    try {<br />      calculator.divide(0); <br /><b>fail();</b><br />    } catch (<b>ArithmeticException</b> e) {<br />    }<br />  }<br /><br />  public void <b>notReadyYet</b>TestMultiply() {<br />    calculator.add(10); <br />    calculator.multiply(10); <br />    assertEquals(calculator.getResult(), 100); <br />    }<br />}<br /></code></pre></td><td align="left" bgcolor="white" valign="top"><pre><code>package junit4; <br /><br />import calc.Calculator; <br />import <b>org.junit</b>.Before; <br />import org.junit.Ignore; <br />import org.junit.Test; <br /><b>import static org.junit.Assert.*;</b><br /><br />public class CalculatorTest {<br /><br />  private static Calculator calculator = <br />             new Calculator();<br /><br /><b>@Before</b><br /><b>public</b> void <b>clearCalculator</b>() {<br />    calculator.clear();<br />  }<br /><br /><b>@Test</b><br />  public void <b>add</b>() {<br />    calculator.add(1); <br />    calculator.add(1); <br />    assertEquals(calculator.getResult(), 2); <br />  }<br /><br /><b>@Test</b><br />  public void <b>subtract</b>() {<br />    calculator.add(10); <br />    calculator.subtract(2); <br />    assertEquals(calculator.getResult(), 8); <br />  }<br /><br /><b>@Test</b><br />  public void <b>divide</b>() {<br />    calculator.add(8); <br />    calculator.divide(2); <br />    assert calculator.getResult() == 5; <br />  }<br /><br /><b>@Test(expected = ArithmeticException.class)</b><br />  public void divideByZero() {<br />    calculator.divide(0); <br />  }<br /><br /><br /><b>@Ignore("not ready yet")</b><br />  @Test<br />  public void multiply() {<br />    calculator.add(10); <br />    calculator.multiply(10); <br />    assertEquals(calculator.getResult(), 100); <br />  }<br />}<br /></code></pre></td></tr></tbody></table><br /><p><b>Packages</b><br />
First of all, you can see that JUnit 4 uses <span class="pf">org.junit.*</span> package while JUnit 3.8 uses <span class="pf">junit.framework.*</span>. Of course, for backward compatibility, the JUnit 4 jar file ships with both packages.
</p><p><b>Inheritance</b><br />
Test classes do not have to extend <span class="pf">junit.framework.TestCase</span>
anymore. In fact, they don't have to extend anything. JUnit 4 has
decided to use annotations instead. To be executed as a test case, a
JUnit 4 class needs at least one @Test annotation. For example, if you
write a class with only @Before and @After annotations without at least
one @Test method, you will get an error when trying to execute it: <span class="pf">java.lang.Exception: No runnable methods</span>.
</p><p><b>Assert Methods</b><br />
Because in JUnit 4 a test class doesn't inherit from TestCase (where <span class="pf">assertEquals()</span> methods are defined in JUnit 3.8), you have to use the prefixed syntax (e.g. <span class="pf">Assert.assertEquals()</span>) or, thanks to JDK 5.0, import statically the Assert class. In doing so, you can then use <span class="pf">assertEquals</span> methods exactly the way you have used them previously (e.g. <span class="pf">assertEquals ()</span>).
</p><p>
There are two new assertion methods in JUnit 4. They are used to
compare arrays of objects. Both arrays are equal if each element they
contain is equal.
</p><pre><code><br />public static void assertEquals(String message, Object[] expecteds, Object[] actuals);<br />public static void assertEquals(Object[] expecteds, Object[] actuals);<br /></code></pre>Twelve assertEquals methods have totally disappeared
thanks to the autoboxing of the JDK 5.0. Methods such as
assertEquals(long, long) in JUnit 3.8 use the assertEquals(Object,
Object) in JUnit 4. It is the same for assertEquals(byte, byte),
assertEquals(int, int), and so on. This will help prevent the
antipattern "Using the Wrong Assert" (see <a href="http://www-128.ibm.com/developerworks/opensource/library/os-junit/" target="_blank">http://www-128.ibm.com/developerworks/opensource/library/os-junit/</a> and <a href="http://www.exubero.com/junit/antipatterns.html" target="_blank">http://www.exubero.com/junit/antipatterns.html</a> ).
<p>
A novelty with JUnit 4 is the neat integration of the assert keyword
(divide() method in our example). You can use it as you would use the
assertEquals methods, because they both throw the same exception
(java.lang.AssertionError). JUnit 3.8 assertEquals would throw a
junit.framework.AssertionFailedError. Note that when using assert, you
must specify the –ea parameter to Java; if not, asserts are ignored
(see "<a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html" target="_blank">Programming with Asserts</a>").
</p><p><b>Fixture</b><br />
Fixtures are methods to initialize and release any common objects during tests. In JUnit 3.8 you would use <span class="pf">setUp()</span> for initialization before running each test and then <span class="pf">tearDown()</span>
for cleaning purposes after each test had completed. Both methods are
overridden from the TestCase class and therefore are uniquely defined.
Note that I'm using the Java 5.0 built-in @Override annotation for the
setup method—this annotation indicates that the method declaration is
intended to override the method declaration in a superclass. Instead,
JUnit 4 uses @Before and @After annotations. These methods can be
called by any name (<span class="pf">clearCalculator()</span> in our example). I'll explain more about these annotations later in the article.
</p><p><b>Tests</b><br />
JUnit 3.8 recognizes a test method by analyzing its signature: The
method name has to be prefixed with 'test', it must return void, and it
must have no parameters (e.g. <span class="pf">public void testDivide()</span>).
A test method that doesn't follow this naming convention is simply
ignored by the framework and no exception is thrown, indicating a
mistake has been made.
</p><p>JUnit 4 doesn't use the same conventions. A test method does
not have to be prefixed with 'test' but instead uses the @Test
annotation. As in the previous framework, a test method must return
void and have no parameters. With JUnit 4 this is controlled at runtime
and throws an exception if not respected:
</p><pre><code><br />java.lang.Exception: Method xxx should have no parameters<br />java.lang.Exception: Method xxx should be void<br /></code></pre>The @Test annotation supports the optional expected
parameters. It declares that a test method should throw an exception.
If it doesn't or if it throws a different exception than the one
declared, the test fails. In our example, dividing an integer by zero
should raise an <span class="pf">ArithmeticException</span>.
<p><b>Ignoring a Test</b><br />
Remember that the multiply method is not implemented. However, you
don't want the test to fail, you just want it ignored. How do you
temporarily disable a test with JUnit 3.8? By commenting it or changing
the naming conventions so that the runner doesn't find it. In my
example I used the method name <span class="pf">notReadyYetTestMultiply()</span>.
It doesn't start with 'test' so it won't be recognized. The problem is
that in the middle of thousands of other tests, you might not remember
to rename this method.
</p><p>To ignore a test in JUnit 4 you can comment a method or delete
the @Test annotation (you can't change the naming conventions anymore
or an exception would be thrown). However, the problem will remain: The
runner will not report such a test. You can now add the @Ignore
annotation in front or after @Test. Test runners will report the number
of ignored tests, along with the number of tests that ran and the
number of tests that failed. Note that @Ignore takes an optional
parameter (a String) if you want to record why a test is being ignored.
</p><p><b>Running the Tests</b><br />In JUnit 3.8 you could choose from several
runners: text, AWT, or Swing. JUnit 4 only uses text runners. Remember
the tagline underneath the JUnit logo? "Keep the bar green to keep the
code clean." Well, JUnit 4 will not display any green bar to inform you
that your tests have succeeded. If you want to see any kind of green
you'll need to use <a href="http://junitext.sourceforge.net/" target="_blank">JUnit extensions</a> or an IDE that integrates JUnit such as IDEA or Eclipse"
</p><p>
First, I want to run the JUnit 3.8 test class with the good old <span class="pf">junit.textui.TestRunner</span> (with the –ea parameter to take into account the assert keyword).

</p><pre><code><br />java -ea junit.textui.TestRunner junit3.CalculatorTest<br /><br />..F.E.<br /><br />There was 1 error:<br />1) testDivide(junit3.CalculatorTest)java.lang.AssertionError<br />        at junit3.CalculatorTest.testDivide(CalculatorTest.java:33)<br /><br />There was 1 failure:<br />1) testSubtract(junit3.CalculatorTest)junit.framework.AssertionFailedError: expected:&lt;9&gt; but was:&lt;8&gt;<br />        at junit3.CalculatorTest.testSubtract(CalculatorTest.java:27)<br /><br />FAILURES!!!<br />Tests run: 4,  Failures: 1,  Errors: 1<br /></code></pre>
TestDivide produces an error because assert ensures that 8/2 does not
equal 5. TestSubstract produces a failure because 10-2 should be equal
to 8 but there is a bug in the implementation and it returns 9.
<p>
Now I'll run both classes with the new <span class="pf">org.junit.runner.JUnitCore</span> runner, which acts like a facade for running tests. It can execute JUnit 4 and JUnit 3.8 tests as well as a mixture of both. 

</p><pre><code><br />java –ea org.junit.runner.JUnitCore junit3.CalculatorTest<br />JUnit version 4.1<br /><br />..E.E.<br /><br />There were 2 failures:<br />1) testSubtract(junit3.CalculatorTest)<br />junit.framework.AssertionFailedError: expected:&lt;9&gt; but was:&lt;8&gt;<br />        at junit.framework.Assert.fail(Assert.java:47)<br />2) testDivide(junit3.CalculatorTest)<br />java.lang.AssertionError<br />        at junit3.CalculatorTest.testDivide(CalculatorTest.java:33)<br /><br />FAILURES!!!<br />Tests run: 4,  Failures: 2<br /></code></pre>
***
<pre><code><br />java –ea org.junit.runner.JUnitCore junit4.CalculatorTest<br />JUnit version 4.1<br /><br />...E.EI<br /><br />There were 2 failures:<br />1) subtract(junit4.CalculatorTest)<br />java.lang.AssertionError: expected:&lt;9&gt; but was:&lt;8&gt;<br />        at org.junit.Assert.fail(Assert.java:69)<br />2) divide(junit4.CalculatorTest)<br />java.lang.AssertionError<br />        at junit4.CalculatorTest.divide(CalculatorTest.java:40)<br /><br />FAILURES!!!<br />Tests run: 4,  Failures: 2<br /></code></pre>The first visible difference is that the JUnit version
number is displayed in the console (4.1). The second is that JUnit 3.8
differentiates failures and errors. JUnit 4 makes it simpler by only
using failures. A novelty is the letter "I", which indicates that a
test has been ignored.
<p></p><p><br /><br /></p></td>
						</tr>
				</tbody>
		</table>
		<table border="0" cellpadding="0" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<br />
								</td>
						</tr>
						<tr>
								<td>
										<b>Advanced Tests</b>
										<br />
Now I'll demonstrate some advanced features of JUnit 4. <a href="javascript:showSupportItem('listing1')">Listing 1</a> is a new test class, AdvancedTest, that extends AbstractParent.
<p><b>Advanced Fixture</b><br />Both classes use the new annotations
@BeforeClass and @AfterClass as well as @Before and @After. The main
differences between these annotations are shown in Table 2.
</p><p><b>Table 2. @BeforeClass/@AfterClass vs. @Before/@After</b><br /></p><table bordercolordark="white" bordercolorlight="black" border="1" cellspacing="0"><tbody><tr><td align="left" bgcolor="#99ccff" valign="top"><b>@BeforeClass and @AfterClass
</b></td><td align="left" bgcolor="#99ccff" valign="top"><b>@Before and @After
</b></td></tr><tr><td align="left" bgcolor="white" valign="top">Only one method per class can be annotated.</td><td align="left" bgcolor="white" valign="top">Multiple methods can be annotated. Order of execution is unspecified. Overridden methods are not run.</td></tr><tr><td align="left" bgcolor="white" valign="top">Method names are irrelevant</td><td align="left" bgcolor="white" valign="top">Method names are irrelevant</td></tr><tr><td align="left" bgcolor="white" valign="top">Runs once per class</td><td align="left" bgcolor="white" valign="top">Runs before/after each test method</td></tr><tr><td align="left" bgcolor="white" valign="top">@BeforeClass methods of
superclasses will be run before those of the current class. @AfterClass
methods declared in superclasses will be run after those of the current
class.</td><td align="left" bgcolor="white" valign="top">@Before in superclasses are run before those in subclasses. @After in superclasses are run after those in subclasses. </td></tr><tr><td align="left" bgcolor="white" valign="top">Must be public and static.</td><td align="left" bgcolor="white" valign="top">Must be public and non static.</td></tr><tr><td align="left" bgcolor="white" valign="top">All @AfterClass methods are guaranteed to run even if a @BeforeClass method throws an exception.</td><td align="left" bgcolor="white" valign="top">All @After methods are guaranteed to run even if a @Before or @Test method throws an exception.</td></tr></tbody></table><br /><p>
@BeforeClass and @AfterClass can be very useful if you need to allocate
and release expensive resources only once. In our example the
AbstractParent starts and stops the entire test system using these
annotations on <span class="pf">startTestSystem()</span> and <span class="pf">stopTestSystem()</span>
methods. And it initializes and cleans the system using @Before and
@After. The child class AdvancedTest also uses a mixture of these
annotations.
</p><p>It is not good practice to have System.out.println in your test
code, but in this case it helps to understand the order these
annotations are called. When I run AdvancedTest I get:
</p><pre><code><br />Start test system                //@BeforeClass of parent<br />  Switch on calculator           //@BeforeClass of child<br /><br />    Initialize test system       //First test<br />    Clear calculator<br /><br />    Initialize test system       //Second test<br />    Clear calculator<br />    Clean test system<br /><br />    Initialize test system       //Third test<br />    Clear calculator<br />    Clean test system<br /><br />    Initialize test system       //Forth test<br />    Clear calculator<br />    Clean test system<br /><br />  Switch off calculator          //@AfterClass of child<br />Stop test system                 //@AfterClass of parent<br /></code></pre>

As you can see @BeforeClass and @AfterClass are only called once, meanwhile @Before and @After are called for each test.
<p><b>Timeout Tests</b><br />
In the previous example I wrote a test case for the <span class="pf">squareRoot()</span>
method. Remember that there is a bug in this method which causes it to
loop indefinitely. I want this test to exit after 1 second if there is
no result. That's what the timeout parameter does. This second optional
parameter of the @Test annotation (the first one was expected), causes
a test to fail if it takes longer than a specified amount of clock time
(milliseconds). When I run the test I get:
</p><pre><code><br />There was 1 failure:<br />1) squareRoot(junit4.AdvancedTest)<br />java.lang.Exception: test timed out after 1000 milliseconds<br />        at org.junit.internal.runners.TestMethodRunner.runWithTimeout(TestMethodRunner.java:68)<br />        at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:43)<br /><br />FAILURES!!!<br />Tests run: 4,  Failures: 1<br /></code></pre><p><b>Parameterized Tests</b><br />In Listing 1 I tested the squareRoot
&lt;&lt;it is the square method not the squareRoot&gt;&gt; method by
creating several test methods (square2, square4, square5), which do
exactly the same thing, parameterized by some variables. This
copy/paste technique can now be optimized using a parameterized test
case (see <a href="javascript:showSupportItem('listing2')">Listing 2</a>).
</p><p>
The test case in <a href="javascript:showSupportItem('listing2')">Listing 2</a>
uses two new annotations. When a class is annotated with @RunWith,
JUnit will invoke the class referenced to run the tests instead of the
default runner. To use a parameterized test case, you need to use the
runner <span class="pf">org.junit.runners.Parameterized</span>. To know which parameters to use, the test case needs a public static method (here <span class="pf">data()</span>
but the name is irrelevant) that returns a Collection and is annotated
with @Parameters. You also need a public constructor that takes these
parameters.
</p><p>
When running this class, the output is:

</p><pre><code><br />java org.junit.runner.JUnitCore junit4.SquareTest<br />JUnit version 4.1<br /><br />.......E<br /><br />There was 1 failure:<br />1) square[6](junit4.SquareTest)<br />java.lang.AssertionError: expected:&lt;48&gt; but was:&lt;49&gt;<br />        at org.junit.Assert.fail(Assert.java:69)<br /><br />FAILURES!!!<br />Tests run: 7,  Failures: 1<br /></code></pre>There are seven tests executed (the seven dots '.'), as if
seven individual square methods were written. Note that we have a
failure in our test because the square of 7 is 49, not 48.
<p><b>Suite</b><br />
To run several test classes into a suite in JUnit 3.8 you had to add a <span class="pf">suite()</span>
method to your classes. With JUnit 4 you use annotations instead. To
run the CalculatorTest and SquareTest you write an empty class with
@RunWith and @Suite annotations.
</p><pre><code><br />package junit4;<br /><br />import org.junit.runner.RunWith;<br />import org.junit.runners.Suite;<br /><br />@RunWith(Suite.class)<br />@Suite.SuiteClasses({<br />        CalculatorTest.class,<br />        SquareTest.class<br />        })<br />public class AllCalculatorTests {<br />}<br /></code></pre>

Again, the @RunWith annotation is telling JUnit to use the <span class="pf">org.junit.runner.Suite</span>.
This runner allows you to manually build a suite containing tests from
many classes. The names of these classes are defined in the <span class="pf">@Suite.SuiteClass</span>. When you run this class, it will run CalculatorTest and SquareTest. The output is:

<pre><code><br />java -ea org.junit.runner.JUnitCore junit4.AllCalculatorTests<br />JUnit version 4.1<br /><br />...E.EI.......E<br /><br />There were 3 failures:<br />1) subtract(junit4.CalculatorTest)<br />java.lang.AssertionError: expected:&lt;9&gt; but was:&lt;8&gt;<br />        at org.junit.Assert.fail(Assert.java:69)<br />2) divide(junit4.CalculatorTest)<br />java.lang.AssertionError<br />        at junit4.CalculatorTest.divide(CalculatorTest.java:40)<br />3) square[6](junit4.SquareTest)<br />java.lang.AssertionError: expected:&lt;48&gt; but was:&lt;49&gt;<br />        at org.junit.Assert.fail(Assert.java:69)<br /><br />FAILURES!!!<br />Tests run: 11,  Failures: 3<br /></code></pre><b>Runner</b><br />
It may not be obvious but JUnit 4 uses runners extensively. If @RunWith
is not specified, your class will still be executed with a default
runner (<span class="pf">org.junit.internal.runners.TestClassRunner</span>).
The original Calculator class doesn't explicitly declare a runner, so
therefore it uses the default. A class containing a method with @Test
has a @RunWith by implication. In fact, you could add the following
code to the Calculator class and the output would be exactly the same.
<pre><code><br />import org.junit.internal.runners.TestClassRunner;<br />import org.junit.runner.RunWith;<br /><br />@RunWith(TestClassRunner.class)<br />public class CalculatorTest {<br />...<br />}<br /></code></pre>In the case of the @Parameterized and @Suite I needed a
special runner to execute my test cases. That's why I explicitly
annotated them.
<p></p><p><br /><br /></p></td>
						</tr>
				</tbody>
		</table>
		<table border="0" cellpadding="0" cellspacing="0">
				<tbody>
						<tr>
								<td>
										<br />
								</td>
						</tr>
						<tr>
								<td>
										<b>Tools Integration (or Lack Thereof)</b>
										<br />As
I'm writing this article, JUnit 4 integration in IDEs is not yet
perfect. In fact if you try to run the test classes we’ve just seen,
they will not work in any IDE because they are not recognized as being
test classes. For forward compatibility JUnit 4 comes with an adapter (<span class="pf">junit.framework.JUnit4TestAdapter</span>) that you have to use in a <span class="pf">suite()</span> method. Here is the code you have to add in every class to make them understandable by IDEs, Ant, and JUnit 3.8 text runner:

<pre><code><br />    public static junit.framework.Test suite() {<br />        return new JUnit4TestAdapter(CalculatorTest.class);<br />    }<br /></code></pre><b>Intellij IDEA</b><br />
IDEA 5 does not integrate JUnit 4. We will have to wait for IDEA 6. In
the meantime I've used the early access version (Demetra build 5321).
The parameterized test case didn't work. <a href="javascript:showSupportItem('figure1')">Figure 1</a> shows the CalculatorTest executing (the ignored test is represented with a different icon).

<p></p><table align="center" border="0" cellpadding="3" width="95%"><tbody><tr><td valign="top"><a href="javascript:showSupportItem('figure1')"><img alt="" src="http://assets.devx.com/articlefigs/16496.png" border="0" height="150" width="220" /></a><br /><span class="caption"><a href="javascript:showSupportItem('figure1')"><b>Figure 1</b></a>. IDEA Demetra is only running CalculatorTest.</span></td><td width="12"> </td><td valign="top"><a href="javascript:showSupportItem('figure2')"><img alt="" src="http://assets.devx.com/articlefigs/16497.png" border="0" height="150" width="220" /></a><br /><span class="caption"><a href="javascript:showSupportItem('figure2')"><b>Figure 2</b></a>. Eclipse 3.2RC7 is running the suite class AllCalculatorTests.</span></td></tr></tbody></table><b>Eclipse</b><br />
I’ve used the version 3.2 RC7 of Eclipse. It is not a stable version
but the integration with JUnit 4 is much better than with IDEA. <a href="javascript:showSupportItem('figure2')">Figure 2</a> shows what you get when running the AllCalculatorTests class.
<p>
As you can see, the parameterized test case (SquareTest) is represented as seven individual tests.
</p><p><b>Ant Integration</b><br />
The junit task currently only supports JUnit 3.8 style tests, meaning
you also have to wrap your JUnit 4 tests in a JUnit4TestAdapter in
order to run them in Ant. The <span class="pf">&lt;junit&gt;</span> task is used in exactly the same way as in JUnit 3.8:
</p><pre><code><br />    &lt;!-- Test --&gt;<br />    &lt;target name="test" depends="compile"&gt;<br />        &lt;junit fork="yes" haltonfailure="yes"&gt;<br />            &lt;test name=" junit4.AllCalculatorTests"/&gt;<br />            &lt;formatter type="plain" usefile="false"/&gt;<br />            &lt;classpath refid="classpath"/&gt;<br />        &lt;/junit&gt;<br />    &lt;/target&gt;<br /></code></pre><b>JUnit: Losing Market or Coming Back Strong?</b><br />
For a long time JUnit was the defacto unit testing framework. But
lately not much has happened to this framework: no major release, no
notable new features. This is possibly the reason why other frameworks,
such as <a href="http://testng.org/" target="_blank">Test-NG</a> have started taking over.
<p>
With this new version, JUnit is back on track. It has new APIs and now
uses annotations, making it easier to develop test cases. In fact, the
JUnit developers have started to think of new, future annotations. For
example, you could add a @Prerequisite annotation for a test case that
depends on prerequisites (e.g. you need to be online to execute this
test); or add a @Repeat annotation that would specify the number of
repetitions along with a timeout (e.g. repeat a test five times to make
sure there is a real timeout problem); or even add a platform parameter
to the @Ignore annotation (e.g. @Ignore(platform=macos), which would
ignore a test only if you run on a MacOS platform). As you can see,
JUnit is still alive with a promising future.
</p><p></p><p></p><div class=""><b>Antonio Goncalves</b> is a
senior architect specialized in Java/J2EE. Former BEA consultant he now
helps insurance, finance and telecommunication clients set up their
architectures. He also teaches J2EE at CNAM University in Paris.</div><br /></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/JafeLee/aggbug/127712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-03 00:02 <a href="http://www.blogjava.net/JafeLee/articles/127712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JUnit Cookbook</title><link>http://www.blogjava.net/JafeLee/articles/127708.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Mon, 02 Jul 2007 15:50:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/127708.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/127708.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/127708.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/127708.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/127708.html</trackback:ping><description><![CDATA[
		<h1>
				<font color="#33ff33">
				</font>
		</h1>
		<h1>
				<font color="#33ff33">J</font>
				<font color="#cc0000">U</font>nit Cookbook</h1>
		<p>
Kent Beck, Erich Gamma</p>
		<hr width="100%" />
		<br />Here is a short cookbook showing you the steps you can follow in writing
and organizing your own tests using JUnit.
<h2>
Simple Test Case</h2>
How do you write testing code?
<p>The simplest way is as an expression in a debugger. You can change debug
expressions without recompiling, and you can wait to decide what to write
until you have seen the running objects. You can also write test expressions
as statements which print to the standard output stream. Both styles of
tests are limited because they require human judgment to analyze their
results. Also, they don't compose nicely- you can only execute one debug
expression at a time and a program with too many print statements causes
the dreaded "Scroll Blindness".
</p><p>JUnit tests do not require human judgment to interpret, and it is easy
to run many of them at the same time. When you need to test something,
here is what you do:
</p><ol><li>
Annotate a method with @org.junit.Test

</li><li>
When you want to check a value, import org.junit.Assert.* statically, call <tt>assertTrue</tt>() and pass a boolean
that is true if the test succeeds</li></ol>
For example, to test that the sum of two Moneys with the same currency
contains a value which is the sum of the values of the two Moneys, write:
<blockquote><pre><tt>@Test public void simpleAdd() {<br />    Money m12CHF= new Money(12, "CHF"); <br />    Money m14CHF= new Money(14, "CHF"); <br />    Money expected= new Money(26, "CHF"); <br />    Money result= m12CHF.add(m14CHF); <br />    assertTrue(expected.equals(result));<br />}</tt></pre></blockquote>
If you want to write a test similar to one you have already written, write
a Fixture instead.
<h2>
Fixture</h2>
What if you have two or more tests that operate on the same or similar
sets of objects?
<p>Tests need to run against the background of a known set of objects.
This set of objects is called a test fixture. When you are writing tests
you will often find that you spend more time writing the code to set up
the fixture than you do in actually testing values.
</p><p>To some extent, you can make writing the fixture code easier by paying
careful attention to the constructors you write. However, a much bigger
savings comes from sharing fixture code. Often, you will be able to use
the same fixture for several different tests. Each case will send slightly
different messages or parameters to the fixture and will check for different
results.
</p><p>When you have a common fixture, here is what you do:
</p><ol><li>
Add a field for each part of the fixture</li><li>
Annotate a method with @org.junit.Before
and initialize the variables in that method</li><li>
Annotate a method with @org.junit.After
to release any permanent resources you allocated in setUp</li></ol>
For example, to write several test cases that want to work with different
combinations of 12 Swiss Francs, 14 Swiss Francs, and 28 US Dollars, first
create a fixture:
<pre><tt>public class MoneyTest { <br />    private Money f12CHF; <br />    private Money f14CHF; <br />    private Money f28USD; <br />    <br />    @Before public void setUp() { <br />        f12CHF= new Money(12, "CHF"); <br />        f14CHF= new Money(14, "CHF"); <br />        f28USD= new Money(28, "USD"); <br />    }<br />}</tt></pre>
Once you have the Fixture in place, you can write as many Test Cases as
you'd like. Add as many test methods (annotated with @Test) as you'd like.
<h2>Running Tests</h2>
How do you run your tests and collect their results?
<p>Once you have tests, you'll want to run them. JUnit provides tools
to define the suite to be run and to display its results. To run tests and see the
results on the console, run:
</p><blockquote><pre><tt>org.junit.JUnitCore.runClasses(TestClass1.class, ...); <br /></tt></pre></blockquote>
You make your JUnit 4 test classes accessible to a TestRunner designed to work with earlier versions of JUnit,
declare a static method <i>suite</i>
that returns a test.
<blockquote><pre><tt>public static junit.framework.Test suite() { <br />    return new JUnit4TestAdapter(Example.class); <br />}</tt></pre></blockquote><h2>
Expected Exceptions</h2>
How do you verify that code throws exceptions as expected?
<p>Verifying that code completes normally is only part of programming. Making sure the code
behaves as expected in exceptional situations is part of the craft of programming too. For example:
</p><blockquote><pre><tt>new ArrayList&lt;Object&gt;().get(0); <br /></tt></pre></blockquote>
This code should throw an IndexOutOfBoundsException. The @Test annotation has an optional parameter "expected"
that takes as values subclasses of Throwable. If we wanted to verify that ArrayList throws the correct exception,
we would write:
<blockquote><pre><tt>@Test(expected= IndexOutOfBoundsException.class) public void empty() { <br />    new ArrayList&lt;Object&gt;().get(0); <br />}</tt></pre></blockquote><hr width="100%" /><br /><br /><img src ="http://www.blogjava.net/JafeLee/aggbug/127708.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-07-02 23:50 <a href="http://www.blogjava.net/JafeLee/articles/127708.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JUnit 4 抢先看</title><link>http://www.blogjava.net/JafeLee/articles/127003.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Fri, 29 Jun 2007 02:24:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/127003.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/127003.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/127003.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/127003.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/127003.html</trackback:ping><description><![CDATA[
		<blockquote>JUnit 是 Java? 语言<i>事实上的</i> 标准单元测试库。JUnit 4
是该库三年以来最具里程碑意义的一次发布。它的新特性主要是通过采用 Java 5
中的标记（annotation）而不是利用子类、反射或命名机制来识别测试，从而简化测试。在本文中，执着的代码测试人员 Elliotte
Harold 以 JUnit 4 为例，详细介绍了如何在自己的工作中使用这个新框架。注意，本文假设读者具有 JUnit 的使用经验。</blockquote>
		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
		<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
		<p>JUnit 由 Kent
Beck 和 Erich Gamma 开发，几乎毫无疑问是迄今所开发的最重要的第三方 Java 库。正如 Martin Fowler
所说，“在软件开发领域，从来就没有如此少的代码起到了如此重要的作用”。JUnit 引导并促进了测试的盛行。由于 JUnit，Java
代码变得更健壮，更可靠，bug 也比以前更少。JUnit（它本身的灵感来自 Smalltalk 的 SUnit）衍生了许多 xUnit
工具，将单元测试的优势应用于各种语言。nUnit (.NET)、pyUnit (Python)、CppUnit (C++)、dUnit
(Delphi) 以及其他工具，影响了各种平台和语言上的程序员的测试工作。</p>
		<p>然而，JUnit
仅仅是一个工具而已。真正的优势来自于 JUnit 所采用的思想和技术，而不是框架本身。单元测试、测试先行的编程和测试驱动的开发并非都要在
JUnit 中实现，任何比较 GUI 的编程都必须用 Swing 来完成。JUnit
本身的最后一次更新差不多是三年以前了。尽管它被证明比大多数框架更健壮、更持久，但是也发现了 bug；而更重要的是，Java
不断在发展。Java 语言现在支持泛型、枚举、可变长度参数列表和注释，这些特性为可重用的框架设计带来了新的可能。</p>
		<p>JUnit
的停滞不前并没有被那些想要废弃它的程序员所打败。挑战者包括 Bill Venners 的 Artima SuiteRunner 以及
Cedric Beust 的 TestNG 等。这些库有一些可圈可点的特性，但是都没有达到 JUnit
的知名度和市场占有份额。它们都没有在诸如 Ant、Maven 或 Eclipse 之类的产品中具有广泛的开箱即用支持。所以 Beck 和
Gamma 着手开发了一个新版本的 JUnit，它利用 Java 5 的新特性（尤其是注释）的优势，使得单元测试比起用最初的 JUnit
来说更加简单。用 Beck 的话来说，“JUnit 4 的主题是通过进一步简化 JUnit，鼓励更多的开发人员编写更多的测试。”JUnit 4
尽管保持了与现有 JUnit 3.8 测试套件的向后兼容，但是它仍然承诺是自 JUnit 1.0 以来 Java 单元测试方面最重大的改进。</p>
		<p>
				<b>注意：</b>该框架的改进是相当前沿的。尽管 JUnit 4 的大轮廓很清晰，但是其细节仍然可以改变。这意味着本文是对 JUnit 4 抢先看，而不是它的最终效果。</p>
		<p>
				<a name="N10084">
						<span class="atitle">测试方法</span>
				</a>
		</p>
		<p>以前所有版本的 JUnit 都使用命名约定和反射来定位测试。例如，下面的代码测试 1+1 等于 2：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import junit.framework.TestCase;<br />public class AdditionTest extends TestCase {<br />  private int x = 1;<br />  private int y = 1;<br /><br />  public void testAddition() {<br />    int z = x + y;<br />    assertEquals(2, z);<br />  }<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>而在 JUnit 4 中，测试是由 <code>@Test</code> 注释来识别的，如下所示：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import org.junit.Test;<br />import junit.framework.TestCase;<br />public class AdditionTest extends TestCase {<br />  private int x = 1;<br />  private int y = 1;<br /><br />  @Test public void testAddition() {<br />    int z = x + y;<br />    assertEquals(2, z);<br />  }<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>使用注释的优点是不再需要将所有的方法命名为 <code>testFoo()</code>、<code>testBar()</code>，等等。例如，下面的方法也可以工作：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import org.junit.Test;<br />import junit.framework.TestCase;<br />public class AdditionTest extends TestCase {<br />  private int x = 1;<br />  private int y = 1;<br /><br />  @Test public void additionTest() {<br />    int z = x + y;<br />    assertEquals(2, z);<br />  }<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>下面这个方法也同样能够工作：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import org.junit.Test;<br />import junit.framework.TestCase;<br />public class AdditionTest extends TestCase {<br />  private int x = 1;<br />  private int y = 1;<br /><br />  @Test public void addition() {<br />    int z = x + y;<br />    assertEquals(2, z);<br />  }<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这允许您遵循最适合您的应用程序的命名约定。例如，我介绍的一些例子采用的约定是，测试类对其测试方法使用与被测试的类相同的名称。例如，<code>List.contains()</code> 由 <code>ListTest.contains()</code> 测试，<code>List.add()</code> 由 <code>ListTest.addAll()</code> 测试，等等。</p>
		<p>
				<code>TestCase</code> 类仍然可以工作，但是您不再需要扩展它了。只要您用 <code>@Test</code> 来注释测试方法，就可以将测试方法放到任何类中。但是您需要导入 <code>junit.Assert</code> 类以访问各种 assert 方法，如下所示：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import org.junit.Assert;<br />public class AdditionTest {<br />  private int x = 1;<br />  private int y = 1;<br /><br />  @Test public void addition() {<br />    int z = x + y;<br />    Assert.assertEquals(2, z);<br />  }<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
您也可以使用 JDK 5 中新特性（static import），使得与以前版本一样简单：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">import static org.junit.Assert.assertEquals;<br />public class AdditionTest {<br />  private int x = 1;<br />  private int y = 1;<br /><br />  @Test public void addition() {<br />    int z = x + y;<br />    assertEquals(2, z);<br />  }<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
这种方法使得测试受保护的方法非常容易，因为测试案例类现在可以扩展包含受保护方法的类了。 
</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N100E2">
						<span class="atitle">SetUp 和 TearDown</span>
				</a>
		</p>
		<p>
JUnit 3 测试运行程序（test runner）会在运行每个测试之前自动调用 <code>setUp()</code> 方法。该方法一般会初始化字段，打开日志记录，重置环境变量，等等。例如，下面是摘自 XOM 的 <code>XSLTransformTest</code> 中的 <code>setUp()</code> 方法：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">protected void setUp() {<br /><br />    System.setErr(new PrintStream(new ByteArrayOutputStream()));<br /><br />    inputDir = new File("data");<br />    inputDir = new File(inputDir, "xslt");<br />    inputDir = new File(inputDir, "input");<br /><br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>在 JUnit 4 中，您仍然可以在每个测试方法运行之前初始化字段和配置环境。然而，完成这些操作的方法不再需要叫做 <code>setUp()</code>，只要用 <code>@Before</code> 注释来指示即可，如下所示：
</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@Before protected void initialize() {<br /><br />    System.setErr(new PrintStream(new ByteArrayOutputStream()));<br /><br />    inputDir = new File("data");<br />    inputDir = new File(inputDir, "xslt");<br />    inputDir = new File(inputDir, "input");<br /><br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
甚至可以用 <code>@Before</code> 来注释多个方法，这些方法都在每个测试之前运行：
</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@Before protected void findTestDataDirectory() {<br />    inputDir = new File("data");<br />    inputDir = new File(inputDir, "xslt");<br />    inputDir = new File(inputDir, "input");<br />}<br /><br /> @Before protected void redirectStderr() {<br />    System.setErr(new PrintStream(new ByteArrayOutputStream()));<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>清除方法与此类似。在 JUnit 3 中，您使用 <code>tearDown()</code> 方法，该方法类似于我在 XOM 中为消耗大量内存的测试所使用的方法：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">protected void tearDown() {<br />  doc = null;<br />  System.gc();   <br />} </pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
对于 JUnit 4，我可以给它取一个更自然的名称，并用 <code>@After</code> 注释它：
</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@After protected void disposeDocument() {<br />  doc = null;<br />  System.gc();   <br />} </pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>与 <code>@Before</code> 一样，也可以用 <code>@After</code> 来注释多个清除方法，这些方法都在每个测试之后运行。</p>
		<p>最后，您不再需要在超类中显式调用初始化和清除方法，只要它们不被覆盖即可，测试运行程序将根据需要自动为您调用这些方法。超类中的 <code>@Before</code> 方法在子类中的 <code>@Before</code> 方法之前被调用（这反映了构造函数调用的顺序）。<code>@After</code> 方法以反方向运行：子类中的方法在超类中的方法之前被调用。否则，多个 <code>@Before</code> 或 <code>@After</code> 方法的相对顺序就得不到保证。</p>
		<p>
				<a name="N1014D">
						<span class="smalltitle">套件范围的初始化</span>
				</a>
		</p>
		<p>JUnit 4 也引入了一个 JUnit 3 中没有的新特性：类范围的 <code>setUp()</code> 和 <code>tearDown()</code> 方法。任何用 <code>@BeforeClass</code> 注释的方法都将在该类中的测试方法运行之前刚好运行一次，而任何用 <code>@AfterClass</code> 注释的方法都将在该类中的所有测试都运行之后刚好运行一次。</p>
		<p>例
如，假设类中的每个测试都使用一个数据库连接、一个网络连接、一个非常大的数据结构，或者还有一些对于初始化和事情安排来说比较昂贵的其他资源。不要在每
个测试之前都重新创建它，您可以创建它一次，并还原它一次。该方法将使得有些测试案例运行起来快得多。例如，当我测试调用第三方库的代码中的错误处理时，
我通常喜欢在测试开始之前重定向 <code>System.err</code>，以便输出不被预期的错误消息打乱。然后我在测试结束后还原它，如下所示：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">// This class tests a lot of error conditions, which<br />// Xalan annoyingly logs to System.err. This hides System.err <br />// before each test and restores it after each test.<br />private PrintStream systemErr;<br /><br />@BeforeClass protected void redirectStderr() {<br />    systemErr = System.err; // Hold on to the original value<br />    System.setErr(new PrintStream(new ByteArrayOutputStream()));<br />}<br /><br />@AfterClass protected void tearDown() {<br />    // restore the original value<br />    System.setErr(systemErr);<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>没有必要在每个测试之前和之后都这样做。但是一定要小心对待这个特性。它有可能会违反测试的独立性，并引入非预期的混乱。如果一个测试在某种程度上改变了 <code>@BeforeClass</code>
所初始化的一个对象，那么它有可能会影响其他测试的结果。它有可能在测试套件中引入顺序依赖，并隐藏
bug。与任何优化一样，只在剖析和基准测试证明您具有实际的问题之后才实现这一点。这就是说，我看到了不止一个测试套件运行时间如此之长，以至不能像它
所需要的那样经常运行，尤其是那些需要建立很多网络和数据库连接的测试。（例如，LimeWire
测试套件运行时间超过两小时。）要加快这些测试套件，以便程序员可以更加经常地运行它们，您可以做的就是减少 bug。</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N10178">
						<span class="atitle">测试异常</span>
				</a>
		</p>
		<p>异常测试是 JUnit 4 中的最大改进。旧式的异常测试是在抛出异常的代码中放入 <code>try</code> 块，然后在 <code>try</code> 块的末尾加入一个 <code>fail()</code> 语句。例如，该方法测试被零除抛出一个 <code>ArithmeticException</code>：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public void testDivisionByZero() {<br /><br />    try {<br />        int n = 2 / 0;<br />        fail("Divided by zero!");<br />    }<br />    catch (ArithmeticException success) {<br />        assertNotNull(success.getMessage());<br />    }<br /><br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
该方法不仅难看，而且试图挑战代码覆盖工具，因为不管测试是通过还是失败，总有一些代码不被执行。在 JUnit 4 中，您现在可以编写抛出异常的代码，并使用注释来声明该异常是预期的：
</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@Test(expected=ArithmeticException.class) <br />  public void divideByZero() {<br />    int n = 2 / 0;<br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
如果该异常没有抛出（或者抛出了一个不同的异常），那么测试就将失败。但是如果您想要测试异常的详细消息或其他属性，则仍然需要使用旧式的 <code>try-catch</code> 样式。</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101A3">
						<span class="atitle">被忽略的测试</span>
				</a>
		</p>
		<p>也
许您有一个测试运行的时间非常地长。不是说这个测试应该运行得更快，而是说它所做的工作从根本上比较复杂或缓慢。需要访问远程网络服务器的测试通常都属于
这一类。如果您不在做可能会中断该类测试的事情，那么您可能想要跳过运行时间长的测试方法，以缩短编译-测试-调试周期。或者也许是一个因为超出您的控制
范围的原因而失败的测试。例如，W3C XInclude 测试套件测试 Java 还不支持的一些 Unicode
编码的自动识别。不必老是被迫盯住那些红色波浪线，这类测试可以被注释为 <code>@Ignore</code>，如下所示：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">// Java doesn't yet support <br />// the UTF-32BE and UTF32LE encodings<br />    @Ignore public void testUTF32BE() <br />      throws ParsingException, IOException, XIncludeException {<br /><br />        File input = new File(<br />          "data/xinclude/input/UTF32BE.xml"<br />        );<br />        Document doc = builder.build(input);<br />        Document result = XIncluder.resolve(doc);<br />        Document expectedResult = builder.build(<br />          new File(outputDir, "UTF32BE.xml")<br />        );<br />        assertEquals(expectedResult, result);<br /><br />    }</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>测试运行程序将不运行这些测试，但是它会指出这些测试被跳过了。例如，当使用文本界面时，会输出一个“I”（代表 ignore），而不是为通过的测试输出所经历的时间，也不是为失败的测试输出“E”：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">$ java -classpath .:junit.jar org.junit.runner.JUnitCore <br />  nu.xom.tests.XIncludeTest<br />JUnit version 4.0rc1<br />.....I..<br />Time: 1.149<br />OK (7 tests)</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
但是一定要小心。最初编写这些测试可能有一定的原因。如果永远忽略这些测试，那么它们期望测试的代码可能会中断，并且这样的中断可能不能被检测到。忽略测试只是一个权宜之计，不是任何问题的真正解决方案。
</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101BE">
						<span class="atitle">时间测试</span>
				</a>
		</p>
		<p>测
试性能是单元测试最为痛苦的方面之一。JUnit 4
没有完全解决这个问题，但是它对这个问题有所帮助。测试可以用一个超时参数来注释。如果测试运行的时间超过指定的毫秒数，则测试失败。例如，如果测试花费
超过半秒时间去查找以前设置的一个文档中的所有元素，那么该测试失败：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@Test(timeout=500) public void retrieveAllElementsInDocument() {<br />    doc.query("//*");<br />} </pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>除
了简单的基准测试之外，时间测试也对网络测试很有用。在一个测试试图连接到的远程主机或数据库宕机或变慢时，您可以忽略该测试，以便不阻塞所有其他的测
试。好的测试套件执行得足够快，以至程序员可以在每个测试发生重大变化之后运行这些测试，有可能一天运行几十次。设置一个超时使得这一点更加可行。例如，
如果解析 http://www.ibiblio.org/xml 花费了超过 2 秒，那么下面的测试就会超时：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">@Test(timeout=2000) <br />  public void remoteBaseRelativeResolutionWithDirectory()<br />   throws IOException, ParsingException {<br />      builder.build("http://www.ibiblio.org/xml");<br />  } </pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101D2">
						<span class="atitle">新的断言</span>
				</a>
		</p>
		<p>JUnit 4 为比较数组添加了两个 <code>assert()</code> 方法：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public static void assertEquals(Object[] expected, Object[] actual)<br />public static void assertEquals(String message, Object[] expected, <br />Object[] actual)<br /></pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>这两个方法以最直接的方式比较数组：如果数组长度相同，且每个对应的元素相同，则两个数组相等，否则不相等。数组为空的情况也作了考虑。 
</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101E6">
						<span class="atitle">需要补充的地方</span>
				</a>
		</p>
		<p>JUnit 4 基本上是一个新框架，而不是旧框架的升级版本。JUnit 3 开发人员可能会找到一些原来没有的特性。 
</p>
		<p>
最明显的删节就是 GUI
测试运行程序。如果您想在测试通过时看到赏心悦目的绿色波浪线，或者在测试失败时看到令人焦虑的红色波浪线，那么您需要一个具有集成 JUnit
支持的 IDE，比如 Eclipse。不管是 Swing 还是 AWT 测试运行程序都不会被升级或捆绑到 JUnit 4 中。
</p>
		<p>
下一个惊喜是，失败（assert 方法检测到的预期的错误）与错误（异常指出的非预期的错误）之间不再有任何差别。尽管 JUnit 3 测试运行程序仍然可以区别这些情况，而 JUnit 4 运行程序将不再能够区分。  
</p>
		<p>
最后，JUnit 4 没有 <code>suite()</code> 方法，这些方法用于从多个测试类构建一个测试套件。相反，可变长参数列表用于允许将不确定数量的测试传递给测试运行程序。 
</p>
		<p>
我对消除了 GUI 测试运行程序并不感到太高兴，但是其他更改似乎有可能增加 JUnit 的简单性。只要考虑有多少文档和 FAQ 当前专门用于解释这几点，然后考虑对于 JUnit 4，您不再需要解释这几点了。 
</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N101FF">
						<span class="atitle">编译和运行 JUnit 4</span>
				</a>
		</p>
		<p>
当前，还没有 JUnit 4 的库版本。如果您想要体验新的版本，那么您需要从 SourceForge 上的 CVS 知识库获取它。分支（branch）是“Version4”（参见 <a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#resources">参考资料</a>）。注意，很多的文档没有升级，仍然是指以旧式的 3.x 方式做事。Java 5 对于编译 JUnit 4 是必需的，因为 JUnit 4 大量用到注释、泛型以及 Java 5 语言级的其他特性。 
</p>
		<p>
自 JUnit 3 以来，从命令行运行测试的语法发生了一点变化。您现在使用 <code>org.junit.runner.JUnitCore</code> 类：</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">$ java -classpath .:junit.jar org.junit.runner.JUnitCore <br />  TestA TestB TestC...<br />JUnit version 4.0rc1<br />Time: 0.003<br />OK (0 tests)</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<a name="N10217">
						<span class="smalltitle">兼容性</span>
				</a>
		</p>
		<p>Beck
和 Gamma 努力维持向前和向后兼容。JUnit 4 测试运行程序可以运行 JUnit 3
测试，不用做任何更改。只要将您想要运行的每个测试的全限定类名传递给测试运行程序，就像针对 JUnit 4
测试一样。运行程序足够智能，可以分辨出哪个测试类依赖于哪个版本的 JUnit，并适当地调用它。
</p>
		<p>向后兼容要困难一些，但是也可以在 JUnit 3 测试运行程序中运行 JUnit 4 测试。这一点很重要，所以诸如
Eclipse 之类具有集成 JUnit 支持的工具可以处理 JUnit 4，而不需要更新。为了使 JUnit 4 测试可以运行在 JUnit
3 环境中，可以将它们包装在 <code>JUnit4TestAdapter</code> 中。将下面的方法添加到您的 JUnit 4 测试类中应该就足够了：
</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">public static junit.framework.Test suite() {<br />  return new JUnit4TestAdapter(AssertionTest.class);    <br />}</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>但是由于 Java 比较多变，所以 JUnit 4 一点都不向后兼容。JUnit 4 完全依赖于 Java 5 特性。对于 Java 1.4 或更早版本，它将不会编译或运行。</p>
		<br />
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td>
										<img src="http://www.ibm.com/i/v14/rules/blue_rule.gif" alt="" height="1" width="100%" />
										<br />
										<img alt="" src="http://www.ibm.com/i/c.gif" border="0" height="6" width="8" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" align="right" cellpadding="0" cellspacing="0">
				<tbody>
						<tr align="right">
								<td>
										<img src="http://www.ibm.com/i/c.gif" alt="" height="4" width="100%" />
										<br />
										<table border="0" cellpadding="0" cellspacing="0">
												<tbody>
														<tr>
																<td valign="middle">
																		<img src="http://www.ibm.com/i/v14/icons/u_bold.gif" alt="" border="0" height="16" width="16" />
																		<br />
																</td>
																<td align="right" valign="top">
																		<a href="http://www.ibm.com/developerworks/cn/java/j-junit4.html#main" class="fbox">
																				<b>回页首</b>
																		</a>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p>
				<a name="N1022E">
						<span class="atitle">前景</span>
				</a>
		</p>
		<p>JUnit
4 远没有结束。很多重要的方面没有提及，包括大部分的文档。我不推荐现在就将您的测试套件转换成注释和 JUnit
4。即使如此，开发仍在快速进行，并且 JUnit 4 前景非常看好。尽管 Java 2 程序员在可预见的未来仍然需要使用 JUnit
3.8，但是那些已经转移到 Java 5 的程序员则应该很快考虑使他们的测试套件适合于这个新的框架，以便匹配。
</p>
		<br />
		<br />
		<p>
				<a name="resources">
						<span class="atitle">参考资料 </span>
				</a>
		</p>
		<b>学习</b>
		<br />
		<ul>
				<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/java/library/j-junit4.html?S_TACT=105AGX52&amp;S_CMP=cn-a-j" target="_blank">英文原文</a>。<br /><br /></li>
				<li>
						<a href="http://www.pragmaticprogrammer.com/starter_kit/utj/index.html">
								<i>Pragmatic Unit Testing in Java with JUnit</i>
						</a>（Andy Hunt 和 Dave Thomas，Pragmatic Programmers，2003 年）：非常好地介绍了单元测试。<br /><br /></li>
				<li>
						<a href="http://www.amazon.com/exec/obidos/ISBN=1932394230/ref=nosim/cafeaulaitA/">
								<i>JUnit Recipes: Practical Methods for Programmer Testing</i>
						</a>（J. B. Rainsberger，Manning，2004 年）：一本最广泛地引用和参考了 JUnit 的书籍。<br /><br /></li>
				<li>
						<a href="http://www.beust.com/testng/">TestNG</a>：Cedric Beust 的框架，基于现在用于 JUnit 4 中的测试样式，最先使用了注释。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/java/j-testng">TestNG 使 Java 单元测试轻而易举</a>”（Filippo Diotalevi，developerWorks，2005 年 1 月）：介绍了 TestNG。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/java/j-ant/">利用 Ant 和 JUnit 进行增量开发</a>”（Malcolm Davis，developerWorks，2000 年 11 月）：探讨了单元测试的优势，具体使用了 Ant 和 JUnit，并有示例代码。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/java/j-xp042203/">揭开极端编程的神秘面纱: 测试驱动的编程</a>”（Roy Miller，developerWorks，2003 年 4 月）：找出测试驱动的编程可以如何提高程序员的生产效率和质量，并学习编写测试的机制。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/edu/i-dw-wes-junit-i.html?S_TACT=105AGX52&amp;S_CMP=cn-a-j">Keeping critters out of your code</a>”（David Carew 等人，developerWorks，2003 年 6 月）：学习可以如何将 JUnit 与 WebSphere Application Developer 结合起来使用。<br /><br /></li>
				<li>“<a href="http://www.ibm.com/developerworks/cn/java/j-cobertura/">用 Cobertura 测量测试覆盖率</a>”（Elliotte Rusty Harold，developerWorks，2005 年 5 月）：学习用这个方便的开放源码工具来识别未测试的代码和查找 bug。<br /><br /></li>
		</ul>
		<br />
		<b>讨论</b>
		<br />
		<ul>
				<li>
						<a href="http://www.ibm.com/developerworks/blogs/?S_TACT=105AGX52&amp;S_CMP=cn-a-j">developerWorks blogs</a>：加入 developerWorks 社区。</li>
		</ul>
		<br />
		<br />
		<p>
				<a name="author">
						<span class="atitle">关于作者</span>
				</a>
		</p>
		<table border="0" cellpadding="0" cellspacing="0" width="100%">
				<tbody>
						<tr>
								<td colspan="3">
										<img alt="" src="http://www.ibm.com/i/c.gif" height="5" width="100%" />
								</td>
						</tr>
						<tr align="left" valign="top">
								<td>
										<br />
								</td>
								<td>
										<img alt="" src="http://www.ibm.com/i/c.gif" height="5" width="4" />
								</td>
								<td width="100%">
										<p>Elliotte
Rusty Harold 出生在新奥尔良，现在，他还定期回老家喝一碗美味的秋葵汤。不过目前他与妻子 Beth 定居在纽约临近布鲁克林的
Prospect Heights，与他们住在一起的还有猫咪 Charm（取自夸克）和 Marjorie（按照他岳母的名字）。他是
Polytechnic 大学计算机科学的副教授，讲授 Java 技术和面向对象编程。他的 <a href="http://www.cafeaulait.org/">Cafe au Lait</a> 网站是 Internet 上最受欢迎的独立 Java 站点之一，姊妹站点 <a href="http://www.cafeconleche.org/">Cafe con Leche</a> 是最受欢迎的 XML 站点之一。他的著作包括 <a href="http://www.cafeconleche.org/books/effectivexml/"><i>Effective XML</i></a>、<a href="http://www.cafeconleche.org/books/xmljava/"><i>Processing XML with Java</i></a>、<a href="http://www.cafeaulait.org/books/jnp3/"><i>Java Network Programming</i></a> 和 <a href="http://www.cafeconleche.org/books/bible3/"><i>The XML 1.1 Bible</i></a>。他目前在研究处理 XML 的 <a href="http://www.xom.nu/">XOM</a> API、<a href="http://jaxen.codehaus.org/">Jaxen</a> XPath 引擎和 <a href="http://jester.sourceforge.net/">Jester</a> 测试覆盖工具。
</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/JafeLee/aggbug/127003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-06-29 10:24 <a href="http://www.blogjava.net/JafeLee/articles/127003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JUnit 4.0 In 10 Minutes - A quick reference guide</title><link>http://www.blogjava.net/JafeLee/articles/126996.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Fri, 29 Jun 2007 02:06:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/126996.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/126996.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/126996.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/126996.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/126996.html</trackback:ping><description><![CDATA[
		<p>
				<b>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Abstract: </span>
				</b>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.junit.org/">JUnit</a> needs no introduction. Originally written by <a href="http://www.threeriversinstitute.org/Kent%20Beck.htm">Kent Beck</a> and <a href="http://www.javapolis.com/confluence/display/JP04/Erich+Gamma">Erich Gamma</a>, the software is the preferred tool of choice for developer testing. Now, the team of <a href="http://www.threeriversinstitute.org/Kent%20Beck.htm">Kent Beck</a> and <a href="http://www.javapolis.com/confluence/display/JP04/Erich+Gamma">Erich Gamma</a>
is back again with a new version of JUnit – 4.0. This quick reference
guide is for programmers and testers looking to migrate to JUnit 4.0.
If you have a flight to catch or do not want to spend 10 minutes going
through the guide, just jump to the summary section and you will learn
enough.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">For the purpose of this article, I will call JUnit 3.8.1 and its predecessors as the old JUnit and JUnit 4.0 as the new JUnit. </span>
		</p>
		<h3>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Table of contents:</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">This guide contains the following sections:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_Old_JUnit_revisited">Old JUnit revisited</a>
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_Cut_the_chase_to%20JUnit%204.0">Cut the chase to JUnit 4.0</a>
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_Run_the_tests">Run the tests</a>
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_Set_up_and_tear%20down">Set up and tear down</a>
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_One-time_set_up_and%20tear%20down">One-time set up and tear down</a>
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_Expecting_exceptions">Expecting exceptions</a>
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_Other_Annotations">Other Annotations</a>
				</span>
		</p>
		<blockquote>
				<p>
						<span style="font-size: 11pt; font-family: &quot;Courier New&quot;;">o<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">        </span></span>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
								<a href="http://www.instrumentalservices.com/content/view/45/52/#_Ignoring_a_test">Ignoring a test</a>
						</span>
				</p>
				<p>
						<span style="font-size: 11pt; font-family: &quot;Courier New&quot;;">o<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">        </span></span>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
								<a href="http://www.instrumentalservices.com/content/view/45/52/#_Timing_out_a_test">Timing out a test</a>
						</span>
				</p>
		</blockquote>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<a href="http://www.instrumentalservices.com/content/view/45/52/#_Summary">Summary</a>
				</span>
		</p>
		<h3>
				<a name="_Toc106546128">
				</a>
				<a name="_Old_JUnit_revisited">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Old JUnit revisited</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Using the old JUnit, let us write a test, which verifies the availability of a book in the library.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<img src="http://www.instrumentalservices.com/media/articles/java/junit4/img/OldJunit35Code.png" v:shapes="_x0000_i1025" border="0" height="227" width="553" />
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">To summarize the steps:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">We extend from junit.framework.TestCase.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">We name the test methods with a prefix of ‘test’.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">We validate conditions using one of the several assert methods.</span>
		</p>
		<h3>
				<a name="_Toc106546129">
				</a>
				<a name="_Cut_the_chase_to JUnit 4.0">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Cut the chase to JUnit 4.0</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Let us write the same test using JUnit 4.0.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<img src="http://www.instrumentalservices.com/media/articles/java/junit4/img/NewJUnit4Code.png" v:shapes="_x0000_i1026" border="0" height="278" width="527" />
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">When
I upgrade to a new version I look for tasks, I do not have to do
anymore. Here is the same code with notes telling us what not to do
anymore.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<img src="http://www.instrumentalservices.com/media/articles/java/junit4/img/WhatNotToDoInJunit4.png" v:shapes="_x0000_i1027" border="0" height="278" width="527" />
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">To summarize:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">We do not extend from junit.framework.TestCase.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">We do not prefix the test method with ‘test’.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Next, I look for new tasks I must always do. The diagram below summarizes what we must do according to the new JUnit standards:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<img src="http://www.instrumentalservices.com/media/articles/java/junit4/img/WhatToDoInJunit4.png" v:shapes="_x0000_i1028" border="0" height="278" width="527" />
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">To summarize:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Use a normal class and not extend from junit.framework.TestCase.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Use the Test annotation to mark a method as a test method. To use the Test annotation, we need to import org.junit.Test</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Use
one of the assert methods. There is no difference between the old
assert methods and the new assert methods. An easy way to use the
assert method is to do a static import as shown by point 2 in the code
above.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Run the test using JUnit4TestAdapter. If you want to learn more about JUnit4TestAdapter, keep reading ahead.</span>
		</p>
		<h3>
				<a name="_Toc106546130">
				</a>
				<a name="_Run_the_tests">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Run the tests</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Unfortunately,
our favorite development environments are still unaware of JUnit 4.
JUnit4Adapter enables compatibility with the old runners so that the
new JUnit 4 tests can be run with the old runners. The suite method in
the diagram above illustrates the use of JUnit4Adapter.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Alternatively,
you can use the JUnitCore class in the org.junit.runner package. JUnit
4 runner can also run tests written using the old JUnit. To run the
tests using the JUnitCore class via the command line, type:</span>
		</p>
		<p>
				<tt>
						<span style="font-size: 11pt;">java org.junit.runner.JUnitCore LibraryTest</span>
				</tt>
		</p>
		<h3>
				<a name="_Toc106546131">
				</a>
				<a name="_Set_up_and_tear down">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Set up and tear down</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">The new JUnit provides two new annotations for set up and tear down:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">@Before: Method annotated with @Before executes before every test.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">@After: Method annotated with @After executes after every test.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Here is the code that demonstrates the use of @Before and @After:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<img src="http://www.instrumentalservices.com/media/articles/java/junit4/img/BeforeAndAfter.png" v:shapes="_x0000_i1029" border="0" height="424" width="530" />
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Two features of @Before and @After annotations that are helpful to learn:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">You can have any number of @Before and @After as you need. </span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: Symbol;">·<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">It
is possible to inherit the @Before and @After methods. New JUnit
executes @Before methods in superclass before the inherited @Before
methods. @After methods in subclasses are executed before the inherited
@After methods. </span>
		</p>
		<h3>
				<a name="_Toc106546132">
				</a>
				<a name="_One-time_set_up_and tear down">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">One-time set up and tear down</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">The
new JUnit4 provides @BeforeClass and @AfterClass annotations for
one-time set up and tear down. This is similar to the TestSetup class
in the old junit.extensions package, which ran setup code once before
all the tests and cleanup code once after all the tests. </span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Here is the code that demonstrates @BeforeClass and @AfterClass:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<img src="http://www.instrumentalservices.com/media/articles/java/junit4/img/BeforeClassAndAfterClass.png" v:shapes="_x0000_i1030" border="0" height="450" width="545" />
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Unlike @Before and @After annotations, only one set of @BeforeClass and @AfterClass annotations are allowed.</span>
		</p>
		<h3>
				<a name="_Toc106546133">
				</a>
				<a name="_Expecting_exceptions">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Expecting exceptions</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">The
new JUnit makes checking for exceptions very easy. The @Test annotation
takes a parameter, which declares the type of Exception that should be
thrown. The code below demonstrates this:</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">
						<img src="http://www.instrumentalservices.com/media/articles/java/junit4/img/Exception.png" v:shapes="_x0000_i1031" border="0" height="236" width="491" />
				</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">In
the code above, bookNotAvailableInLibrary is a test, which passes only
if BookNotAvailableException is thrown. The test fails if no exception
is thrown. Test also fails if a different exception is thrown.</span>
		</p>
		<h3>
				<a name="_Toc106546134">
				</a>
				<a name="_Other_Annotations">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Other Annotations</span>
		</h3>
		<h3>
				<a name="_Toc106546135">
				</a>
				<a name="_Ignoring_a_test">
				</a>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Ignoring a test</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">The
@Ignore annotation tells the runner to ignore the test and report that
it was not run. You can pass in a string as a parameter to @Ignore
annotation that explains why the test was ignored. E.g. The new JUnit
will not run a test method annotated with @Ignore(“Database is down”)
but will only report it. The version of JUnit4Adapter, I used, did not
work with @Ignore annotation. Kent Beck has informed me that the next
version of JUnitAdapter will fix this problem.</span>
		</p>
		<h3>
				<a name="_Toc106546136">
				</a>
				<a name="_Timing_out_a_test">
				</a>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Timing out a test</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">You
can pass in a timeout parameter to the test annotation to specify the
timeout period in milliseconds. If the test takes more, it fails. E.g.
A method annotated with @Test (timeout=10) fails if it takes more than
10 milliseconds.</span>
		</p>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Finally, I would like to thank Kent Beck for taking the time to demonstrate and teach the new JUnit to me.</span>
		</p>
		<h3>
				<a name="_Toc106546137">
				</a>
				<a name="_Summary">
				</a>
				<span style="font-family: &quot;Trebuchet MS&quot;;">Summary</span>
		</h3>
		<p>
				<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">To summarize the new JUnit style:</span>
		</p>
		<ol start="1" type="1">
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">It Requires JDK 5 to run.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Test classes do not have to extend from junit.framework.TestCase.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Test methods do not have to be prefixed with ‘test’.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">There is no difference between the old assert methods and the new assert methods.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Use @Test annotations to mark a method as a test case.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">@Before and @After annotations take care of set up and tear down.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">@BeforeClass and @AfterClass annotations take care of one time set up and one time tear down.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">@Test annotations can take a parameter for timeout. Test fails if the test takes more time to execute.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">@Test annotations can take a parameter that declares the type of exception to be thrown.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">JUnit4Adapter enables running the new JUnit4 tests using the old JUnit runners.</span>
				</li>
				<li>
						<span style="font-size: 11pt; font-family: &quot;Trebuchet MS&quot;;">Old JUnit tests can be run in the new JUnit4 runner.</span>
				</li>
		</ol>
<img src ="http://www.blogjava.net/JafeLee/aggbug/126996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-06-29 10:06 <a href="http://www.blogjava.net/JafeLee/articles/126996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>10分钟了解junit 4 (转载）</title><link>http://www.blogjava.net/JafeLee/articles/126995.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Fri, 29 Jun 2007 02:03:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/126995.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/126995.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/126995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/126995.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/126995.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">原文链接：<a href="/easyjf/archive/2006/11/19/82072.aspx">http://www.blogjava.net/easyjf/archive/2006/11/19/82072.aspx</a><br /></span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">
						<br />
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">这篇文章算是一个翻译了。分成两部分，集合了两篇</span>
				<span lang="EN-US">JUnit.org</span>
				<span style="font-family: 宋体;">上的推荐文章，这里是原文的地址：</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<a href="http://www.instrumentalservices.com/index.php?option=com_content&amp;task=view&amp;id=45&amp;Itemid=52">
								<u>http://www.instrumentalservices.com/index.php?option=com_content&amp;task=view&amp;id=45&amp;Itemid=52</u>
						</a>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<a href="http://www.devx.com/Java/Article/31983">
								<u>http://www.devx.com/Java/Article/31983</u>
						</a>
						<a href="http://www.devx.com/Java/Article/31983">
						</a>
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<br />
				</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">JUnit</span>
				<span style="font-family: 宋体;">我就不多做介绍了，</span>
				<span lang="EN-US">Kent Beck </span>
				<span style="font-family: 宋体;">和</span>
				<span lang="EN-US">Erich Gamma</span>
				<span style="font-family: 宋体;">的作品。这里主要讲一下在</span>
				<span lang="EN-US">JUnit 4.0 </span>
				<span style="font-family: 宋体;">和</span>
				<span lang="EN-US">4.1</span>
				<span style="font-family: 宋体;">版本中的一些改进和新的用法。</span>
		</p>
		<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
				<span style="font-family: 宋体;">要很好的使用</span>
				<span lang="EN-US">JUnit 4.x</span>
				<span style="font-family: 宋体;">，必须要</span>
				<span lang="EN-US">Java SE 5.0 </span>
				<span style="font-family: 宋体;">，因为这个版本最大的变化就是加入了大量的</span>
				<span lang="EN-US">Annotation</span>
				<span style="font-family: 宋体;">的使用。</span>
		</p>
		<p>
				<span style="font-size: 10.5pt; font-family: 宋体;">来通过一个例子看下，首先是一个老版本的测试案例：</span>
		</p>
		<p>
				<span style="font-size: 10.5pt; font-family: 宋体;">
						<img src="http://blog.easyjf.com/upfile/blog/1317817455228451/OldJunit35Code.png" border="0" height="227" width="553" />
				</span>
		</p>
		<span style="font-size: 10.5pt; font-family: 宋体;">
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">有几点需要关注：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">1</font>
						</span>
						<span style="font-family: 宋体;">——</span>
						<font face="Times New Roman">
						</font>
						<span style="font-family: 宋体;">一个测试案例必须要继承自</span>
						<span lang="EN-US">
								<font face="Times New Roman">TestCase</font>
						</span>
						<span style="font-family: 宋体;">；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">2</font>
						</span>
						<span style="font-family: 宋体;">——</span>
						<span lang="EN-US">
								<font face="Times New Roman"> JUnit</font>
						</span>
						<span style="font-family: 宋体;">是通过反射机制来执行每一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">test</font>
						</span>
						<span style="font-family: 宋体;">方法，它通过匹配方法名</span>
						<span lang="EN-US">
								<font face="Times New Roman">testXXX</font>
						</span>
						<span style="font-family: 宋体;">来确定一个方法为需要执行的测试</span>
						<span lang="EN-US">
								<font face="Times New Roman">Case</font>
						</span>
						<span style="font-family: 宋体;">。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">3</font>
						</span>
						<span style="font-family: 宋体;">——</span>
						<font face="Times New Roman">
						</font>
						<span style="font-family: 宋体;">使用一个或几个</span>
						<span lang="EN-US">
								<font face="Times New Roman">assertXXX</font>
						</span>
						<span style="font-family: 宋体;">方法来验证我们的情况。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">好，现在使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit 4.x</font>
						</span>
						<span style="font-family: 宋体;">来实现相同的测试，从中，我们就能看到一些新的东西：</span>
				</p>
				<p>
						<img src="http://blog.easyjf.com/upfile/blog/1317817455228451/NewJUnit4Code.png" border="0" height="278" width="527" />
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">首先关注以下几点：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">1</font>
						</span>
						<span style="font-family: 宋体;">——我们的测试类并没有</span>
						<span lang="EN-US">
								<font face="Times New Roman">extends TestCase</font>
						</span>
						<span style="font-family: 宋体;">类了，</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">2</font>
						</span>
						<span style="font-family: 宋体;">——我们的测试方法并没有以</span>
						<span lang="EN-US">
								<font face="Times New Roman">test</font>
						</span>
						<span style="font-family: 宋体;">开头，而是使用了</span>
						<span lang="EN-US">
								<font face="Times New Roman">@Test</font>
						</span>
						<span style="font-family: 宋体;">标签来标记该方法是一个需要测试的方法。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">下面的图标示了用</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit 4.x</font>
						</span>
						<span style="font-family: 宋体;">我们需要做的事情：</span>
				</p>
				<p>
						<img src="http://blog.easyjf.com/upfile/blog/1317817455228451/WhatToDoInJunit4.png" border="0" height="278" width="527" />
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">1</font>
						</span>
						<span style="font-family: 宋体;">——我们需要引进</span>
						<span lang="EN-US">
								<font face="Times New Roman">org.junit.Test</font>
						</span>
						<span style="font-family: 宋体;">标签，还有很多标签都在</span>
						<span lang="EN-US">
								<font face="Times New Roman">org.junit.*</font>
						</span>
						<span style="font-family: 宋体;">包里面。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">2</font>
						</span>
						<span style="font-family: 宋体;">——引进</span>
						<span lang="EN-US">
								<font face="Times New Roman">static assertEquals</font>
						</span>
						<span style="font-family: 宋体;">静态方法，引入静态方法也是</span>
						<span lang="EN-US">
								<font face="Times New Roman">Java 5</font>
						</span>
						<span style="font-family: 宋体;">的一个新的特性，避免了使用过长的应用方法名。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">3</font>
						</span>
						<span style="font-family: 宋体;">——引进</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit4TestAdapter</font>
						</span>
						<span style="font-family: 宋体;">，这是一个和老版本</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit</font>
						</span>
						<span style="font-family: 宋体;">工具合用的适配器。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">4</font>
						</span>
						<span style="font-family: 宋体;">——使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">@Test</font>
						</span>
						<span style="font-family: 宋体;">标签来申明一个方法需要测试。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">5</font>
						</span>
						<span style="font-family: 宋体;">——直接使用需要的</span>
						<span lang="EN-US">
								<font face="Times New Roman">assert</font>
						</span>
						<span style="font-family: 宋体;">方法</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">6</font>
						</span>
						<span style="font-family: 宋体;">——使用一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">main</font>
						</span>
						<span style="font-family: 宋体;">方法来用</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit4TestAdapter</font>
						</span>
						<span style="font-family: 宋体;">在老的</span>
						<span lang="EN-US">
								<font face="Times New Roman">Junit runner</font>
						</span>
						<span style="font-family: 宋体;">上运行新的测试。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">总结一下：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;">
						<span style="font-family: Wingdings;" lang="EN-US">
								<span style="">l<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
						</span>
						<span style="font-family: 宋体;">使用一个普通的类，而不必继承自</span>
						<span lang="EN-US">
								<font face="Times New Roman">Junit.framework.TestCase</font>
						</span>
						<span style="font-family: 宋体;">。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;">
						<span style="font-family: Wingdings;" lang="EN-US">
								<span style="">l<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
						</span>
						<span style="font-family: 宋体;">使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">@Test</font>
						</span>
						<span style="font-family: 宋体;">标签来标记一个方法是一个测试方法。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;">
						<span style="font-family: Wingdings;" lang="EN-US">
								<span style="">l<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
						</span>
						<span style="font-family: 宋体;">使用一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">assert</font>
						</span>
						<span style="font-family: 宋体;">方法。在新版本的</span>
						<span lang="EN-US">
								<font face="Times New Roman">Junit</font>
						</span>
						<span style="font-family: 宋体;">中，</span>
						<span lang="EN-US">
								<font face="Times New Roman">assert</font>
						</span>
						<span style="font-family: 宋体;">方法和老方法没有什么区别。并且使用静态方法引入，（</span>
						<span lang="EN-US">
								<font face="Times New Roman">static import</font>
						</span>
						<span style="font-family: 宋体;">）特性来简化方法的使用。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;">
						<span style="font-family: Wingdings;" lang="EN-US">
								<span style="">l<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">         </span></span>
						</span>
						<span style="font-family: 宋体;">使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit4TestAdapter</font>
						</span>
						<span style="font-family: 宋体;">来运行测试。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">Set up </font>
						</span>
						<span style="font-family: 宋体;">和</span>
						<span lang="EN-US">
								<font face="Times New Roman">tear down</font>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">新版本的</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit</font>
						</span>
						<span style="font-family: 宋体;">提供了两个新的标签来使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">set up</font>
						</span>
						<span style="font-family: 宋体;">和</span>
						<span lang="EN-US">
								<font face="Times New Roman">tear down</font>
						</span>
						<span style="font-family: 宋体;">：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">@Before</font>
						</span>
						<span style="font-family: 宋体;">：使用了该标记的方法在每个测试方法执行之前都要执行一次。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">@After</font>
						</span>
						<span style="font-family: 宋体;">：使用了该标记的方法在每个测试方法执行之后要执行一次。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">这里有个测试的例子：</span>
				</p>
				<p>
						<img src="http://blog.easyjf.com/upfile/blog/1317817455228451/BeforeAndAfter.png" border="0" height="424" width="530" />
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">如果我们在所有的方法中都添加一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">System.out.println()</font>
						</span>
						<span style="font-family: 宋体;">方法，执行的结果会像这样：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">
										<span style="">       </span>runOnceBeforeAllTests() </font>
						</span>
						<span style="font-family: 宋体;">被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">bookNotAvailableInLibrary() </font>
						</span>
						<span style="font-family: 宋体;">被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">bookAvailableInCentralLibrary</font>
						</span>
						<span style="font-family: 宋体;">（）被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">runAfterAllTests</font>
						</span>
						<span style="font-family: 宋体;">（）被调用，</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">而如果我们还有一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">@Before beforeTest()</font>
						</span>
						<span style="font-family: 宋体;">方法和一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">@After afterTest()</font>
						</span>
						<span style="font-family: 宋体;">方法，那么执行的结果会是这样：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">
										<span style="">       </span>runOnceBeforeAllTests() </font>
						</span>
						<span style="font-family: 宋体;">被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">
										<span style="">       </span>beforeTest() </font>
						</span>
						<span style="font-family: 宋体;">被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">bookNotAvailableInLibrary() </font>
						</span>
						<span style="font-family: 宋体;">被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">afterTest</font>
						</span>
						<span style="font-family: 宋体;">（）被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">beforeTest() </font>
						</span>
						<span style="font-family: 宋体;">被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">bookAvailableInCentralLibrary</font>
						</span>
						<span style="font-family: 宋体;">（）被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">afterTest</font>
						</span>
						<span style="font-family: 宋体;">（）被调用；</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;">
						<span lang="EN-US">
								<font face="Times New Roman">runAfterAllTests</font>
						</span>
						<span style="font-family: 宋体;">（）被调用，</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">从这里我们就可以看出两者的区别了。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">另外一点，</span>
						<span lang="EN-US">
								<font face="Times New Roman">@Before</font>
						</span>
						<span style="font-family: 宋体;">和</span>
						<span lang="EN-US">
								<font face="Times New Roman">@After</font>
						</span>
						<span style="font-family: 宋体;">标示的方法只能各有一个。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">错误处理：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">在</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit4.0</font>
						</span>
						<span style="font-family: 宋体;">之前，对错误的测试，我们只能通过</span>
						<span lang="EN-US">
								<font face="Times New Roman">fail</font>
						</span>
						<span style="font-family: 宋体;">来产生一个错误，并在</span>
						<span lang="EN-US">
								<font face="Times New Roman">try</font>
						</span>
						<span style="font-family: 宋体;">块里面</span>
						<span lang="EN-US">
								<font face="Times New Roman">assertTrue</font>
						</span>
						<span style="font-family: 宋体;">（</span>
						<span lang="EN-US">
								<font face="Times New Roman">true</font>
						</span>
						<span style="font-family: 宋体;">）来测试。现在，通过</span>
						<span lang="EN-US">
								<font face="Times New Roman">@Test</font>
						</span>
						<span style="font-family: 宋体;">标签中的</span>
						<span lang="EN-US">
								<font face="Times New Roman">expected</font>
						</span>
						<span style="font-family: 宋体;">属性，就可以更优雅的测试错误了：</span>
				</p>
				<p>
						<img src="http://blog.easyjf.com/upfile/blog/1317817455228451/Exception.png" border="0" height="236" width="491" />
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">在这段代码中，我们为</span>
						<span lang="EN-US">
								<font face="Times New Roman">@Test</font>
						</span>
						<span style="font-family: 宋体;">标签添加了</span>
						<span lang="EN-US">
								<font face="Times New Roman">expected</font>
						</span>
						<span style="font-family: 宋体;">属性，并提供了一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">BookNotAvailableException</font>
						</span>
						<span style="font-family: 宋体;">，那么在这段测试中，如果代码没有抛出这个类型的错误，测试就失败了，如果正确抛出该类型错误，测试通过。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">其他的标签：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">@ignore</font>
						</span>
						<span style="font-family: 宋体;">标签：</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">该标签标记的测试方法在测试中会被忽略。当测试的方法还没有实现，或者测试的方法已经过时，或者在某种条件下才能测试该方法（比如需要一个数据库联接，而在本地测试的时候，数据库并没有连接），那么使用该标签来标示这个方法。同时，你可以为该标签传递一个</span>
						<span lang="EN-US">
								<font face="Times New Roman">String</font>
						</span>
						<span style="font-family: 宋体;">的参数，来表明为什么会忽略这个测试方法。比如：</span>
						<span lang="EN-US">
								<font face="Times New Roman">@lgnore(“</font>
						</span>
						<span style="font-family: 宋体;">该方法还没有实现</span>
						<span lang="EN-US">
								<font face="Times New Roman">”)</font>
						</span>
						<span style="font-family: 宋体;">，在执行的时候，仅会报告该方法没有实现，而不会运行测试方法。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<font face="Times New Roman">@Test(timeout=xxx):</font>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">该标签传入了一个时间（毫秒）给测试方法，</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">如果测试方法在制定的时间之内没有运行完，则测试也失败。</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span lang="EN-US">
								<o:p>
										<font face="Times New Roman"> </font>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">
						<span style="font-family: 宋体;">这篇文章就到这里，其实</span>
						<span lang="EN-US">
								<font face="Times New Roman">JUnit4.x</font>
						</span>
						<span style="font-family: 宋体;">里面还有很多标签的用法，将在明天的</span>
						<span lang="EN-US">
								<font face="Times New Roman">blog</font>
						</span>
						<span style="font-family: 宋体;">中继续。</span>
				</p>
		</span>
<img src ="http://www.blogjava.net/JafeLee/aggbug/126995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-06-29 10:03 <a href="http://www.blogjava.net/JafeLee/articles/126995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何使用JFlex、JavaCUP(详细代码模版) by 踏雪赤兔 (转载）</title><link>http://www.blogjava.net/JafeLee/articles/123387.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Mon, 11 Jun 2007 06:47:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/123387.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/123387.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/123387.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/123387.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/123387.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文链接：http://www.cnitblog.com/cockerel/archive/2007/05/09/26781.html博主踏雪赤兔按：　　编译原理的实验要求我们用JFlex和JavaCUP来对语言进行分析处理，JavaCUP有一个User'sManual教你怎样做，上面还有一个简单的计算器作为例子，但一试之下，却发现那个例子有不少错误，结果改了我n久才完成~当然马上就决定写一篇...&nbsp;&nbsp;<a href='http://www.blogjava.net/JafeLee/articles/123387.html'>阅读全文</a><img src ="http://www.blogjava.net/JafeLee/aggbug/123387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-06-11 14:47 <a href="http://www.blogjava.net/JafeLee/articles/123387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基于JDBC的数据库连接池技术研究与应用 （转载）</title><link>http://www.blogjava.net/JafeLee/articles/120559.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Mon, 28 May 2007 13:45:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/120559.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/120559.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/120559.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/120559.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/120559.html</trackback:ping><description><![CDATA[
		<b>原文链接：<a href="http://blog.csdn.net/databasechannel/archive/2005/12/05/543838.aspx">http://blog.csdn.net/databasechannel/archive/2005/12/05/543838.aspx</a><br /><br />摘 要 </b>本文介绍了Java访问数据库的原理及其存在的问题，提出了解决办法－数据库连接池，并对其关键问题进行了分析，构建了一个简便易用的连接池并结合当前热门技术Servlet说明了其如何在开发时使用。<br /><br /><b>　　关键词 </b>JDBC，Jsp/Servlet，数据库连接池，多数据库服务器和多用户，多线程<br /><br />　　<b>引言</b><br /><br />　　近年来，随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及，计算机<br /><br />　
　应用程序已从传统的桌面应用转到Web应用。基于B/S（Browser/Server）架构的3层开发模式逐渐取代C/S
（Client/Server）架构的开发模式，成为开发企业级应用和电子商务普遍采用的技术。在Web应用开发的早期，主要使用的技术是
CGI﹑ASP﹑PHP等。之后，Sun公司推出了基于Java语言的Servlet+Jsp+JavaBean技术。相比传统的开发技术，它具有跨平台
﹑安全﹑有效﹑可移植等特性，这使其更便于使用和开发。<br /><br />　　<b>Java应用程序访问数据库的基本原理</b><br /><br />　　在Java语言中，JDBC（Java DataBase Connection）是应用程序与数据库沟通的桥梁,<br /><br />　
　即Java语言通过JDBC技术访问数据库。JDBC是一种“开放”的方案，它为数据库应用开发人员﹑数据库前台工具开发人员提供了一种标准的应用程序
设计接口，使开发人员可以用纯Java语言编写完整的数据库应用程序。JDBC提供两种API，分别是面向开发人员的API和面向底层的JDBC驱动程序
API，底层主要通过直接的JDBC驱动和JDBC-ODBC桥驱动实现与数据库的连接。<br /><br />　　一般来说，Java应用程序访问数据库的过程（如图1所示）是：<br /><br />　　①装载数据库驱动程序；<br /><br />　　②通过JDBC建立数据库连接；<br /><br />　　③访问数据库，执行SQL语句；<br /><br />　　④断开数据库连接。<br /><br /><table align="center" border="0" width="90%"><tbody><tr><td><div align="center"><img src="http://dev.yesky.com/imagelist/05/12/jf93vwb47s48.gif" alt="" border="0" /><br />图1 Java数据库访问机制</div></td></tr></tbody></table><p><br />　　JDBC作为一种数据库访问技术，具有简单易用的优点。但使用这种模式进行Web应用<br /><br />　
　程序开发，存在很多问题：首先，每一次Web请求都要建立一次数据库连接。建立连接是一个费时的活动，每次都得花费0.05s～1s的时间，而且系统还
要分配内存资源。这个时间对于一次或几次数据库操作，或许感觉不出系统有多大的开销。可是对于现在的Web应用，尤其是大型电子商务网站，同时有几百人甚
至几千人在线是很正常的事。在这种情况下，频繁的进行数据库连接操作势必占用很多的系统资源，网站的响应速度必定下降，严重的甚至会造成服务器的崩溃。不
是危言耸听，这就是制约某些电子商务网站发展的技术瓶颈问题。其次，对于每一次数据库连接，使用完后都得断开。否则，如果程序出现异常而未能关闭，将会导
致数据库系统中的内存泄漏，最终将不得不重启数据库。还有，这种开发不能控制被创建的连接对象数，系统资源会被毫无顾及的分配出去，如连接过多，也可能导
致内存泄漏，服务器崩溃。</p>　　<b>数据库连接池（connection pool）的工作原理</b><br /><br />　　1、基本概念及原理<br /><br />　　由上面的分析可以看出，问题的根源就在于对数据库连接资源的低效管理。我们知道，<br /><br />　
　对于共享资源，有一个很著名的设计模式：资源池（Resource
Pool）。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题，可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接
建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接，当需要建立数据库连接时，只需从“缓冲池”中取出一个，使用完毕之后再放回去。我们可以通过设定
连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况，为系统开发﹑测试及性能调
整提供依据。连接池的基本工作原理见下图2。<br /><br /><table align="center" border="0" width="90%"><tbody><tr><td><div align="center"><img src="http://dev.yesky.com/imagelist/05/12/34hdqm2lg7vu.gif" alt="" border="0" /><br />图2 连接池的基本工作原理</div></td></tr></tbody></table><br />　　2、服务器自带的连接池<br /><br />　　JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制，但是必须有其第三方的专用类方法支持连接池的用法。<br /><br />　　<b>连接池关键问题分析</b><br /><br />　　1、并发问题<br /><br />　
　为了使连接管理服务具有最大的通用性，必须考虑多线程环境，即并发问题。这个问题相对比较好解决，因为Java语言自身提供了对并发管理的支持，使用
synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字，如：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>public synchronized Connection getConnection（）</td></tr></tbody></table><br />　　2、多数据库服务器和多用户<br /><br />　
　对于大型的企业级应用，常常需要同时连接不同的数据库（如连接Oracle和Sybase）。如何连接不同的数据库呢？我们采用的策略是：设计一个符合
单例模式的连接池管理类，在连接池管理类的唯一实例被创建时读取一个资源文件，其中资源文件中存放着多个数据库的url地址（&lt;
poolName.url&gt;）﹑用户名（&lt;poolName.user&gt;）﹑密码（&lt;
poolName.password&gt;）等信息。如tx.url=172.21.15.123：5000/tx_it，tx.user=yang，
tx.password=yang321。根据资源文件提供的信息，创建多个连接池类的实例，每一个实例都是一个特定数据库的连接池。连接池管理类实例为
每个连接池实例取一个名字，通过不同的名字来管理不同的连接池。<br /><br />　　对于同一个数据库有多个用户使用不同的名称和密码访问的情况，也可以通过资源文件处理，即在资源文件中设置多个具有相同url地址，但具有不同用户名和密码的数据库连接信息。<br /><br />　　3、事务处理<br /><br />　　我们知道，事务具有原子性，此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做，要么全不做。<br /><br />　
　在Java语言中，Connection类本身提供了对事务的支持，可以通过设置Connection的AutoCommit属性为false,然后显
式的调用commit或rollback方法来实现。但要高效的进行Connection复用，就必须提供相应的事务支持机制。可采用每一个事务独占一个
连接来实现，这种方法可以大大降低事务管理的复杂性。<br /><br />　　4、连接池的分配与释放<br /><br />　　连接池的分配与释放，对系统的性能有很大的影响。合理的分配与释放，可以提高连接的复用度，从而降低建立新连接的开销，同时还可以加快用户的访问速度。<br /><br />　
　对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时，系统首先检查空闲池内有没有空
闲连接。如果有就把建立时间最长（通过容器的顺序存放实现）的那个连接分配给他（实际是先做连接是否有效的判断，如果可用就分配给用户，如不可用就把这个
连接从空闲池删掉，重新检测空闲池是否还有连接）；如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数（maxConn）,如果没有达到，就
新建一个连接，如果已经达到，就等待一定的时间（timeout）。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户，如果等待时间
超过预定时间timeout,则返回空值（null）。系统对已经分配出去正在使用的连接只做计数，当使用完后再返还给空闲池。对于空闲连接的状态，可开
辟专门的线程定时检测，这样会花费一定的系统开销，但可以保证较快的响应速度。也可采取不开辟专门线程，只是在分配前检测的方法。<br /><br />　　5、连接池的配置与维护<br /><br />　
　连接池中到底应该放置多少连接，才能使系统的性能最佳？系统可采取设置最小连接数（minConn）和最大连接数（maxConn）来控制连接池中的连
接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多，则系统启动就慢，但创建后系统的响应速度会很快；如果创建过少，则系统启动的很快，响应
起来却慢。这样，可以在开发时，设置较小的最小连接数，开发起来会快，而在系统实际使用时设置较大的，因为这样对访问客户来说速度会快些。最大连接数是连
接池中允许连接的最大数目，具体设置多少，要看系统的访问量，可通过反复测试，找到最佳点。<br /><br />　　如何确保连接池中的最小连接数呢？有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测，如果发现连接数量小于最小连接数，则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。<br /><br />　　<b>连接池的实现</b><br /><br />　　1、连接池模型<br /><br />　
　本文讨论的连接池包括一个连接池类（DBConnectionPool）和一个连接池管理类（DBConnetionPoolManager）。连接池
类是对某一数据库所有连接的“缓冲池”，主要实现以下功能：①从连接池获取或创建可用连接；②使用完毕之后，把连接返还给连接池；③在系统关闭前，断开所
有连接并释放连接占用的系统资源；④还能够处理无效连接（原来登记为可用的连接，由于某种原因不再可用，如超时，通讯问题），并能够限制连接池中的连接总
数不低于某个预定值和不超过某个预定值。<br /><br />　　连接池管理类是连接池类的外覆类（wrapper）,符合单例模式，即系统中只能有一个连接
池管理类的实例。其主要用于对多个连接池对象的管理，具有以下功能：①装载并注册特定数据库的JDBC驱动程序；②根据属性文件给定的信息，创建连接池对
象；③为方便管理多个连接池对象，为每一个连接池对象取一个名字，实现连接池名字与其实例之间的映射；④跟踪客户使用连接情况，以便需要是关闭连接释放资
源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理，如系统需要连接不同的数据库，或连接相同的数据库但由于安全性问题，需要不同的用户使用
不同的名称和密码。<br /><br />　　2、连接池实现<br /><br />　　下面给出连接池类和连接池管理类的主要属性及所要实现的基本接口：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>public class DBConnectionPool implements TimerListener{<br />private int checkedOut;//已被分配出去的连接数<br />private ArrayList freeConnections = new ArrayList();//容器，空闲池，根据//创建时间顺序存放已创建但尚未分配出去的连接<br />private int minConn;//连接池里连接的最小数量<br />private int maxConn;//连接池里允许存在的最大连接数<br />private String name;//为这个连接池取个名字，方便管理<br />private String password;//连接数据库时需要的密码<br />private String url;//所要创建连接的数据库的地址<br />private String user;//连接数据库时需要的用户名<br />public Timer timer;//定时器<br />public DBConnectionPool(String name, String URL, String user, String <br />password, int maxConn)//公开的构造函数<br />public synchronized void freeConnection(Connection con) //使用完毕之后，//把连接返还给空闲池<br />public synchronized Connection getConnection(long timeout)//得到一个连接，//timeout是等待时间<br />public synchronized void release()//断开所有连接，释放占用的系统资源<br />private Connection newConnection()//新建一个数据库连接<br />public synchronized void TimerEvent() //定时器事件处理函数<br /><br />}<br /><br />public class DBConnectionManager {<br />static private DBConnectionManager instance;//连接池管理类的唯一实例<br />static private int clients;//客户数量<br />private ArrayList drivers = new ArrayList();//容器，存放数据库驱动程序<br /><br />private HashMap pools = new HashMap ();//以name/value的形式存取连接池//对象的名字及连接池对象<br />static synchronized public DBConnectionManager getInstance()//如果唯一的//实例instance已经创建，直接返回这个实例;否则，调用私有构造函数，创//建连接池管理类的唯一实例 <br /><br />private DBConnectionManager()//私有构造函数,在其中调用初始化函数init()<br /><br />public void freeConnection(String name, Connection con)// 释放一个连接，//name是一个连接池对象的名字<br /><br />public Connection getConnection(String name)//从名字为name的连接池对象//中得到一个连接<br /><br />public Connection getConnection(String name, long time)//从名字为name<br /><br />//的连接池对象中取得一个连接，time是等待时间<br /><br />public synchronized void release()//释放所有资源<br /><br />private void createPools(Properties props)//根据属性文件提供的信息，创建//一个或多个连接池<br /><br />private void init()//初始化连接池管理类的唯一实例，由私有构造函数调用<br /><br />private void loadDrivers(Properties props)//装载数据库驱动程序<br /><br />} </td></tr></tbody></table><br />　　3、连接池使用<br /><br />　　上面所实现的连接池在程序开发时如何应用到系统中呢？下面以Servlet为例说明连接池的使用。<br /><br />　　Servlet的生命周期是：在开始建立servlet时，调用其初始化（init）方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后，当服务器决定卸载一个servlet时，它首先调用该servlet的 destroy方法。<br /><br />　　根据servlet的特点，我们可以在初始化函数中生成连接池管理类的唯一实例（其中包括创建一个或多个连接池）。如：<br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>public void init() throws ServletException<br />{<br />　connMgr = DBConnectionManager.getInstance(); <br />} </td></tr></tbody></table><br />　　然后就可以在service方法中通过连接池名称使用连接池，执行数据库操作。最后在destroy方法中释放占用的系统资源，如： <br /><br /><table align="center" bgcolor="#e3e3e3" border="1" bordercolor="#cccccc" width="90%"><tbody><tr><td>public void destroy() { <br />　connMgr.release(); super.destroy(); <br />}</td></tr></tbody></table><br />　　<b>结束语</b><br /><br />　
　在使用JDBC进行与数据库有关的应用开发中，数据库连接的管理是一个难点。很多时候，连接的混乱管理所造成的系统资源开销过大成为制约大型企业级应用
效率的瓶颈。对于众多用户访问的Web应用，采用数据库连接技术的系统在效率和稳定性上比采用传统的其他方式的系统要好很多。本文阐述了使用JDBC访问
数据库的技术﹑讨论了基于连接池技术的数据库连接管理的关键问题并给出了一个实现模型。文章所给出的是连接池管理程序的一种基本模式，为提高系统的整体性
能，在此基础上还可以进行很多有<img src ="http://www.blogjava.net/JafeLee/aggbug/120559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-05-28 21:45 <a href="http://www.blogjava.net/JafeLee/articles/120559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用jsp实现session登陆时间的验证.相当与一个监听器 （转载）</title><link>http://www.blogjava.net/JafeLee/articles/120351.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Sun, 27 May 2007 14:14:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/120351.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/120351.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/120351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/120351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/120351.html</trackback:ping><description><![CDATA[原文链接：<a href="http://blog.csdn.net/jhaij/archive/2007/05/03/1595539.aspx">http://blog.csdn.net/jhaij/archive/2007/05/03/1595539.aspx</a><br /><br /><p>1.在login_do.jsp登录成功的前面加上<br />session.setAttribute("user",model);<br />model里面放的是用户名和密码。<br />user是供后面要用到的，也可以说是指针，或键，model是值</p><p>2.单独写一个sessionCheck.jsp文件用来验证session<br />&lt;%<br />Object obj = session.getAttribute("user");<br />if(obj==null){<br />out.print("你没有登录");<br />response.sendRedirect("../login.jsp");<br />}else{<br />UserModel model=(UserModel)obj;<br />}<br />%&gt;<br />=-----------------------------==<br />我来逐行解释<br />第一行是设置一个键，这个键跟它的值是成对存在的。<br />其实就是通过这个键，来操作他的值。<br />如果键为空，就是值为空。<br />那么您没登录，因为登录过后，里面一定会有帐户和密码<br />否则。。。。请离开<br />如果不为空，把键强制转化成值</p>3.上面两部做完了，下面最重要的一步。<br />在每个，jsp文件的头部包含下面的语句<br />&lt;%@include  file="../sessionCheck.jsp"%&gt;<br />这样如果你没登录就想访问这个页面的时候。它会先执行sessionCheck.jsp来<br />检验帐户密码是否为空。<br />没登录当然就为空了 <img src ="http://www.blogjava.net/JafeLee/aggbug/120351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-05-27 22:14 <a href="http://www.blogjava.net/JafeLee/articles/120351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>攻破JNDI连接池(Tomcat5.5下通过管理界面配置连接池)  （转载）</title><link>http://www.blogjava.net/JafeLee/articles/120248.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Sun, 27 May 2007 01:17:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/120248.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/120248.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/120248.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/120248.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/120248.html</trackback:ping><description><![CDATA[原文链接： <span class="t18"><a href="http://www.knowsky.com/344253.html">http://www.knowsky.com/344253.html</a><br /><br />攻破JNDI连接池- -<br />                                       <br />经过几天的努力，终于可以连接上连接池了，其中参考了很多大侠关于这方面的贴子，现在将这几天出现的几个问题写在这里:<br /><br />一.
在tomcat_home\common下放入jdbc的三个驱动程序(一定要的哦)，可以在微软的网站上去下载，安装的SQLSERVER2k默认的用
户名是sa,密码是空，但密码为空并不代表没有密码，所以你的url中一定要定义username和password，最好是重设定一下密码<br /><br />二.出现不能引用错误的话一般就是路径没有写对，tomcat默认的路径是tomcat_home\webapps\不过使用5.5.x的话，按下面方法就行，不需要配置路径，而且也不用在youwebapp\WEB-INF\web.xml文件配置引用<br /><br />三.
tomcat5.5.x版的server.xml配置与tomcat5.0的配置不同，下面列举三种在tomcat5.5.x的配置方法，如果配置不正确
会出现javax.naming.NameNotFoundException: Name is not bound in this
Context 错误<br /><br /><br />方式一、全局数据库连接池<br />1、通过管理界面配置连接池，或者直接在tomcat\conf\server.xml的GlobalNamingResources中增加<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Resource </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="jdbc/mydb"</span><span style="color: rgb(255, 0, 0);"> <br />type</span><span style="color: rgb(0, 0, 255);">="javax.sql.DataSource"</span><span style="color: rgb(255, 0, 0);"> <br />password</span><span style="color: rgb(0, 0, 255);">="mypwd"</span><span style="color: rgb(255, 0, 0);"> <br />driverClassName</span><span style="color: rgb(0, 0, 255);">="com.microsoft.jdbc.sqlserver.SQLServerDriver"</span><span style="color: rgb(255, 0, 0);"> <br />maxIdle</span><span style="color: rgb(0, 0, 255);">="2"</span><span style="color: rgb(255, 0, 0);"> <br />maxWait</span><span style="color: rgb(0, 0, 255);">="5000"</span><span style="color: rgb(255, 0, 0);"> <br />validationQuery</span><span style="color: rgb(0, 0, 255);">="select 1"</span><span style="color: rgb(255, 0, 0);"> <br />username</span><span style="color: rgb(0, 0, 255);">="sa"</span><span style="color: rgb(255, 0, 0);"> <br />url</span><span style="color: rgb(0, 0, 255);">="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"</span><span style="color: rgb(255, 0, 0);"><br />maxActive</span><span style="color: rgb(0, 0, 255);">="4"</span><span style="color: rgb(0, 0, 255);">/&gt;</span></div><br />2、在tomcat\webapps\myapp\META-INF\context.xml的Context中增加：<br />&lt;ResourceLink global="jdbc/mydb" name="jdbc/mydb" type="javax.sql.DataSource"/&gt;<br />这样就可以了。<br /><br />方式二、全局数据库连接池<br />1、同上<br />2、在tomcat\conf\context.xml的Context中增加：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">ResourceLink </span><span style="color: rgb(255, 0, 0);">global</span><span style="color: rgb(0, 0, 255);">="jdbc/mydb"</span><span style="color: rgb(255, 0, 0);"> name</span><span style="color: rgb(0, 0, 255);">="jdbc/mydb"</span><span style="color: rgb(255, 0, 0);"> type</span><span style="color: rgb(0, 0, 255);">="javax.sql.DataSource"</span><span style="color: rgb(0, 0, 255);">/&gt;</span></div><br /><br /><br />方式三、局部数据库连接池<br />只需在tomcat\webapps\myapps\META-INF\context.xml的Context中增加：<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">Resource </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="jdbc/mydb"</span><span style="color: rgb(255, 0, 0);"> <br />type</span><span style="color: rgb(0, 0, 255);">="javax.sql.DataSource"</span><span style="color: rgb(255, 0, 0);"> <br />password</span><span style="color: rgb(0, 0, 255);">="mypwd"</span><span style="color: rgb(255, 0, 0);"> <br />driverClassName</span><span style="color: rgb(0, 0, 255);">="com.microsoft.jdbc.sqlserver.SQLServerDriver"</span><span style="color: rgb(255, 0, 0);"> <br />maxIdle</span><span style="color: rgb(0, 0, 255);">="2"</span><span style="color: rgb(255, 0, 0);"> <br />maxWait</span><span style="color: rgb(0, 0, 255);">="5000"</span><span style="color: rgb(255, 0, 0);"> <br />validationQuery</span><span style="color: rgb(0, 0, 255);">="select 1"</span><span style="color: rgb(255, 0, 0);"> <br />username</span><span style="color: rgb(0, 0, 255);">="sa"</span><span style="color: rgb(255, 0, 0);"> url</span><span style="color: rgb(0, 0, 255);">="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"</span><span style="color: rgb(255, 0, 0);"> <br />maxActive</span><span style="color: rgb(0, 0, 255);">="4"</span><span style="color: rgb(0, 0, 255);">/&gt;</span></div><br />参数说明：<br />driveClassName：JDBC驱动类的完整的名称； <br />maxActive：同时能够从连接池中被分配的可用实例的最大数； <br />maxIdle：可以同时闲置在连接池中的连接的最大数； <br />maxWait：最大超时时间，以毫秒计； <br />password：用户密码； <br />url：到JDBC的URL连接； <br />user：用户名称； <br />validationQuery：用来查询池中空闲的连接。<br />以上三种方式在tomcat 5.5.4下都可以。另外，sql server的jdbc driver是从微软网站上下载的sql server jdbc (sp3)。<br /><br />四.
报错org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create
PoolableConnectionFactory ([Microsoft][SQLServer 2000 Driver for
JDBC]Error establishing
socket.)此是一个小问题，因为我的SQLSERVER2K的服务改成手动的，所以每次启动后就要手动的启动SQLSERVER2K，由于一下子不
记的启动了，所以报些错误，所以如果你经常要用到SQLSERVER2K的话，最好不要将其改为手动启动</span><img src ="http://www.blogjava.net/JafeLee/aggbug/120248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-05-27 09:17 <a href="http://www.blogjava.net/JafeLee/articles/120248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat5.5.17安装admin管理插件 (转载）</title><link>http://www.blogjava.net/JafeLee/articles/120235.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Sat, 26 May 2007 15:43:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/120235.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/120235.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/120235.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/120235.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/120235.html</trackback:ping><description><![CDATA[
		<div class="cnt">
				<p>
						<font size="5">原文链接：<a href="http://hi.baidu.com/dxtao/blog/item/610bc6950674f54bd1135e14.html">http://hi.baidu.com/dxtao/blog/item/610bc6950674f54bd1135e14.html</a><br /></font>
				</p>
				<p>
						<font size="5">
								<br />
						</font>
				</p>
				<p>
						<font size="5">
								<br />
						</font>
				</p>
				<p>
						<font size="5">Tomcat5.5.17安装admin管理插件</font>
				</p>
				<div>
						<div>
								<span>
										<h4>Tomcat 及Tomcat 管理模块的下载:<br />
Tomcat5.0以后的版本是不直接安装管理插件的，因此需要单独下载。<br />
apache-tomcat-5.5.17.zip<br />
下载地址： <a href="http://www.apache.org/dist/tomcat/tomcat-5/v5.5.17/bin/apache-tomcat-5.5.17.zip"><u><font color="#0000ff">http://www.apache.org/dist/tomcat/tomcat-5/v5.5.17/bin/apache-tomcat-5.5.17.zip</font></u></a><br />
图形管理插件:jakarta-tomcat-5.5.17-admin<br />
下载地址:<a target="_blank" href="http://apache.justdn.org/tomcat/tomcat-5/v5.5.17/bin/apache-tomcat-5.5.17-admin.zip">http://apache.justdn.org/tomcat/tomcat-5/v5.5.17/bin/apache-tomcat-5.5.17-admin.zip<br /></a>下载后，解压缩，<br />
2.将管理包解压,解压后的文件夹包含conf,server以及其他三个文件，三个单独的文件可以不用管。将\conf\Catalina\
localhost\文件夹里面的admin.xml拷贝到你的【tomcat的安装目录】\conf\Catalina\localhost\文件夹里
面，再将\server\webapps\文件夹里面的admin文件夹整个拷贝到【tomcat的安装目录】\server\webapps\文件夹
中。这样就安装完了。
<div><br />3.要想管理模块能够顺利运行，那么还要保证一点：确保设置了CATALINA_HOME这个系统环境变量，变量的值为你的
tomcat的安装目录。如果你不愿意设置环境变量，那么也有一个方法，就是将【tomcat的安装目录】\server\webapps\admin\
admin.xml和【tomcat的安装目录】\conf\Catalina\localhost\admin.xml文件中<br />
antiResourceLocking="false" antiJARLocking="false"&gt;一行里的${catalina.home}改成你的tomcat的安装路径就可以了。</div><div><br />
4.好了，最后打开<a href="http://localhost:8080/admin/"><u><font color="#0000ff">http://localhost:8080/admin/</font></u></a>就可以看见登陆界面了，然后用你安装tomcat时所设置的用户名密码登陆就可以了。</div></h4>
								</span>
						</div>
				</div>
		</div>
<img src ="http://www.blogjava.net/JafeLee/aggbug/120235.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-05-26 23:43 <a href="http://www.blogjava.net/JafeLee/articles/120235.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA面试题集  （转载）</title><link>http://www.blogjava.net/JafeLee/articles/119252.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Tue, 22 May 2007 15:28:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/119252.html</guid><description><![CDATA[原文链接：<a href="http://simie.blog.hexun.com/6714285_d.html">http://simie.blog.hexun.com/6714285_d.html</a><br /><br />基础知识：<br />1.C++或Java中的异常处理机制的简单原理和应用。<br />当JAVA程序违反了JAVA的语义规则时，JAVA虚拟机就会将发
生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发
IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就是JAVA允
许程序员扩展这种语义检查，程序员可以创建自己的异常，并自由选择在何时用throw关键字引发异常。所有的异常都是
java.lang.Thowable的子类。<br />2. Java的接口和C++的虚类的相同和不同处。<br />由于Java不支持多继承，而有可能
某个类或对象要使用分别在几个类或对象里面的方法或属性，现有的单继承机制就不能满足要求。与继承相比，接口有更高的灵活性，因为接口中没有任何实现代
码。当一个类实现了接口以后，该类要实现接口里面所有的方法和属性，并且接口里面的属性在默认状态下面都是public
static,所有方法默认情况下是public.一个类可以实现多个接口。<br />3. 垃圾回收的优点和原理。并考虑2种回收机制。<br />Java
语言中一个显著的特点就是引入了垃圾回收机制，使c++程序员最头疼的内存管理的问题迎刃而解，它使得Java程序员在编写程序的时候不再需要考虑内存管
理。由于有个垃圾回收机制，Java中的对象不再有“作用域”的概念，只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露，有效的使用可以使
用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行，不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收，程序员不能
实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收，增量垃圾回收。<br />4. 请说出你所知道的线程同步的方法。<br />wait():使一个线程处于等待状态，并且释放所持有的对象的lock。<br />sleep():使一个正在运行的线程处于睡眠状态，是一个静态方法，调用此方法要捕捉InterruptedException异常。<br />notify():唤醒一个处于等待状态的线程，注意的是在调用此方法的时候，并不能确切的唤醒某一个等待状态的线程，而是由JVM确定唤醒哪个线程，而且不是按优先级。<br />Allnotity():唤醒所有处入等待状态的线程，注意并不是给所有唤醒线程一个对象的锁，而是让它们竞争。<br />5. 请讲一讲析构函数和虚函数的用法和作用。<br />6. Error与Exception有什么区别？<br />Error表示系统级的错误和程序不必处理的异常，<br />Exception表示需要捕捉或者需要程序进行处理的异常。<br />7. 在java中一个类被声明为final类型，表示了什么意思？<br />表示该类不能被继承，是顶级类。<br />8. 描述一下你最常用的编程风格。 <br />9. heap和stack有什么区别。<br />栈是一种线形集合，其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。<br />堆是栈的一个组成元素<br />10. 如果系统要使用超大整数（超过long长度范围），请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算）。<br />public class BigInt()<br />{<br />int[] ArrOne = new ArrOne[1000];<br />String intString="";<br />public int[] Arr(String s)<br />{<br />intString = s;<br />for(int i=0;i&lt;ArrOne.leght;i++)<br />{<br />11. 如果要设计一个图形系统，请你设计基本的图形元件(Point,Line,Rectangle,Triangle)的简单实现<br />12，谈谈final, finally, finalize的区别。 <br />　
　final—修饰符（关键字）如果一个类被声明为final，意味着它不能再派生出新的子类，不能作为父类被继承。因此一个类不能既被声明为
abstract的，又被声明为final的。将变量或方法声明为final，可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定
初值，而在以后的引用中只能读取，不可修改。被声明为final的方法也同样只能使用，不能重载。 <br />　　finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常，那么相匹配的 catch 子句就会执行，然后控制就会进入 finally 块（如果有的话）。<br />　
　finalize—方法名。Java 技术允许使用 finalize()
方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在
Object 类中定义的，因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize()
方法是在垃圾收集器删除对象之前对这个对象调用的。 <br />13，Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类，是否可以implements(实现)interface(接口)? <br />　　匿名的内部类是没有名字的内部类。不能extends(继承) 其它类，但一个内部类可以作为一个接口，由另一个内部类实现。 <br />14，Static Nested Class 和 Inner Class的不同，说得越多越好(面试题有的很笼统)。<br />　
　Nested Class （一般是C++的说法），Inner Class
(一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http:
//www.frontfree.net/articles/services/view.asp?id=704&amp;page=1 <br />　　注： 静态内部类（Inner Class）意味着1创建一个static内部类的对象，不需要一个外部类对象，2不能从一个static内部类的一个对象访问一个外部类对象 <br />第四，&amp;和&amp;&amp;的区别。<br />　　&amp;是位运算符。&amp;&amp;是布尔逻辑运算符。 <br />15，HashMap和Hashtable的区别。<br />　　都属于Map接口的类，实现了将惟一键映射到特定的值上。<br />　　HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。<br />　　Hashtable 类似于 HashMap，但是不允许 null 键和 null 值。它也比 HashMap 慢，因为它是同步的。 <br />16，Collection 和 Collections的区别。<br />　　Collections是个java.util下的类，它包含有各种有关集合操作的静态方法。<br />　　Collection是个java.util下的接口，它是各种集合结构的父接口。 <br />17，什么时候用assert。<br />　　断言是一个包含布尔表达式的语句，在执行这个语句时假定该表达式为 true。如果表达式计算为 false，那么系统会报告一个 Assertionerror。它用于调试目的：<br />assert(a &gt; 0); // throws an Assertionerror if a &lt;= 0 <br />断言可以有两种形式：<br />assert Expression1 ; <br />assert Expression1 : Expression2 ; <br />　　Expression1 应该总是产生一个布尔值。<br />　　Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试信息的 String 消息。<br />　　断言在默认情况下是禁用的。要在编译时启用断言，需要使用 source 1.4 标记：<br />　　javac -source 1.4 Test.java <br />　　要在运行时启用断言，可使用 -enableassertions 或者 -ea 标记。<br />　　要在运行时选择禁用断言，可使用 -da 或者 -disableassertions 标记。<br />　　要系统类中启用断言，可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用断言。 <br />　
　可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过，断言不应该用于验证传递给公有方法的参数，因为不管
是否启用了断言，公有方法都必须检查其参数。不过，既可以在公有方法中，也可以在非公有方法中利用断言测试后置条件。另外，断言不应该以任何方式改变程序
的状态。 <br />18，GC是什么? 为什么要有GC? (基础)。<br />　　GC是垃圾收集器。Java 程序员不用担心内存管理，因为垃圾收集器会自动进行管理。要请求垃圾收集，可以调用下面的方法之一：<br />System.gc() <br />Runtime.getRuntime().gc() <br />19，String s = new String("xyz");创建了几个String Object? <br />　　两个对象，一个是“xyx”,一个是指向“xyx”的引用对象s。 <br />20，Math.round(11.5)等於多少? Math.round(-11.5)等於多少? <br />　　Math.round(11.5)返回（long）12，Math.round(-11.5)返回（long）-11; <br />21，short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错? <br />　　short s1 = 1; s1 = s1 + 1;有错，s1是short型，s1+1是int型,不能显式转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。 <br />22，sleep() 和 wait() 有什么区别? 搞线程的最爱<br />　　sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后，线程不一定立即恢复执行。这是因为在那个时刻，其它线程可能正在运行而且没有被调度为放弃执行，除非(a)“醒来”的线程具有更高的优先级 (b)正在运行的线程因为其它原因而阻塞。<br />　　wait()是线程交互时，如果线程对一个同步对象x 发出一个wait()调用，该线程会暂停执行，被调对象进入等待状态，直到被唤醒或等待时间到。 <br />23，Java有没有goto? <br />　　Goto—java中的保留字，现在没有在java中使用。 <br />24，数组有没有length()这个方法? String有没有length()这个方法？<br />　　数组没有length()这个方法，有length的属性。<br />　　String有有length()这个方法。 <br />25，Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型? <br />　
　方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表
现，重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数，我们说该方法被重写
(Overriding)。子类的对象使用这个方法时，将调用子类中的定义，对它而言，父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方
法，它们或有不同的参数个数或有不同的参数类型，则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。 <br />26，Set里的元素是不能重复的，那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别? <br />　　Set里的元素是不能重复的，那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。<br />　　equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖，为的是当两个分离的对象的内容和类型相配的话，返回真值。 <br />27，给我一个你最常见到的runtime exception。<br />ArithmeticException,
ArrayStoreException, BufferOverflowException, BufferUnderflowException,
CannotRedoException, CannotUndoException, ClassCastException,
CMMException, ConcurrentModificationException, DOMException,
EmptyStackException, IllegalArgumentException,
IllegalMonitorStateException, IllegalPathStateException,
IllegalStateException, <br />ImagingOpException,
IndexOutOfBoundsException, MissingResourceException,
NegativeArraySizeException, NoSuchElementException,
NullPointerException, ProfileDataException, ProviderException,
RasterFORMatException, SecurityException, SystemException,
UndeclaredThrowableException, UnmodifiableSetException,
UnsupportedOperationException <br />28，error和exception有什么区别? <br />　　error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。<br />　　exception 表示一种设计或实现问题。也就是说，它表示如果程序运行正常，从不会发生的情况。 <br />29，List, Set, Map是否继承自Collection接口? <br />List，Set是 <br />Map不是 <br />30，abstract class和interface有什么区别? <br />　
　声明方法的存在而不去实现它的类被叫做抽象类（abstract
class），它用于要创建一个体现某些基本行为的类，并为该类声明方法，但不能在该类中实现该类的情况。不能创建abstract
类的实例。然而可以创建一个变量，其类型是一个抽象类，并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract
类的子类为它们父类中的所有抽象方法提供实现，否则它们也是抽象类为。取而代之，在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。<br />　
　接口（interface）是抽象类的变体。在接口中，所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的，没有一
个有程序体。接口只可以定义static
final成员变量。接口的实现与子类相似，除了该实现类不能从接口定义中继承行为。当类实现特殊接口时，它定义（即将程序体给予）所有这种接口的方法。
然后，它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类，它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到
接口类型或从接口类型转换，instanceof 运算符可以用来决定某对象的类是否实现了接口。<br />31，abstract的method是否可同时是static,是否可同时是native，是否可同时是synchronized? <br />　　都不能 <br />32，接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? <br />　　接口可以继承接口。抽象类可以实现(implements)接口，抽象类是否可继承实体类，但前提是实体类必须有明确的构造函数。 <br />33，启动一个线程是用run()还是start()? <br />　　启动一个线程是调用start()方法，使线程所代表的虚拟处理机处于可运行状态，这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。 <br />34，构造器Constructor是否可被override? <br />　　构造器Constructor不能被继承，因此不能重写Overriding，但可以被重载Overloading。 <br />35，是否可以继承String类? <br />　　String类是final类故不可以继承。 <br />36，当一个线程进入一个对象的一个synchronized方法后，其它线程是否可进入此对象的其它方法? <br />　　不能，一个对象的一个synchronized方法只能由一个线程访问。 <br />37，try {}里有一个return语句，那么紧跟在这个try后的finally {}里的code会不会被执行，什么时候被执行，在return前还是后? <br />　　会执行，在return前执行。 <br />38，编程题: 用最有效率的方法算出2乘以8等於几? <br />　　有C背景的程序员特别喜欢问这种问题。 <br />　　2 &lt;&lt; 3 <br />39，两个对象值相同(x.equals(y) == true)，但却可有不同的hash code，这句话对不对? <br />　　不对，有相同的hash code。 <br />40，当一个对象被当作参数传递到一个方法后，此方法可改变这个对象的属性，并可返回变化后的结果，那么这里到底是值传递还是引用传递? <br />　　是值传递。Java 编程语言只由值传递参数。当一个对象实例作为一个参数被传递到方法中时，参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变，但对象的引用是永远不会改变的。 <br />41，swtich是否能作用在byte上，是否能作用在long上，是否能作用在String上?<br />　　switch（expr1）中，expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。 <br />42，编程题: 写一个Singleton出来。<br />　　Singleton模式主要作用是保证在Java应用程序中，一个类Class只有一个实例存在。<br />　　一般Singleton模式通常有几种种形式：<br />　　第一种形式：定义一个类，它的构造函数为private的，它有一个static的private的该类变量，在类初始化时实例话，通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。<br />public class Singleton { <br />　　private Singleton(){} <br />　　//在自己内部定义自己一个实例，是不是很奇怪？ <br />　　//注意这是private 只供内部调用 <br />　　private static Singleton instance = new Singleton(); <br />　　//这里提供了一个供外部访问本class的静态方法，可以直接访问　　 <br />　　public static Singleton getInstance() { <br />　　　　return instance; 　　 <br />　　 } <br />} <br />　　第二种形式：<br />public class Singleton { <br />　　private static Singleton instance = null; <br />　　public static synchronized Singleton getInstance() { <br />　　//这个方法比上面有所改进，不用每次都进行生成对象，只是第一次　　　 　 <br />　　//使用时生成实例，提高了效率！ <br />　　if (instance==null) <br />　　　　instance＝new Singleton(); <br />return instance; 　　} <br />} <br />其他形式：<br />　　定义一个类，它的构造函数为private的，所有方法为static的。<br />　　一般认为第一种形式要更加安全些 <br />　　Hashtable和HashMap <br />　　Hashtable继承自Dictionary类，而HashMap是Java1.2引进的Map interface的一个实现 <br /><br />　　HashMap允许将null作为一个entry的key或者value，而Hashtable不允许 <br />　　还有就是，HashMap把Hashtable的contains方法去掉了，改成containsvalue和containsKey。因为contains方法容易让人引起误解。 <br />　　最大的不同是，Hashtable的方法是Synchronize的，而HashMap不是，在 <br />多个线程访问Hashtable时，不需要自己为它的方法实现同步，而HashMap <br />就必须为之提供外同步。 <br />Hashtable和HashMap采用的hash/rehash算法都大概一样，所以性能不会有很大的差异。<br />43.描述一下JVM加载class文件的原理机制?<br />44.试举例说明一个典型的垃圾回收算法？ <br />45.请用java写二叉树算法，实现添加数据形成二叉树功能，并以先序的方式打印出来. <br />46.请写一个java程序实现线程连接池功能？ <br />47.给定一个C语言函数，要求实现在java类中进行调用。<br />48、编一段代码，实现在控制台输入一组数字后，排序后在控制台输出；<br />49、列出某文件夹下的所有文件；<br />50、调用系统命令实现删除文件的操作；<br />51、实现从文件中一次读出一个字符的操作；<br />52、列出一些控制流程的方法；<br />53、多线程有哪些状态？<br />54、编写了一个服务器端的程序实现在客户端输入字符然后在控制台上显示，直到输入"END"为止，让你写出客户端的程序；<br />55、作用域public,private,protected,以及不写时的区别 <br />答：区别如下： <br />作用域 当前类 同一package 子孙类 其他package <br />public √ √ √ √ <br />protected √ √ √ × <br />friendly √ √ × × <br />private √ × × × <br />不写时默认为friendly <br />56、ArrayList和Vector的区别,HashMap和Hashtable的区别 <br />答：就ArrayList与Vector主要从二方面来说. <br />一.同步性:Vector是线程安全的，也就是说是同步的，而ArrayList是线程序不安全的，不是同步的 <br />二.数据增长:当需要增长时,Vector默认增长为原来一培，而ArrayList却是原来的一半 <br />就HashMap与HashTable主要从三方面来说。 <br />一.历史原因:Hashtable是基于陈旧的Dictionary类的，HashMap是Java 1.2引进的Map接口的一个实现 <br />二.同步性:Hashtable是线程安全的，也就是说是同步的，而HashMap是线程序不安全的，不是同步的 <br />三.值：只有HashMap可以让你将空值作为一个表的条目的key或value <br />57、char型变量中能不能存贮一个中文汉字?为什么? <br />答：是能够定义成为一个中文的，因为java中以unicode编码，一个char占16个字节，所以放一个中文是没问题的 <br />58、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? <br />答：多线程有两种实现方法，分别是继承Thread类与实现Runnable接口 <br />同步的实现方面有两种，分别是synchronized,wait与notify<br />59、垃圾回收机制,如何优化程序?  <br />60、float型float f=3.4是否正确? <br />答:不正确。精度不准确,应该用强制类型转换，如下所示：float f=(float)3.4 <br />61、介绍JAVA中的Collection FrameWork(包括如何写自己的数据结构)? <br />答：Collection FrameWork如下： <br />Collection <br />├List <br />│├LinkedList <br />│├ArrayList <br />│└Vector <br />│　└Stack <br />└Set <br />Map <br />├Hashtable <br />├HashMap <br />└WeakHashMap <br />Collection是最基本的集合接口，一个Collection代表一组Object，即Collection的元素（Elements） <br />Map提供key到value的映射 <br />62、Java中异常处理机制，事件机制？ <br />11、JAVA中的多形与继承？ <br />希望大家补上，谢谢 <br />63、抽象类与接口？ <br />答：抽象类与接口都用于抽象，但是抽象类(JAVA中)可以有自己的部分实现，而接口则完全是一个标识(同时有多重继承的功能)。<br />编程题：<br />1．现在输入n个数字，以逗号，分开；<br />然后可选择升或者降序排序；<br />按提交键就在另一页面显示<br />按什么 排序，结果为，  ，<br />提供reset<br />答案（1）  public static String[] splitStringByComma(String source){<br />           if(source==null||source.trim().equals(""))<br />                   return null;<br />           StringTokenizer commaToker =  new StringTokenizer(source,",");<br />           String[] result = new String[commaToker.countTokens()];<br />           int i=0;<br />           while(commaToker.hasMoreTokens()){<br />                   result = commaToker.nextToken();<br />                   i++;<br />           }<br />           return result;<br />  }<br />循环遍历String数组<br />Integer.parseInt(String s)变成int类型<br />组成int数组<br />Arrays.sort(int[] a),<br />a数组升序<br />降序可以从尾部开始输出<br />2．金额转换，阿拉伯数字的金额转换成中国传统的形式如：<br />（￥1011）－&gt;（一千零一拾一元整）输出。 <br />3、继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么? <br />答:父类： <br />package test; <br />public class FatherClass <br />{ <br />public FatherClass() <br />{ <br />System.out.println("FatherClass Create"); <br />} <br />} <br />子类: <br />package test; <br />import test.FatherClass; <br />public class ChildClass extends FatherClass <br />{ <br />public ChildClass() <br />{ <br />System.out.println("ChildClass Create"); <br />} <br />public static void main(String[] args) <br />{ <br />FatherClass fc = new FatherClass(); <br />ChildClass cc = new ChildClass(); <br />} <br />} <br />输出结果： <br />C:&gt;java test.ChildClass <br />FatherClass Create <br />FatherClass Create <br />ChildClass Create <br />4、内部类的实现方式? <br />答：示例代码如下： <br />package test; <br />public class OuterClass <br />{ <br />private class InterClass <br />{ <br />public InterClass() <br />{ <br />System.out.println("InterClass Create"); <br />} <br />} <br />public OuterClass() <br />{ <br />InterClass ic = new InterClass(); <br />System.out.println("OuterClass Create"); <br />} <br />public static void main(String[] args) <br />{ <br />OuterClass oc = new OuterClass(); <br />} <br />} <br />输出结果: <br />C:&gt;java test/OuterClass <br />InterClass Create <br />OuterClass Create <br />再一个例题： <br />public class OuterClass { <br />private double d1 = 1.0; <br />//insert code here <br />} <br />You need to insert an inner class declaration at line 3. Which two inner class declarations are <br />valid?(Choose two.) <br />A. class InnerOne{ <br />public static double methoda() {return d1;} <br />} <br />B. public class InnerOne{ <br />static double methoda() {return d1;} <br />} <br />C. private class InnerOne{ <br />double methoda() {return d1;} <br />} <br />D. static class InnerOne{ <br />protected double methoda() {return d1;} <br />} <br />E. abstract class InnerOne{ <br />public abstract double methoda(); <br />} <br />说明如下： <br />一.静态内部类可以有静态成员，而非静态内部类则不能有静态成员。 故 A、B 错 <br />二.静态内部类的非静态成员可以访问外部类的静态变量，而不可访问外部类的非静态变量；return d1 出错。 <br />故 D 错 <br />三.非静态内部类的非静态成员可以访问外部类的非静态变量。 故 C 正确 <br />四.答案为C、E <br />5、Java 的通信编程，编程题(或问答)，用JAVA SOCKET编程，读服务器几个字符，再写入本地显示？ <br />答:Server端程序: <br />package test; <br />import java.net.*; <br />import java.io.*; <br />public class Server <br />{ <br />private ServerSocket ss; <br />private Socket socket; <br />private BufferedReader in; <br />private PrintWriter out; <br />public Server() <br />{ <br />try <br />{ <br />ss=new ServerSocket(10000); <br />while(true) <br />{ <br />socket = ss.accept(); <br />String RemoteIP = socket.getInetAddress().getHostAddress(); <br />String RemotePort = ":"+socket.getLocalPort(); <br />System.out.println("A client come in!IP:"+RemoteIP+RemotePort); <br />in = new BufferedReader(new <br />InputStreamReader(socket.getInputStream())); <br />String line = in.readLine(); <br />System.out.println("Cleint send is :" + line); <br />out = new PrintWriter(socket.getOutputStream(),true); <br />out.println("Your Message Received!"); <br />out.close(); <br />in.close(); <br />socket.close(); <br />} <br />}catch (IOException e) <br />{ <br />out.println("wrong"); <br />} <br />} <br />public static void main(String[] args) <br />{ <br />new Server(); <br />} <br />}; <br />Client端程序: <br />package test; <br />import java.io.*; <br />import java.net.*; <br />public class Client <br />{ <br />Socket socket; <br />BufferedReader in; <br />PrintWriter out; <br />public Client() <br />{ <br />try <br />{ <br />System.out.println("Try to Connect to 127.0.0.1:10000"); <br />socket = new Socket("127.0.0.1",10000); <br />System.out.println("The Server Connected!"); <br />System.out.println("Please enter some Character:"); <br />BufferedReader line = new BufferedReader(new <br />InputStreamReader(System.in)); <br />out = new PrintWriter(socket.getOutputStream(),true); <br />out.println(line.readLine()); <br />in = new BufferedReader(new InputStreamReader(socket.getInputStream())); <br />System.out.println(in.readLine()); <br />out.close(); <br />in.close(); <br />socket.close(); <br />}catch(IOException e) <br />{ <br />out.println("Wrong"); <br />} <br />} <br />public static void main(String[] args) <br />{ <br />new Client(); <br />} <br />}; <br />6、用JAVA实现一种排序，JAVA类实现序列化的方法(二种)？ 如在COLLECTION框架中，实现比较要实现什么样的接口？ <br />答:用插入法进行排序代码如下 <br />package test; <br />import java.util.*; <br />class InsertSort <br />{ <br />ArrayList al; <br />public InsertSort(int num,int mod) <br />{ <br />al = new ArrayList(num); <br />Random rand = new Random(); <br />System.out.println("The ArrayList Sort Before:"); <br />for (int i=0;i&lt;num ;i++ ) <br />{ <br />al.add(new Integer(Math.abs(rand.nextInt()) % mod + 1)); <br />System.out.println("al["+i+"]="+al.get(i)); <br />} <br />} <br />public void SortIt() <br />{ <br />Integer tempInt; <br />int MaxSize=1; <br />for(int i=1;i&lt;al.size();i++) <br />{ <br />tempInt = (Integer)al.remove(i); <br />if(tempInt.intValue()&gt;=((Integer)al.get(MaxSize-1)).intValue()) <br />{ <br />al.add(MaxSize,tempInt); <br />MaxSize++; <br />System.out.println(al.toString()); <br />} else { <br />for (int j=0;j&lt;MaxSize ;j++ ) <br />{ <br />if <br />(((Integer)al.get(j)).intValue()&gt;=tempInt.intValue()) <br />{ <br />al.add(j,tempInt); <br />MaxSize++; <br />System.out.println(al.toString()); <br />break; <br />} <br />} <br />} <br />} <br />System.out.println("The ArrayList Sort After:"); <br />for(int i=0;i&lt;al.size();i++) <br />{ <br />System.out.println("al["+i+"]="+al.get(i)); <br />} <br />} <br />public static void main(String[] args) <br />{ <br />InsertSort is = new InsertSort(10,100); <br />is.SortIt(); <br />} <br />} <br />JAVA类实现序例化的方法是实现java.io.Serializable接口 <br />Collection框架中实现比较要实现Comparable 接口和 Comparator 接口 <br />7、编程：编写一个截取字符串的函数，输入为一个字符串和字节数，输出为按字节截取的字符串。 但是要保证汉字不被截半个，如“我ABC”4，应该截为“我AB”，输入“我ABC汉DEF”，6，应该输出为“我ABC”而不是“我ABC+汉的半个”。 <br />答：代码如下： <br />package test; <br />class SplitString <br />{ <br />String SplitStr; <br />int SplitByte; <br />public SplitString(String str,int bytes) <br />{ <br />SplitStr=str; <br />SplitByte=bytes; <br />System.out.println("The String is:′"+SplitStr+"′;SplitBytes="+SplitByte); <br />} <br />public void SplitIt() <br />{ <br />int loopCount; <br />loopCount=(SplitStr.length()%SplitByte==0)?(SplitStr.length()/SplitByte):(SplitStr.length()/Split <br />Byte+1); <br />System.out.println("Will Split into "+loopCount); <br />for (int i=1;i&lt;=loopCount ;i++ ) <br />{ <br />if (i==loopCount){ <br />System.out.println(SplitStr.substring((i-1)*SplitByte,SplitStr.length())); <br />} else { <br />System.out.println(SplitStr.substring((i-1)*SplitByte,(i*SplitByte))); <br />} <br />} <br />} <br />public static void main(String[] args) <br />{ <br />SplitString ss = new SplitString("test中dd文dsaf中男大3443n中国43中国人 <br />0ewldfls=103",4); <br />ss.SplitIt(); <br />} <br />} <br />8、JAVA多线程编程。 用JAVA写一个多线程程序，如写四个线程，二个加1，二个对一个变量减一，输出。 <br /><br />希望大家补上，谢谢 <br /><br />9、STRING与STRINGBUFFER的区别。 <br /><br />答：STRING的长度是不可变的，STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作，特别是内容要修改时，那么使用StringBuffer，如果最后需要String，那么使用StringBuffer的toString()方法 <br /><br />Jsp方面 <br /><br />1、jsp有哪些内置对象?作用分别是什么? <br /><br />答:JSP共有以下9种基本内置组件（可与ASP的6种内部组件相对应）： <br /><br />　request 用户端请求，此请求会包含来自GET/POST请求的参数 <br /><br />response 网页传回用户端的回应 <br /><br />pageContext 网页的属性是在这里管理 <br /><br />session 与请求有关的会话期 <br /><br />application servlet 正在执行的内容 <br /><br />out 用来传送回应的输出 <br /><br />config servlet的构架部件 <br /><br />page JSP网页本身 <br /><br />exception 针对错误网页，未捕捉的例外 <br /><br />2、jsp有哪些动作?作用分别是什么? <br /><br />答:JSP共有以下6种基本动作 <br /><br />jsp:include：在页面被请求的时候引入一个文件。 <br /><br />jsp:useBean：寻找或者实例化一个JavaBean。 <br /><br />jsp:setProperty：设置JavaBean的属性。 <br /><br />jsp:getProperty：输出某个JavaBean的属性。 <br /><br />jsp:forward：把请求转到一个新的页面。 <br /><br />jsp:plugin：根据浏览器类型为Java插件生成OBJECT或EMBED标记 <br /><br />3、JSP中动态INCLUDE与静态INCLUDE的区别？ <br /><br />答：动态INCLUDE用jsp:include动作实现 <br /><br />&lt;jsp:include page="included.jsp" flush="true" /&gt;它总是会检查所含文件中的变化，适合用于包含动态页面，并且可以带参数 <br /><br />静态INCLUDE用include伪码实现,定不会检查所含文件的变化，适用于包含静态页面 <br /><br />&lt;%@ include file="included.htm" %&gt; <br /><br />4、两种跳转方式分别是什么?有什么区别? <br /><br />答：有两种，分别为： <br /><br />&lt;jsp:include page="included.jsp" flush="true"&gt; <br /><br />&lt;jsp:forward page= "nextpage.jsp"/&gt; <br /><br />前者页面不会转向include所指的页面，只是显示该页的结果，主页面还是原来的页面。执行完后还会回来，相当于函数调用。并且可以带参数.后者完全转向新页面，不会再回来。相当于go to 语句。 <br /><br />Servlet方面 <br /><br />1、说一说Servlet的生命周期? <br /><br />答:servlet有良好的生存期的定义，包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。 <br /><br />2、Servlet版本间(忘了问的是哪两个版本了)的不同? <br /><br />希望大家补上，谢谢 <br /><br />3、JAVA SERVLET API中forward() 与redirect()的区别？ <br /><br />答:
前者仅是容器中控制权的转向，在客户端浏览器地址栏中不会显示出转向后的地址；后者则是完全的跳转，浏览器将会得到跳转的地址，并重新发送请求链接。这
样，从浏览器的地址栏中可以看到跳转后的链接地址。所以，前者更加高效，在前者可以满足需要时，尽量使用forward()方法，并且，这样也有助于隐藏
实际的链接。在有些情况下，比如，需要跳转到一个其它服务器上的资源，则必须使用sendRedirect()方法。 <br /><br />4、Servlet的基本架构 <br /><br />public class ServletName extends HttpServlet { <br /><br />public void doPost(HttpServletRequest request, HttpServletResponse response) throws <br /><br />ServletException, IOException { <br /><br />} <br /><br />public void doGet(HttpServletRequest request, HttpServletResponse response) throws <br /><br />ServletException, IOException { <br /><br />} <br /><br />} <br /><br /><br /><br />Jdbc、Jdo方面 <br /><br />1、可能会让你写一段Jdbc连Oracle的程序,并实现数据查询. <br /><br />答:程序如下： <br /><br />package hello.ant; <br /><br />import java.sql.*; <br /><br />public class jdbc <br /><br />{ <br /><br />String dbUrl="jdbc:oracle:thin:@127.0.0.1:1521:orcl"; <br /><br />String theUser="admin"; <br /><br />String thePw="manager"; <br /><br />Connection c=null; <br /><br />Statement conn; <br /><br />ResultSet rs=null; <br /><br />public jdbc() <br /><br />{ <br /><br />try{ <br /><br />Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <br /><br />c = DriverManager.getConnection(dbUrl,theUser,thePw); <br /><br />conn=c.createStatement(); <br /><br />}catch(Exception e){ <br /><br />e.printStackTrace(); <br /><br />} <br /><br />} <br /><br />public boolean executeUpdate(String sql) <br /><br />{ <br /><br />try <br /><br />{ <br /><br />conn.executeUpdate(sql); <br /><br />return true; <br /><br />} <br /><br />catch (SQLException e) <br /><br />{ <br /><br />e.printStackTrace(); <br /><br />return false; <br /><br />} <br /><br />} <br /><br />public ResultSet executeQuery(String sql) <br /><br />{ <br /><br />rs=null; <br /><br />try <br /><br />{ <br /><br />rs=conn.executeQuery(sql); <br /><br />} <br /><br />catch (SQLException e) <br /><br />{ <br /><br />e.printStackTrace(); <br /><br />} <br /><br />return rs; <br /><br />} <br /><br />public void close() <br /><br />{ <br /><br />try <br /><br />{ <br /><br />conn.close(); <br /><br />c.close(); <br /><br />} <br /><br />catch (Exception e) <br /><br />{ <br /><br />e.printStackTrace(); <br /><br />} <br /><br />} <br /><br />public static void main(String[] args) <br /><br />{ <br /><br />ResultSet rs; <br /><br />jdbc conn = new jdbc(); <br /><br />rs=conn.executeQuery("select * from test"); <br /><br />try{ <br /><br />while (rs.next()) <br /><br />{ <br /><br />System.out.println(rs.getString("id")); <br /><br />System.out.println(rs.getString("name")); <br /><br />} <br /><br />}catch(Exception e) <br /><br />{ <br /><br />e.printStackTrace(); <br /><br />} <br /><br />} <br /><br />} <br /><br />2、Class.forName的作用?为什么要用? <br /><br />答：调用该访问返回一个以字符串指定类名的类的对象。 <br /><br />3、Jdo是什么? <br /><br />答:
JDO是Java对象持久化的新的规范，为java data
object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储，因此对开发人员来说，存储数据对象完全不需要额
外的代码（如JDBC
API的使用）。这些繁琐的例行工作已经转移到JDO产品提供商身上，使开发人员解脱出来，从而集中时间和精力在业务逻辑上。另外，JDO很灵活，因为它
可以在任何数据底层上运行。JDBC只是面向关系数据库（RDBMS)JDO更通用，提供到任何数据底层的存储功能，比如关系数据库、文件、XML以及对
象数据库（ODBMS）等等，使得应用可移植性更强。 <br /><br />4、在ORACLE大数据量下的分页解决方法。一般用截取ID方法，还有是三层嵌套方法。 <br /><br />答:一种分页方法 <br /><br />&lt;% <br /><br />int i=1; <br /><br />int numPages=14; <br /><br />String pages = request.getParameter("page") ; <br /><br />int currentPage = 1; <br /><br />currentPage=(pages==null)?(1):{Integer.parseInt(pages)} <br /><br />sql = "select count(*) from tables"; <br /><br />ResultSet rs = DBLink.executeQuery(sql) ; <br /><br />while(rs.next()) i = rs.getInt(1) ; <br /><br />int intPageCount=1; <br /><br />intPageCount=(i%numPages==0)?(i/numPages):(i/numPages+1); <br /><br />int nextPage ; <br /><br />int upPage; <br /><br />nextPage = currentPage+1; <br /><br />if (nextPage&gt;=intPageCount) nextPage=intPageCount; <br /><br />upPage = currentPage-1; <br /><br />if (upPage&lt;=1) upPage=1; <br /><br />rs.close(); <br /><br />sql="select * from tables"; <br /><br />rs=DBLink.executeQuery(sql); <br /><br />i=0; <br /><br />while((i&lt;numPages*(currentPage-1))&amp;&amp;rs.next()){i++;} <br /><br />%&gt; <br /><br />//输出内容 <br /><br />//输出翻页连接 <br /><br />合计:&lt;%=currentPage%&gt;/&lt;%=intPageCount%&gt;&lt;a href="List.jsp?page=1"&gt;第一页&lt;/a&gt;&lt;a <br /><br /><br /><br />href="List.jsp?page=&lt;%=upPage%&gt;"&gt;上一页&lt;/a&gt; <br /><br />&lt;% <br /><br />for(int j=1;j&lt;=intPageCount;j++){ <br /><br />if(currentPage!=j){ <br /><br />%&gt; <br /><br />&lt;a href="list.jsp?page=&lt;%=j%&gt;"&gt;[&lt;%=j%&gt;]&lt;/a&gt; <br /><br />&lt;% <br /><br />}else{ <br /><br />out.println(j); <br /><br />} <br /><br />} <br /><br />%&gt; <br /><br />&lt;a href="List.jsp?page=&lt;%=nextPage%&gt;"&gt;下一页&lt;/a&gt;&lt;a href="List.jsp?page=&lt;%=intPageCount%&gt;"&gt;最后页 <br /><br /><br /><br />&lt;/a&gt; <br /><br />Xml方面 <br /><br />1、xml有哪些解析技术?区别是什么? <br /><br />答:有DOM,SAX,STAX等 <br /><br />DOM:
处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的，这种结构占用的内存较多，而且DOM必须在解析文件之前把整个文档装入内存,
适合对XML的随机访问SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件，不需要一次全部装载整个文件。当遇到像文件开
头，文档结束，或者标签开头与标签结束时，它会触发一个事件，用户通过在其回调事件中写入处理代码来处理XML文件，适合对XML的顺序访问 <br /><br />STAX:Streaming API for XML (StAX) <br /><br />2、你在项目中用到了xml技术的哪些方面?如何实现的? <br /><br />答:
用到了数据存贮，信息配置两方面。在做数据交换平台时，将不能数据源的数据组装成XML文件，然后将XML文件压缩打包加密后通过网络传送给接收者，接收
解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时，利用XML可以很方便的进行，软件的各种配置参数都存贮在XML文件中。 <br /><br />3、用jdom解析xml文件时如何解决中文问题?如何解析? <br /><br />答:看如下代码,用编码方式加以解决 <br /><br />package test; <br /><br />import java.io.*; <br /><br />public class DOMTest <br /><br />{ <br /><br />private String inFile = "c:\people.xml"; <br /><br />private String outFile = "c:\people.xml"; <br /><br />public static void main(String args[]) <br /><br />{ <br /><br />new DOMTest(); <br /><br />} <br /><br />public DOMTest() <br /><br />{ <br /><br />try <br /><br />{ <br /><br />javax.xml.parsers.DocumentBuilder builder = <br /><br />javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder(); <br /><br />org.w3c.dom.Document doc = builder.newDocument(); <br /><br />org.w3c.dom.Element root = doc.createElement("老师"); <br /><br />org.w3c.dom.Element wang = doc.createElement("王"); <br /><br />org.w3c.dom.Element liu = doc.createElement("刘"); <br /><br />wang.appendChild(doc.createTextNode("我是王老师")); <br /><br />root.appendChild(wang); <br /><br />doc.appendChild(root); <br /><br />javax.xml.transform.Transformer transformer = <br /><br />javax.xml.transform.TransformerFactory.newInstance().newTransformer(); <br /><br />transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "gb2312"); <br /><br />transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes"); <br />transformer.transform(new javax.xml.transform.dom.DOMSource(doc), <br />new <br />javax.xml.transform.stream.StreamResult(outFile)); <br /><br />} <br /><br />catch (Exception e) <br /><br />{ <br /><br />System.out.println (e.getMessage()); <br /><br />} <br /><br />} <br /><br />} <br /><br />4、编程用JAVA解析XML的方式. <br /><br />答:用SAX方式解析XML，XML文件如下： <br /><br />&lt;?xml version="1.0" encoding="gb2312"?&gt; <br /><br />&lt;person&gt; <br /><br />&lt;name&gt;王小明&lt;/name&gt; <br /><br />&lt;college&gt;信息学院&lt;/college&gt; <br /><br />&lt;telephone&gt;6258113&lt;/telephone&gt; <br /><br />&lt;notes&gt;男,1955年生,博士，95年调入海南大学&lt;/notes&gt; <br /><br />&lt;/person&gt; <br /><br />事件回调类SAXHandler.java <br /><br />import java.io.*; <br /><br />import java.util.Hashtable; <br /><br />import org.xml.sax.*; <br /><br />public class SAXHandler extends HandlerBase <br /><br />{ <br /><br />private Hashtable table = new Hashtable(); <br /><br />private String currentElement = null; <br /><br />private String currentValue = null; <br /><br />public void setTable(Hashtable table) <br /><br />{ <br /><br />this.table = table; <br /><br />} <br /><br />public Hashtable getTable() <br /><br />{ <br /><br />return table; <br /><br />} <br /><br />public void startElement(String tag, AttributeList attrs) <br /><br />throws SAXException <br /><br />{ <br /><br />currentElement = tag; <br /><br />} <br /><br />public void characters(char[] ch, int start, int length) <br /><br />throws SAXException <br /><br />{ <br /><br />currentValue = new String(ch, start, length); <br /><br />} <br /><br />public void endElement(String name) throws SAXException <br /><br />{ <br /><br />if (currentElement.equals(name)) <br /><br />table.put(currentElement, currentValue); <br /><br />} <br /><br />} <br /><br />JSP内容显示源码,SaxXml.jsp: <br /><br />&lt;HTML&gt; <br /><br />&lt;HEAD&gt; <br /><br />&lt;TITLE&gt;剖析XML文件people.xml&lt;/TITLE&gt; <br /><br />&lt;/HEAD&gt; <br /><br />&lt;BODY&gt; <br /><br />&lt;%@ page errorPage="ErrPage.jsp" <br /><br />contentType="text/html;charset=GB2312" %&gt; <br /><br />&lt;%@ page import="java.io.*" %&gt; <br /><br />&lt;%@ page import="java.util.Hashtable" %&gt; <br /><br />&lt;%@ page import="org.w3c.dom.*" %&gt; <br /><br />&lt;%@ page import="org.xml.sax.*" %&gt; <br /><br />&lt;%@ page import="javax.xml.parsers.SAXParserFactory" %&gt; <br /><br />&lt;%@ page import="javax.xml.parsers.SAXParser" %&gt; <br /><br />&lt;%@ page import="SAXHandler" %&gt; <br /><br />&lt;% <br /><br />File file = new File("c:\people.xml"); <br /><br />FileReader reader = new FileReader(file); <br /><br />Parser parser; <br /><br />SAXParserFactory spf = SAXParserFactory.newInstance(); <br /><br />SAXParser sp = spf.newSAXParser(); <br /><br />SAXHandler handler = new SAXHandler(); <br /><br />sp.parse(new InputSource(reader), handler); <br /><br />Hashtable hashTable = handler.getTable(); <br /><br />out.println("&lt;TABLE BORDER=2&gt;&lt;CAPTION&gt;教师信息表&lt;/CAPTION&gt;"); <br /><br />out.println("&lt;TR&gt;&lt;TD&gt;姓名&lt;/TD&gt;" + "&lt;TD&gt;" + <br /><br />(String)hashTable.get(new String("name")) + "&lt;/TD&gt;&lt;/TR&gt;"); <br /><br />out.println("&lt;TR&gt;&lt;TD&gt;学院&lt;/TD&gt;" + "&lt;TD&gt;" + <br /><br />(String)hashTable.get(new String("college"))+"&lt;/TD&gt;&lt;/TR&gt;"); <br /><br />out.println("&lt;TR&gt;&lt;TD&gt;电话&lt;/TD&gt;" + "&lt;TD&gt;" + <br /><br />(String)hashTable.get(new String("telephone")) + "&lt;/TD&gt;&lt;/TR&gt;"); <br /><br />out.println("&lt;TR&gt;&lt;TD&gt;备注&lt;/TD&gt;" + "&lt;TD&gt;" + <br /><br />(String)hashTable.get(new String("notes")) + "&lt;/TD&gt;&lt;/TR&gt;"); <br /><br />out.println("&lt;/TABLE&gt;"); <br /><br />%&gt; <br /><br />&lt;/BODY&gt; <br /><br />&lt;/HTML&gt; <br /><br />EJB方面 <br /><br />1、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? <br /><br />答：
规范内容包括Bean提供者，应用程序装配者，EJB容器，EJB配置工具，EJB服务提供者，系统管理员。这里面，EJB容器是EJB之所以能够运行的
核心。EJB容器管理着EJB的创建，撤消，激活，去活，与数据库的连接等等重要的核心工作。JSP,Servlet,EJB,JNDI,JDBC,
JMS..... <br /><br />2、EJB与JAVA BEAN的区别？ <br /><br />答:Java Bean 是可复用的组件，对Java
Bean并没有严格的规范，理论上讲，任何一个Java类都可以是一个Bean。但通常情况下，由于Java
Bean是被容器所创建（如Tomcat)的，所以Java Bean应具有一个无参的构造器，另外，通常Java
Bean还要实现Serializable接口用于实现Bean的持久性。Java
Bean实际上相当于微软COM模型中的本地进程内COM组件，它是不能被跨进程访问的。Enterprise Java Bean
相当于DCOM，即分布式组件。它是基于Java的远程方法调用（RMI）技术的，所以EJB可以被远程访问（跨进程、跨计算机）。但EJB必须被布署在
诸如Webspere、WebLogic这样的容器中，EJB客户从不直接访问真正的EJB组件，而是通过其容器访问。EJB容器是EJB组件的代理，
EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。 <br /><br />3、EJB的基本架构 <br /><br />答:一个EJB包括三个部分: <br /><br />Remote Interface 接口的代码 <br /><br />package Beans; <br /><br />import javax.ejb.EJBObject; <br /><br />import java.rmi.RemoteException; <br /><br />public interface Add extends EJBObject <br /><br />{ <br /><br />//some method declare <br /><br />} <br /><br />Home Interface 接口的代码 <br /><br />package Beans; <br /><br />import java.rmi.RemoteException; <br /><br />import jaax.ejb.CreateException; <br /><br />import javax.ejb.EJBHome; <br /><br />public interface AddHome extends EJBHome <br /><br />{ <br /><br />//some method declare <br /><br />} <br /><br />EJB类的代码 <br /><br />package Beans; <br /><br />import java.rmi.RemoteException; <br /><br />import javax.ejb.SessionBean; <br /><br />import javx.ejb.SessionContext; <br /><br />public class AddBean Implements SessionBean <br /><br />{ <br /><br />//some method declare <br /><br />} <br /><br /><br /><br />J2EE,MVC方面 <br /><br />1、MVC的各个部分都有那些技术来实现?如何实现? <br /><br />答:
MVC是Model－View－Controller的简写。"Model" 代表的是应用的业务逻辑（通过JavaBean，EJB组件实现），
"View" 是应用的表示面（由JSP页面产生），"Controller"
是提供应用的处理过程控制（一般是一个Servlet），通过这种设计模型把应用逻辑，处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重
用。 <br /><br />2、应用服务器与WEB SERVER的区别？ <br /><br />希望大家补上，谢谢 <br /><br />3、J2EE是什么？ <br /><br />答:
Je22是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应
用模型(enterpriese application
model).在这样的一个应用系统中，可按照功能划分为不同的组件，这些组件又可在不同计算机上，并且处于相应的层次(tier)中。所属层次包括客户
层(clietn tier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。 <br /><br />4、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 <br /><br />答：Web Service描述语言WSDL <br /><br />SOAP即简单对象访问协议(Simple Object Access Protocol)，它是用于交换XML编码信息的轻量级协议。 <br /><br />UDDI 的目的是为电子商务建立标准；UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范，同时也包含一组使企业能将自身提供的Web Service注册，以使别的企业能够发现的访问协议的实现标准。 <br /><br />5、BS与CS的联系与区别。 <br /><br />希望大家补上，谢谢 <br /><br />6、STRUTS的应用(如STRUTS架构) <br /><br />答：
Struts是采用Java Servlet/JavaServer Pages技术，开发Web应用程序的开放源码的framework。
采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能： <br /><br />一.包含一个controller servlet，能将用户的请求发送到相应的Action对象。 <br /><br />二.JSP自由tag库，并且在controller servlet中提供关联支持，帮助开发员创建交互式表单应用。 <br /><br />三.提供了一系列实用对象：XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息。 <br /><br />设计模式方面 <br /><br />1、开发中都用到了那些设计模式?用在什么场合? <br /><br />答：
每个模式都描述了一个在我们的环境中不断出现的问题，然后描述了该问题的解决方案的核心。通过这种方式，你可以无数次地使用那些已有的解决方案，无需在重
复相同的工作。主要用到了MVC的设计模式。用来开发JSP/Servlet或者J2EE的相关应用。简单工厂模式等。 <br /><br />2、UML方面 <br /><br />答：标准建模语言UML。用例图,静态图(包括类图、对象图和包图),行为图,交互图(顺序图,合作图),实现图, <br /><br />JavaScript方面 <br /><br />1、如何校验数字型? <br /><br />var re=/^d{1,8}$|.d{1,2}$/; <br /><br />var str=document.form1.all(i).value; <br /><br />var r=str.match(re); <br /><br />if (r==null) <br /><br />{ <br /><br />sign=-4; <br /><br />break; <br /><br />} <br /><br />else{ <br /><br />document.form1.all(i).value=parseFloat(str); <br /><br />} <br /><br />CORBA方面 <br /><br />1、CORBA是什么?用途是什么? <br /><br />答：
CORBA 标准是公共对象请求代理结构(Common Object Request Broker Architecture)，由对象管理组织
(Object Management Group，缩写为 OMG)标准化。它的组成是接口定义语言(IDL),
语言绑定(binding:也译为联编)和允许应用程序间互操作的协议。 其目的为： <br /><br />用不同的程序设计语言书写 <br /><br />在不同的进程中运行 <br /><br />为不同的操作系统开发 <br /><br />LINUX方面 <br /><br />1、LINUX下线程，GDI类的解释。 <br /><br />答：LINUX实现的就是基于核心轻量级进程的"一对一"线程模型，一个线程实体对应一个核心轻量级进程，而线程之间的管理在核外函数库中实现。 <br /><br />GDI类为图像设备编程接口类库。<br /><br />JAVA华为面试题<br /><br />JAVA方面<br /><br />1 面向对象的特征有哪些方面   <br /><br />2 String是最基本的数据类型吗?<br /><br />3 int 和 Integer 有什么区别<br /><br />4 String 和StringBuffer的区别<br /><br />5运行时异常与一般异常有何异同？<br /><br />异常表示程序运行过程中可能出现的非正常状态，运行时异常表示虚拟机的通常操作中可能遇到的异常，是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常，但是并不要求必须声明抛出未被捕获的运行时异常。<br /><br />6 说出一些常用的类，包,接口，请各举5个<br /><br />7 说出ArrayList,Vector, LinkedList的存储性能和特性<br /><br />ArrayList
和Vector都是使用数组方式存储数据，此数组元素数大于实际存储的数据以便增加和插入元素，它们都允许直接按序号索引元素，但是插入元素要涉及数组元
素移动等内存操作，所以索引数据快而插入数据慢，Vector由于使用了synchronized方法（线程安全），通常性能上较ArrayList差，
而LinkedList使用双向链表实现存储，按序号索引数据需要进行前向或后向遍历，但是插入数据时只需要记录本项的前后项即可，所以插入速度较快。<br /><br />8设计4个线程，其中两个线程每次对j增加1，另外两个线程对j每次减少1。写出程序。<br /><br />以下程序使用内部类实现线程，对j增减的时候没有考虑顺序问题。<br /><br />public class ThreadTest1{<br /><br />         private int j;<br /><br />         public static void main(String args[]){<br /><br />                  ThreadTest1 tt=new ThreadTest1();<br /><br />                   Inc inc=tt.new Inc();<br /><br />                   Dec dec=tt.new Dec();<br /><br />                   for(int i=0;i&lt;2;i++){<br /><br />                            Thread t=new Thread(inc);<br /><br />                            t.start();<br /><br />                            t=new Thread(dec);<br /><br />                            t.start();<br /><br />                   }<br /><br />         }<br /><br />         private synchronized void inc(){<br /><br />                   j++;<br /><br />                  System.out.println(Thread.currentThread().getName()+"-inc:"+j);<br /><br />         }<br /><br />         private synchronized void dec(){<br /><br />                   j--;<br /><br />                  System.out.println(Thread.currentThread().getName()+"-dec:"+j);<br /><br />         }<br /><br />         <br /><br />         class Inc implements Runnable{<br /><br />                   public void run(){<br /><br />                            for(int i=0;i&lt;100;i++){<br /><br />                                     inc();<br /><br />                            }<br /><br />                   }<br /><br />         }<br /><br />         class Dec implements Runnable{<br /><br />                   public void run(){<br /><br />                            for(int i=0;i&lt;100;i++){<br /><br />                                     dec();<br /><br />                            }<br /><br />                   }<br /><br />         }<br /><br />}<br /><br />9．   JSP的内置对象及方法。<br /><br />request request表示HttpServletRequest对象。它包含了有关浏览器请求的信息，并且提供了几个用于获取cookie, header, 和session数据的有用的方法。 <br /><br />response response表示HttpServletResponse对象，并提供了几个用于设置送回 浏览器的响应的方法（如cookies,头信息等） <br /><br />out out 对象是javax.jsp.JspWriter的一个实例，并提供了几个方法使你能用于向浏览器回送输出结果。 <br /><br />pageContext pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API，并且包装了通用的servlet相关功能的方法。 <br /><br />session session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息 <br /><br />application applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息 <br /><br />config config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。 <br /><br />page page表示从该页面产生的一个servlet实例<br /><br />10.用socket通讯写出客户端和服务器端的通讯，要求客户发送数据后能够回显相同的数据。<br /><br />参见课程中socket通讯例子。<br /><br />11说出Servlet的生命周期，并说出Servlet和CGI的区别。<br /><br />Servlet被服务器实例化后，容器运行其init方法，请求到达时运行其service方法，service方法自动派遣运行与请求对应的doXXX方法（doGet，doPost）等，当服务器决定将实例销毁的时候调用其destroy方法。<br /><br />与cgi的区别在于servlet处于服务器进程中，它通过多线程方式运行其service方法，一个实例可以服务于多个请求，并且其实例一般不会销毁，而CGI对每个请求都产生新的进程，服务完成后就销毁，所以效率上低于servlet。<br /><br />12.EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别，StatefulBean和StatelessBean的区别。<br />13．EJB包括（SessionBean,EntityBean）说出他们的生命周期，及如何管理事务的？<br />14．说出数据连接池的工作机制是什么?<br />15同步和异步有和异同，在什么情况下分别使用他们？举例说明。<br />16应用服务器有那些？<br />17你所知道的集合类都有哪些？主要方法？<br />18给你一个:驱动程序A,数据源名称为B,用户名称为C,密码为D,数据库表为T，请用JDBC检索出表T的所有数据。<br />19．说出在JSP页面里是怎么分页的?<br />页面需要保存以下参数：<br />总行数：根据sql语句得到总行数<br />每页显示行数：设定值<br />当前页数：请求参数<br />页面根据当前页数和每页行数计算出当前页第一行行数，定位结果集到此行，对结果集取出每页显示行数的行即可。<br />数据库方面：<br />1.          存储过程和函数的区别<br />存储过程是用户定义的一系列sql语句的集合，涉及特定表或其它对象的任务，用户可以调用存储过程，而函数通常是数据库已定义的方法，它接收参数并返回某种类型的值并且不涉及特定用户表。<br />2.          事务是什么？<br />事务是作为一个逻辑单元执行的一系列操作，一个逻辑工作单元必须有四个属性，称为 ACID（原子性、一致性、隔离性和持久性）属性，只有这样才能成为一个事务：<br />原子性<br />事务必须是原子工作单元；对于其数据修改，要么全都执行，要么全都不执行。<br />一致性<br />事务在完成时，必须使所有的数据都保持一致状态。在相关数据库中，所有规则都必须应用于事务的修改，以保持所有数据的完整性。事务结束时，所有的内部数据结构（如 B 树索引或双向链表）都必须是正确的。<br />隔离性<br />由
并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态，要么是另一并发事务修改它之前的状态，要么是另一事务修改它之
后的状态，事务不会查看中间状态的数据。这称为可串行性，因为它能够重新装载起始数据，并且重播一系列事务，以使数据结束时的状态与原始事务执行的状态相
同。<br /><br />持久性<br /><br />事务完成之后，它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。<br /><br /><br /><br />3.          游标的作用？如何知道游标已经到了最后？<br /><br />游标用于定位结果集的行，通过判断全局变量@@FETCH_STATUS可以判断是否到了最后，通常此变量不等于0表示出错或到了最后。<br /><br />4.          触发器分为事前触发和事后触发，这两种触发有和区别。语句级触发和行级触发有何区别。<br /><br />事前触发器运行于触发事件发生之前，而事后触发器运行于触发事件发生之后。通常事前触发器可以获取事件之前和新的字段值。<br /><br />语句级触发器可以在语句执行前或后执行，而行级触发在触发器所影响的每一行触发一次。<br /><br /><br /><br /><br /><br />中远面试题<br /><br />   1、面向对象的三个基本特征<br /><br />   2、方法重载和方法重写的概念和区别<br /><br />   3、接口和内部类、抽象类的特性<br /><br />   4、文件读写的基本类<br /><br />   **5、串行化的注意事项以及如何实现串行化<br /><br />   6、线程的基本概念、线程的基本状态以及状态之间的关系<br /><br />   7、线程的同步、如何实现线程的同步<br /><br />   8、几种常用的数据结构及内部实现原理。<br /><br />   9、Socket通信(TCP、UDP区别及Java实现方式)<br /><br />  **10、Java的事件委托机制和垃圾回收机制<br /><br />  11、JDBC调用数据库的基本步骤<br /><br />  **12、解析XML文件的几种方式和区别<br /><br />  13、Java四种基本权限的定义<br /><br />  14、Java的国际化<br /><br />二、JSP<br />   1、至少要能说出7个隐含对象以及他们的区别<br /><br />  ** 2、forward 和redirect的区别<br /><br />   3、JSP的常用指令<br /><br />三、servlet<br />   1、什么情况下调用doGet()和doPost()？<br /><br />   2、servlet的init()方法和service()方法的区别<br /><br />   3、servlet的生命周期<br /><br />   4、如何现实servlet的单线程模式<br /><br />   5、servlet的配置<br /><br />   6、四种会话跟踪技术<br /><br />四、EJB<br />   **1、EJB容器提供的服务<br /><br />         主要提供声明周期管理、代码产生、持续性管理、安全、事务管理、锁和并发行管理等服务。<br /><br />   2、EJB的角色和三个对象<br /><br />         EJB角色主要包括Bean开发者 应用组装者 部署者 系统管理员 EJB容器提供者 EJB服务器提供者<br /><br />         三个对象是Remote（Local）接口、Home（LocalHome）接口，Bean类<br /><br />   2、EJB的几种类型<br /><br />         会话（Session）Bean ，实体（Entity）Bean 消息驱动的（Message Driven）Bean<br /><br />         会话Bean又可分为有状态（Stateful）和无状态（Stateless）两种<br /><br />         实体Bean可分为Bean管理的持续性（BMP）和容器管理的持续性（CMP）两种<br /><br />   3、bean 实例的生命周期<br /><br />        
对于Stateless Session Bean、Entity Bean、Message Driven
Bean一般存在缓冲池管理，而对于Entity Bean和Statefull Session
Bean存在Cache管理，通常包含创建实例，设置上下文、创建EJB
Object（create）、业务方法调用、remove等过程，对于存在缓冲池管理的Bean，在create之后实例并不从内存清除，而是采用缓冲
池调度机制不断重用实例，而对于存在Cache管理的Bean则通过激活和去激活机制保持Bean的状态并限制内存中实例数量。<br /><br />   4、激活机制<br /><br />        
以Statefull Session Bean
为例：其Cache大小决定了内存中可以同时存在的Bean实例的数量，根据MRU或NRU算法，实例在激活和去激活状态之间迁移，激活机制是当客户端调
用某个EJB实例业务方法时，如果对应EJB
Object发现自己没有绑定对应的Bean实例则从其去激活Bean存储中（通过序列化机制存储实例）回复（激活）此实例。状态变迁前会调用对应的
ejbActive和ejbPassivate方法。<br /><br />   5、remote接口和home接口主要作用<br /><br />         remote接口定义了业务方法，用于EJB客户端调用业务方法<br /><br />         home接口是EJB工厂用于创建和移除查找EJB实例<br /><br />   6、客服端调用EJB对象的几个基本步骤<br /><br />一、  设置JNDI服务工厂以及JNDI服务地址系统属性<br /><br />二、  查找Home接口<br /><br />三、  从Home接口调用Create方法创建Remote接口<br /><br />四、  通过Remote接口调用其业务方法<br /><br />五、数据库<br />   1、存储过程的编写<br /><br />   2、基本的SQL语句<br /><br />六、weblogic<br />1、   如何给weblogic指定大小的内存? <br /><br />在启动Weblogic的脚本中（位于所在Domian对应服务器目录下的startServerName），增加set MEM_ARGS=-Xms32m -Xmx200m，可以调整最小内存为32M，最大200M<br /><br />2、   如何设定的weblogic的热启动模式(开发模式)与产品发布模式?<br /><br />可以在管理控制台中修改对应服务器的启动模式为开发或产品模式之一。或者修改服务的启动文件或者commenv文件，增加set PRODUCTION_MODE=true。<br /><br />3、   如何启动时不需输入用户名与密码?<br /><br />修改服务启动文件，增加 WLS_USER和WLS_PW项。也可以在boot.properties文件中增加加密过的用户名和密码.<br /><br />4、   在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么文件中?<br /><br />保存在此Domain的config.xml文件中，它是服务器的核心配置文件。<br /><br />5、
  
说说weblogic中一个Domain的缺省目录结构?比如要将一个简单的helloWorld.jsp放入何目录下,然的在浏览器上就可打入
http://主机:端口号//helloword.jsp就可以看到运行结果了? 又比如这其中用到了一个自己写的javaBean该如何办?<br /><br />Domain
目录\服务器目录\applications，将应用目录放在此目录下将可以作为应用访问，如果是Web应用，应用目录需要满足Web应用目录要求，
jsp文件可以直接放在应用目录中，Javabean需要放在应用目录的WEB-INF目录的classes目录中，设置服务器的缺省应用将可以实现在浏
览器上无需输入应用名。<br /><br />6、   如何查看在weblogic中已经发布的EJB?<br /><br />可以使用管理控制台，在它的Deployment中可以查看所有已发布的EJB <br /><br />7、   如何在weblogic中进行ssl配置与客户端的认证配置或说说j2ee(标准)进行ssl的配置<br /><br />缺
省安装中使用DemoIdentity.jks和DemoTrust.jks  KeyStore实现SSL，需要配置服务器使用Enable
SSL，配置其端口，在产品模式下需要从CA获取私有密钥和数字证书，创建identity和trust
keystore，装载获得的密钥和数字证书。可以配置此SSL连接是单向还是双向的。<br /><br />   8、在weblogic中发布ejb需涉及到哪些配置文件<br /><br />不同类型的EJB涉及的配置文件不同，都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP实体Bean一般还需要weblogic-cmp-rdbms-jar.xml<br /><br />   9、EJB需直接实现它的业务接口或Home接口吗,请简述理由.<br /><br />远程接口和Home接口不需要直接实现，他们的实现代码是由服务器产生的，程序运行中对应实现类会作为对应接口类型的实例被使用。<br /><br />  10、说说在weblogic中开发消息Bean时的persistent与non-persisten的差别<br /><br />persistent方式的MDB可以保证消息传递的可靠性,也就是如果EJB容器出现问题而JMS服务器依然会将消息在此MDB可用的时候发送过来，而non－persistent方式的消息将被丢弃。<br /><br />  11、说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法<br /><br />       Session Facade Pattern：使用SessionBean访问EntityBean<br /><br />Message Facade Pattern：实现异步调用<br /><br />EJB Command Pattern：使用Command JavaBeans取代SessionBean，实现轻量级访问<br /><br />Data Transfer Object Factory：通过DTO Factory简化EntityBean数据提供特性<br /><br />Generic Attribute Access：通过AttibuteAccess接口简化EntityBean数据提供特性<br /><br />Business Interface：通过远程（本地）接口和Bean类实现相同接口规范业务逻辑一致性<br /><br />ＥＪＢ架构的设计好坏将直接影响系统的性能、可扩展性、可维护性、组件可重用性及开发效率。项目越复杂，项目队伍越庞大则越能体现良好设计的重要性<br /><img src ="http://www.blogjava.net/JafeLee/aggbug/119252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-05-22 23:28 <a href="http://www.blogjava.net/JafeLee/articles/119252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java接口特性学习 (转载）</title><link>http://www.blogjava.net/JafeLee/articles/117942.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Wed, 16 May 2007 15:38:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/117942.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/117942.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/117942.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/117942.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/117942.html</trackback:ping><description><![CDATA[from: http://www.blogjava.net/flyingis<br><font size="2"><span style="font-size: 10.5pt; font-family: 宋体;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: 10pt; font-family: 宋体;">作者：<a  href="http://www.blogjava.net/flyingis/"><font color="#000080">Flyingis</font></a><br><br>&nbsp;&nbsp;&nbsp; 在</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">Java</font></span><span style="font-size: 10pt; font-family: 宋体;">中看到接口，第一个想到的可能就是</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">C++</font></span><span style="font-size: 10pt; font-family: 宋体;">中的多重继承和</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">Java</font></span><span style="font-size: 10pt; font-family: 宋体;">中的另外一个关键字</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">abstract</font></span><span style="font-size: 10pt; font-family: 宋体;">。从另外一个角度实现多重继承是接口的功能之一，接口的存在可以使</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">Java</font></span><span style="font-size: 10pt; font-family: 宋体;">中的对象可以向上转型为多个基类型，并且和抽象类一样可以防止他人创建该类的对象，因为接口不允许创建对象。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: 10pt;" lang="EN-US"><o:p><font face="Times New Roman">&nbsp;</font></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 18pt;"><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">interface</font></span><span style="font-size: 10pt; font-family: 宋体;">关键字用来声明一个接口，它可以产生一个完全抽象的类，并且不提供任何具体实现。</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">interface</font></span><span style="font-size: 10pt; font-family: 宋体;">的特性整理如下：</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">1.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">接口中的方法可以有参数列表和返回类型，但不能有任何方法体。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">2.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">接口中可以包含字段，但是会被隐式的声明为</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">static</font></span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">final</font></span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">3.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">接口中的字段只是被存储在该接口的静态存储区域内，而不属于该接口。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">4.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">接口中的方法可以被声明为</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">public</font></span><span style="font-size: 10pt; font-family: 宋体;">或不声明，但结果都会按照</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">public</font></span><span style="font-size: 10pt; font-family: 宋体;">类型处理。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">5.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">当实现一个接口时，需要将被定义的方法声明为</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">public</font></span><span style="font-size: 10pt; font-family: 宋体;">类型的，否则为默认访问类型，</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">Java</font></span><span style="font-size: 10pt; font-family: 宋体;">编译器不允许这种情况。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">6.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">如果没有实现接口中所有方法，那么创建的仍然是一个接口。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">7.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">扩展一个接口来生成新的接口应使用关键字</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">extends</font></span><span style="font-size: 10pt; font-family: 宋体;">，实现一个接口使用</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">implements</font></span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 10pt;" lang="EN-US"><o:p><font face="Times New Roman">&nbsp;</font></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 18pt;"><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">interface</font></span><span style="font-size: 10pt; font-family: 宋体;">在某些地方和</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">abstract</font></span><span style="font-size: 10pt; font-family: 宋体;">有相似的地方，但是采用哪种方式来声明类主要参照以下两点：</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">1.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">如果要创建不带任何方法定义和成员变量的基类，那么就应该选择接口而不是抽象类。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span style="font-size: 10pt;" lang="EN-US"><span><font face="Times New Roman">2.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span style="font-size: 10pt; font-family: 宋体;">如果知道某个类应该是基类，那么第一个选择的应该是让它成为一个接口，只有在必须要有方法定义和成员变量的时候，才应该选择抽象类。因为抽象类中允许存在一个或多个被具体实现的方法，只要方法没有被全部实现该类就仍是抽象类。</span><span style="font-size: 10pt;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 10pt;" lang="EN-US"><o:p><font face="Times New Roman">&nbsp;</font></o:p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 18pt;"><span style="font-size: 10pt; font-family: 宋体;">以上就是接口的基本特性和应用的领域，但是接口绝不仅仅如此，在</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">Java</font></span><span style="font-size: 10pt; font-family: 宋体;">语法结构中，接口可以被嵌套，既可以被某个类嵌套，也可以被接口嵌套。这在实际开发中可能应用的不多，但也是它的特性之一。需要注意的是，在实现某个接口时，并不需要实现嵌套在其内部的任何接口，而且，</span><span style="font-size: 10pt;" lang="EN-US"><font face="Times New Roman">private</font></span><span style="font-size: 10pt; font-family: 宋体;">接口不能在定义它的类之外被实现。</span></p>
</span></font><br><br><br><img src ="http://www.blogjava.net/JafeLee/aggbug/117942.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-05-16 23:38 <a href="http://www.blogjava.net/JafeLee/articles/117942.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>详细介绍在tomcat中配置数据源以及数据源的原理 (转载)</title><link>http://www.blogjava.net/JafeLee/articles/117838.html</link><dc:creator>Jafe</dc:creator><author>Jafe</author><pubDate>Wed, 16 May 2007 06:46:00 GMT</pubDate><guid>http://www.blogjava.net/JafeLee/articles/117838.html</guid><wfw:comment>http://www.blogjava.net/JafeLee/comments/117838.html</wfw:comment><comments>http://www.blogjava.net/JafeLee/articles/117838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/JafeLee/comments/commentRss/117838.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/JafeLee/services/trackbacks/117838.html</trackback:ping><description><![CDATA[<p>作者:baggio785</p>
<p>来源:<a href="http://blog.csdn.net/baggio785" target=_blank><font color=#0000ff>http://blog.csdn.net/baggio785</font></a></p>
<strong><font size=6>前言</font></strong>
<p>本文根据实例详细介绍了如何在tomcat中配置数据源。网上此类文章很多，但是基本都是雷同的，而且对一些特殊问题以及原理并未详细阐述，所以想根据自己的实际经验，并结合例子写一篇详细的文章。</p>
<p>本文是偶的一些拙见，有不正确的地方请大家多多评论指正。</p>
<p><strong><font size=6>开发环境</font></strong></p>
<p>&nbsp;本文的环境：JDK1.4.2，TOMCAT5.0.28，Oracle9i</p>
<p><strong><font size=6>JDBC简介</font></strong></p>
<p>&nbsp;提到数据源，那就不能不说JDBC。JDBC是Java Database Connectivity的缩写。在java.sql包中提供了JDBC API，定义了访问数据库的接口和类。但是JDBC API不能直接访问数据库，必须依赖于数据库厂商提供的JDBC驱动程序，即JDBC DRIVER。</p>
<p>Java.sql中常用的接口和类如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Driver接口和DriverManager类</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Connection</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Statement</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PreparedSataement</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResultSet</p>
<p>1&nbsp;&nbsp;&nbsp;&nbsp; Driver接口和DriverManager类<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DriverManager类用来建立和数据库的连接以及管理JDBC驱动程序，常用方法如下：</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>方法</strong></td>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>描述</strong></td>
        </tr>
        <tr>
            <td width="50%">registerDriver(Driver driver)</td>
            <td width="50%">在DriverManager中注册JDBC驱动程序</td>
        </tr>
        <tr>
            <td width="50%">getConnection(String url,String user,String pwd)</td>
            <td width="50%">建立和数据库的连接，返回Connection对象</td>
        </tr>
        <tr>
            <td width="50%">setLoginTimeOut(int seconds)</td>
            <td width="50%">设定等待数据库连接的最长时间</td>
        </tr>
        <tr>
            <td width="50%">setLogWriter(PrintWriter out)</td>
            <td width="50%">设定输入数据库日至的PrintWriter对象</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p>2&nbsp;&nbsp;&nbsp;&nbsp; Connection<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Connection代表和数据库的连接，其常用方法如下：</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>方法</strong></td>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>描述</strong></td>
        </tr>
        <tr>
            <td width="50%">getMetaData()</td>
            <td width="50%">返回数据库的MetaData数据。MetaData数据包含了数据库的相关信息，例如当前数据库连接的用户名、使用的JDBC驱动程序、数据库允许的最大连接数、数据库的版本等等。</td>
        </tr>
        <tr>
            <td width="50%">createStatement()</td>
            <td width="50%">创建并返回Statement对象</td>
        </tr>
        <tr>
            <td width="50%">PrepareStatement(String sql)</td>
            <td width="50%">创建并返回prepareStatement对象</td>
        </tr>
    </tbody>
</table>
</p>
<p>3&nbsp;&nbsp;&nbsp;&nbsp; Statement<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Statement用来执行静态sql语句。例如，对于insert、update、delete语句，调用executeUpdate(String sql)方法，而select语句可以调用executeQuery(String sql)方法，executeQuery(String sql)方法返回ResultSet对象。</p>
<p>4&nbsp;&nbsp;&nbsp;&nbsp; PrepareStatement<br>&nbsp;&nbsp; PrepareStatement用于执行动态的sql语句，即允许sql语句中包含参数。使用方法为：<br>&nbsp;&nbsp; String sql = &#8220;select col1 from tablename where col2=? And col3=?&#8221;;<br>&nbsp;&nbsp; PrepareStatement perpStmt = conn.preparestatement(sql);<br>&nbsp;&nbsp; perpStmt.setstring(1,col2Value);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; perpStmt.setFloat(2,col3Value);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResultSet rs = perpStmt.executeQuery();</p>
<p>5&nbsp;&nbsp;&nbsp;&nbsp; ResultSet<br>ResultSet用来表示select语句查询得到的记录集，一个StateMent对象在同一时刻只能打开一个ResultSet对象。通过ResultSet的getXXX()方法来得到字段值。ResultSet提供了getString()、getFloat()、getInt()等方法。可以通过字段的序号或者字段的名字来制定获取某个字段的值。例如：在上例中getString(0),getString(col1)都可以获得字段col1的值。</p>
<p><strong>事务处理</strong></p>
<p>在实际应用中，我们会遇到同时提交多个sql语句，这些sql语句要么全部成功，要么全部失败，如果其中一条提交失败，则必须撤销整个事务。为此，Connection类提供了3个控制事务的方法：</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>方法</strong></td>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>描述</strong></td>
        </tr>
        <tr>
            <td width="50%">setAutoCommit(boolen autoCommit)</td>
            <td width="50%">设置是否自动提交事务，默认为自动提交。</td>
        </tr>
        <tr>
            <td width="50%">commit()</td>
            <td width="50%">提交事务</td>
        </tr>
        <tr>
            <td width="50%">rollback()</td>
            <td width="50%">撤销事务</td>
        </tr>
    </tbody>
</table>
</p>
<p>参考例子：</p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td width="100%" bgColor=#c0c0c0>try{<br><br><br>conn.SetautoCommit(false);<br><br><br>stmt = conn.createstatement();<br>stmt.executeUpdate(&#8220;delete form table1 where col1=1&#8221;);<br>stmt.eecuteUpdate(&#8220;delete from table2 where col2=1&#8221;);<br><br><br>conn.comm.it();<br><br><br>}catch(Exception e){<br><br><br>e.printStackTrace;<br><br><br>try{<br><br>conn.rollback();<br><br><br>} catch(Exception e1){<br><br><br>e1.printStackTrace;<br><br><br>}<br><br><br>}</td>
        </tr>
    </tbody>
</table>
<p>通过一个JSP例子来访问oracle数据库：</p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td width="100%" bgColor=#c0c0c0>&lt;%@ page import="java.util.*"&gt;<br><br><br>&lt;%@ page import="java.sql.*"&gt;<br><br><br>&lt;%<br><br><br>try{<br><br><br>Connection conn = null;<br><br><br>Statement stmt = null;<br><br><br>ResultSet rs = null;<br><br><br>//加载oracle驱动程序<br><br><br>Class.forName("oracle.jdbc.driver.OracleDriver.");<br><br><br>//注册oracle驱动程序<br><br><br>DriverManager.regidterDriver(new&nbsp;<br>oracle.jdbc.driver.OracleDriver());<br><br><br>//建立数据库连接<br><br><br>conn=DriverManager.getConnection("jdbc:oracle:thin:@your&nbsp;<br>db ip:your db port:sid",dbuser,dbpassword);<br><br><br>stmt = conn.createStatement();<br><br><br>rs = stmt.executeQuery("select * from&nbsp;<br>tablename");<br><br><br>while(rs.next){<br><br>out.print(rs.getstring("colname"));<br><br><br>}<br><br><br>}catch(Exception e){<br><br><br>}<br><br><br>finally{<br><br><br>rs.close();<br><br><br>stmt.close();<br><br><br>conn.close();<br><br><br>}<br><br>%&gt;</td>
        </tr>
    </tbody>
</table>
<p><strong><font size=6>数据源简介</font></strong></p>
<p>JDBC2.0提供了javax.sql.DataSource的接口，负责与数据库建立连接，实际应用时不需要编写连接数据库代码，直接从数据源获得数据库的连接。Dataource中事先建立了多个数据库连接，这些数据库连接保持在数据库连接池中，当程序访问数据库时，只需要从连接池从取出空闲的连接，访问数据库结束，在将这些连接归还给连接池。DataSource对象由容器（Tomcat）提供，不能使用创建实例的方法来生成DataSource对象，要采用JAVA的JNDI（Java Nameing and Directory Interface，java命名和目录接口）来获得DataSource对象的引用。（另有一种说法：&#8220;其实从技术上来说，数据源连接方式是不需要目录服务的，我们同样可以通过序列化数据源对象直接访问文件系统。这点是需要明确的。&#8221;感兴趣的朋友可以试试。）JNDI是一种将对象和名字绑定的技术，对象工厂负责生产出对象，这些对象都和唯一的名字相绑定。程序中可以通过这个名字来获得对象的引用。Tomcat把DataSource作为一种可配置的JNDI资源来处理，生成DataSource对象的工厂为org.apache.comm.ons.dbcp.BasicDataSourceFactory。</p>
<p><strong><font size=6>配置数据源</font></strong></p>
<p>配置数据源其实相当简单：</p>
<p>首先在server.xml中加入&lt;Resource&gt;元素，打开server.xml，在&lt;Context&gt;中加入以下代码（以oracle为例）：</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td width="100%" bgColor=#c0c0c0>&lt;Resource name="jdbc/ JNDI名字" auth="Container" type="javax.sql.DataSource"/&gt;<br><br>&lt;ResourceParams name="jdbc/JNDI名字"&gt;<br><br>&lt;parameter&gt;<br><br>&lt;name&gt;factory&lt;/name&gt;<br>&nbsp;<br>&lt;value&gt;org.apache.commons.dbcp.BasicDataSourceFactory&lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;parameter&gt;<br><br>&lt;name&gt;maxActive&lt;/name&gt;<br><br>&lt;value&gt;100&lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;parameter&gt;<br>&nbsp;<br>&lt;name&gt;maxIdle&lt;/name&gt;<br>&nbsp;<br>&lt;value&gt;30&lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;parameter&gt;<br><br>&lt;name&gt;maxWait&lt;/name&gt;<br>&nbsp;<br>&lt;value&gt;10000&lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;parameter&gt;<br>&nbsp;<br>&lt;name&gt;username&lt;/name&gt;<br><br>&lt;value&gt;用户名&lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;parameter&gt;<br><br>&lt;name&gt;password&lt;/name&gt;<br><br>&lt;value&gt;密码&lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;parameter&gt;<br><br>&lt;name&gt;driverClassName&lt;/name&gt;<br><br>&lt;value&gt;oracle.jdbc.driver.OracleDriver&lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;parameter&gt;<br><br>&lt;name&gt;url&lt;/name&gt;<br>&nbsp;<br>&lt;value&gt;jdbc:oracle:thin:@ip:端口:sid &lt;/value&gt;<br><br>&lt;/parameter&gt;<br><br>&lt;/ResourceParams&gt;</td>
        </tr>
    </tbody>
</table>
</p>
<p>&lt;Resource&gt;元素的属性如下：</p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>属性</strong></td>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>描述</strong></td>
        </tr>
        <tr>
            <td width="50%">name</td>
            <td width="50%">指定Resource的JNDI的名字</td>
        </tr>
        <tr>
            <td width="50%">auth</td>
            <td width="50%">指定管理Resource的Manager，由两个可选值：Container和Application。Container表示由容器来创建和管理Resource，Application表示由WEB应用来创建和管理Resource。如果在web application deployment descriptor中使用&lt;resource-ref&gt;，这个属性是必需的，如果使用&lt;resource-env-ref&gt;，这个属性是可选的。</td>
        </tr>
        <tr>
            <td width="50%">type</td>
            <td width="50%">指定Resource所属的java类名</td>
        </tr>
    </tbody>
</table>
<p>&lt;ResourceParams&gt;元素的属性如下：</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>属性</strong></td>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>描述</strong></td>
        </tr>
        <tr>
            <td width="50%">name</td>
            <td width="50%">指定ResourceParams的JNDI的名字，必须和Resource的name保持一致</td>
        </tr>
        <tr>
            <td width="50%">factory</td>
            <td width="50%">指定生成DataSource对象的factory的类名</td>
        </tr>
        <tr>
            <td width="50%">maxActive</td>
            <td width="50%">指定数据库连接池中处于活动状态的数据库连接最大数目，0表示不受限制</td>
        </tr>
        <tr>
            <td width="50%">maxIdle</td>
            <td width="50%">指定数据库连接池中处于空闲状态的数据库连接的最大数目，0表示不受限制</td>
        </tr>
        <tr>
            <td width="50%">maxWait</td>
            <td width="50%">指定数据库连接池中的数据库连接处于空闲状态的最长时间（单位为毫秒），超过这一事件，将会抛出异常。-1表示可以无限期等待。</td>
        </tr>
        <tr>
            <td width="50%">username</td>
            <td width="50%">指定连接数据库的用户名</td>
        </tr>
        <tr>
            <td width="50%">password</td>
            <td width="50%">指定连接数据库的密码</td>
        </tr>
        <tr>
            <td width="50%">driverClassName</td>
            <td width="50%">指定连接数据库的JDBC驱动程序</td>
        </tr>
        <tr>
            <td width="50%">url</td>
            <td width="50%">指定连接数据库的URL</td>
        </tr>
    </tbody>
</table>
</p>
<p>其他文章说以上配置就OK了，对于web.xml的配置可有可无，其实不是这样子的。如果在web应用中访问了由Servlet容器管理的某个JNDI Resource，则必须在web.xml中声明对这个JNDI Resource的引用。表示资源引用的元素为&lt;resource-ref&gt;,该元素加在&lt;wepapp&gt;&lt;/ wepapp &gt;中。</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td width="100%" bgColor=#c0c0c0>&lt;resource-ref&gt;<br><br>&lt;descryiption&gt;DB Connection&lt;/descryiption&gt;<br><br>&lt;res-ref-name&gt;jdbc/JNDI名字 &lt;/res-ref-name&gt;<br><br>&lt;res-type&gt;javax.sql.DataSource &lt;/res- type&gt;<br><br>&lt;res-auth&gt;Container &lt;/res-auth&gt;<br><br>&lt;/resource-ref&gt;</td>
        </tr>
    </tbody>
</table>
</p>
<p>&lt;resource-ref&gt;元素的属性如下：</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>属性</strong></td>
            <td align=middle width="50%" bgColor=#c0c0c0><strong>描述</strong></td>
        </tr>
        <tr>
            <td width="50%">description</td>
            <td width="50%">对所引用的资源的说明</td>
        </tr>
        <tr>
            <td width="50%">res-ref-name</td>
            <td width="50%">指定所引用资源的JNDI名字，与&lt;Resource&gt;元素中的name属性保持一致</td>
        </tr>
        <tr>
            <td width="50%">res-type</td>
            <td width="50%">指定所引用资源的类名字，与&lt;Resource&gt;元素中的type属性保持一致</td>
        </tr>
        <tr>
            <td width="50%">res-auth</td>
            <td width="50%">指定所引用资源的Manager，与&lt;Resource&gt;元素中的auth属性保持一致</td>
        </tr>
    </tbody>
</table>
</p>
<p>到这里，数据源就已经配置成功了。但是我在测试的时候除了一点小麻烦，主要原因是对DataSource的概念没搞清楚。我是这么测试的，写一个测试类，然后在eclipse中进行junit测试，捕获的异常为： </p>
<p>javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:&nbsp;java.naming.factory.initial。 </p>
<p>同样的代码在JSP文件中正常运行，后来翻了一些资料，终于找到了问题的所在了。原来DataSource是由容器（TOMCAT）提供的，所以我的测试会抛出异常。为了再次验证想法是否正确，在jsp文件中import刚才抛出异常的类，在进行连接数据库，结果一切正常。 </p>
<p>下面的例子是实际应用中使用DataSource，在jsp文件中连接oracle。</p>
<p>
<table width="90%" border=1>
    <tbody>
        <tr>
            <td width="100%" bgColor=#c0c0c0>&lt;%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&gt;<br><br>&lt;%@ page import="java.sql.*"%&gt;<br><br>&lt;%@ page import="javax.naming.*"%&gt;<br><br>&lt;%@ page import="javax.sql.*"%&gt;<br><br>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD&nbsp;<br>HTML 4.01 Transitional//EN"&gt;<br><br>&lt;html&gt;<br><br>&lt;head&gt;<br><br>&lt;/head&gt;<br><br>&lt;body&gt;<br><br>&lt;%<br>Context initContext = new InitialContext();<br><br>Context envContext = (Context) initContext.lookup("java:/comp/env");<br><br><br>DataSource db = (DataSource)envContext.lookup("jdbc/javablogorl");<br><br><br>//javablogorl为&lt;Resource&gt;元素中name属性的值<br><br>Connection conn = db.getConnection( );<br><br>Statement stmt = conn.createStatement();<br><br><br>ResultSet rs = stmt.executeQuery("SELECT * FROM blog_systemadmin");<br><br>while(rs.next()){<br><br>out.print(rs.getString("admin_name")+" ");<br><br>out.print(rs.getString("admin_password")+"&lt;br&gt;");<br><br>}<br><br>rs.close();<br><br>stmt.close();<br><br>conn.close();<br>%&gt;<br><br>&lt;/body&gt;<br><br>&lt;/html&gt;</td>
        </tr>
    </tbody>
</table>
</p>
<p>另:tomcat5.5的配制方法为:</p>
<p>&lt;Resource&nbsp;name="jdbc/JNDI名字"&nbsp;auth="Container"&nbsp;type="javax.sql.DataSource"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;maxActive="100"&nbsp;maxIdle="30"&nbsp;maxWait="10000"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;username="用户名"&nbsp;password="密码"&nbsp;driverClassName="oracle.jdbc.driver.OracleDriver"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url="jdbc:oracle:thin:@ip:端口:sid"/&gt;</p>
<img src ="http://www.blogjava.net/JafeLee/aggbug/117838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/JafeLee/" target="_blank">Jafe</a> 2007-05-16 14:46 <a href="http://www.blogjava.net/JafeLee/articles/117838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>