﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-小菜毛毛技术分享-随笔分类-面试</title><link>http://www.blogjava.net/caizh2009/category/44189.html</link><description>与大家共同成长</description><language>zh-cn</language><lastBuildDate>Thu, 12 May 2011 08:55:19 GMT</lastBuildDate><pubDate>Thu, 12 May 2011 08:55:19 GMT</pubDate><ttl>60</ttl><item><title>java sax 解析 实例</title><link>http://www.blogjava.net/caizh2009/archive/2011/05/11/350042.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Wed, 11 May 2011 14:34:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2011/05/11/350042.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/350042.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2011/05/11/350042.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/350042.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/350042.html</trackback:ping><description><![CDATA[<span style="font-size: 22pt; color: navy; font-family: 宋体; letter-spacing: 1.3pt">&nbsp;
<div align="right"><strong>用</strong></span><strong><span style="font-size: 22pt; color: navy; font-family: tahoma; letter-spacing: 1.3pt"  Times New Roman??>SAX</span><span style="font-size: 22pt; color: navy; font-family: 宋体; letter-spacing: 1.3pt">解析</span><span style="font-size: 22pt; color: navy; font-family: tahoma; letter-spacing: 1.3pt"  Times New Roman??>XML</span><span style="font-size: 22pt; color: navy; font-family: 宋体; letter-spacing: 1.3pt">实例</span></strong></div>
<div style="margin: 12pt 0cm"><strong><span style="font-size: 14pt; color: purple; font-family: 幼圆">实例：以下输出</strong></span><strong><span style="font-size: 14pt; color: purple; font-family: tahoma"  Times New Roman?;??><strong><span style="font-size: 14pt; color: purple; font-family: 幼圆">中的所有属性和标签值</strong></span></div>
<span style="font-size: 14pt; color: purple; font-family: tahoma"  Times New #eeeeee? background-color: verdana,宋体; font-family: solid; 1px #cccccc border-bottom: 4px; padding-top: 16px; line-height: break-all; word-break: #000000; color: 98%; width: border-left: padding-bottom: 10pt; font-size: padding-left: border-top: padding-right: Roman?;?border-right:><font color="#0000ff">package</font> com.meixin.xml; <br />
<br />
<font color="#0000ff">import</font> java.io.File; <br />
<font color="#0000ff">import</font> java.util.HashMap; <br />
<font color="#0000ff">import</font> java.util.Vector; <br />
<br />
<font color="#0000ff">import</font> org.xml.sax.Attributes; <br />
<font color="#0000ff">import</font> org.xml.sax.SAXException; <br />
<font color="#0000ff">import</font> org.xml.sax.helpers.DefaultHandler; <br />
<br />
<font color="#0000ff">import</font> javax.xml.parsers.SAXParser; <br />
<font color="#0000ff">import</font> javax.xml.parsers.SAXParserFactory; <br />
<br />
<font color="#0000ff">public</font> <font color="#0000ff">class</font> PraseXML <font color="#0000ff">extends</font> DefaultHandler <br />
{ <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">private</font> Vector&lt;String&gt; tagName; <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">private</font> Vector&lt;String&gt; tagValue; <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">private</font> <font color="#0000ff">int</font> step; <br />
<br />
&nbsp;&nbsp;<font color="#008000">// 开始解析XML文件 </font><br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">void</font> startDocument() <font color="#0000ff">throws</font> SAXException <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;tagName = <font color="#0000ff">new</font> Vector&lt;String&gt;(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;tagValue = <font color="#0000ff">new</font> Vector&lt;String&gt;(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;step = 0; <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#008000">// 结束解析XML文件 </font><br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">void</font> endDocument() <font color="#0000ff">throws</font> SAXException <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i &lt; tagName.size(); i++) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">if</font> (!tagName.get(i).equals("") || tagName.get(i) != <font color="#0000ff">null</font>) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<font color="#800000">"节点名称："</font> + tagName.get(i)); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<font color="#800000">"节点值："</font> + tagValue.get(i)); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#008000">/** <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 在解释到一个开始元素时会调用此方法.但是当元素有重复时可以自己写算法来区分 <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 这些重复的元素.qName是什么? &lt;name:page ll=""&gt;&lt;/name:page&gt;这样写就会抛出SAXException错误 <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 通常情况下qName等于localName <br />
&nbsp;&nbsp;&nbsp;&nbsp;*/</font> <br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">void</font> startElement(String uri, String localName, String qName, <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Attributes attributes) <font color="#0000ff">throws</font> SAXException <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">// 节点名称 </font><br />
&nbsp;&nbsp;&nbsp;&nbsp;tagName.add(qName); <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">// 循环输出属性 </font><br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">for</font> (<font color="#0000ff">int</font> i = 0; i &lt; attributes.getLength(); i++) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">// 获取属性名称 </font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<font color="#800000">"属性名称："</font> + attributes.getQName(i)); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">// 获取属性值 </font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<font color="#800000">"属性值："</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ attributes.getValue(attributes.getQName(i))); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#008000">/** <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 在遇到结束标签时调用此方法 <br />
&nbsp;&nbsp;&nbsp;&nbsp;*/</font> <br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">void</font> endElement(String uri, String localName, String qName) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">throws</font> SAXException <br />
&nbsp;&nbsp;{ <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;step = step + 1; <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#008000">/** <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 读取标签里的值,ch用来存放某行的xml的字符数据,包括标签,初始大小是2048, <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 每解释到新的字符会把它添加到char[]里。&nbsp;&nbsp;&nbsp;&nbsp;* 注意,这个char字符会自己管理存储的字符, <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 并不是每一行就会刷新一次char,start,length是由xml的元素数据确定的, <br />
&nbsp;&nbsp;&nbsp;&nbsp;* 暂时找不到规律,以后看源代码. <br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;* 这里一个正标签，反标签都会被执行一次characters，所以在反标签时不用获得其中的值 <br />
&nbsp;&nbsp;&nbsp;&nbsp;*/</font> <br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">void</font> characters(<font color="#0000ff">char</font> ch[], <font color="#0000ff">int</font> start, <font color="#0000ff">int</font> length) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">throws</font> SAXException <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#008000">// 只要当前的标签组的长度一至，值就不赋，则反标签不被计划在内 </font><br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">if</font> (tagName.size() - 1 == tagValue.size()) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tagValue.add(<font color="#0000ff">new</font> String(ch, start, length)); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;String filename = <font color="#800000">"MyXml.xml"</font>; <br />
&nbsp;&nbsp;&nbsp;&nbsp;SAXParserFactory spf = SAXParserFactory.newInstance(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">try</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SAXParser saxParser = spf.newSAXParser(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saxParser.parse(<font color="#0000ff">new</font> File(filename), <font color="#0000ff">new</font> PraseXML()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">catch</font> (Exception e) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">public</font> Vector getTagName() <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">return</font> tagName; <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">void</font> setTagName(Vector tagName) <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">this</font>.tagName = tagName; <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">public</font> Vector getTagValue() <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">return</font> tagValue; <br />
&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">public</font> <font color="#0000ff">void</font> setTagValue(Vector tagValue) <br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">this</font>.tagValue = tagValue; <br />
&nbsp;&nbsp;} <br />
<br />
} <br />
<div></div>
</span>
<div style="margin: 12pt 0cm"><strong><span style="font-size: 14pt; color: purple; font-family: 幼圆">输出结果：</span></strong></div>
<span>
<div>
<div style="border-right: #cccccc 1px solid; padding-right: 4px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 10pt; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; color: #000000; word-break: break-all; line-height: 16px; padding-top: 4px; border-bottom: #cccccc 1px solid; font-family: verdana,宋体; background-color: #eeeeee">属性名称：personid <br />
属性值：e01 <br />
属性名称：enable <br />
属性值：true <br />
属性名称：personid <br />
属性值：e02 <br />
属性名称：enable <br />
属性值：false <br />
属性名称：personid <br />
属性值：e03 <br />
属性名称：enable <br />
属性值：true <br />
节点名称：people <br />
节点值： <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
节点名称：person <br />
节点值： <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
节点名称：name <br />
节点值：张三 <br />
节点名称：tel <br />
节点值：5128 <br />
节点名称：email <br />
节点值：txq512@sina.com <br />
节点名称：person <br />
节点值： <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
节点名称：name <br />
节点值：meixin <br />
节点名称：tel <br />
节点值：5252525 <br />
节点名称：email <br />
节点值：wnight88@sina.com <br />
节点名称：person <br />
节点值： <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
节点名称：name <br />
节点值：yu <br />
节点名称：tel <br />
节点值：5389654 <br />
节点名称：email <br />
节点值：yu@188.net <br />
</div>
</div>
<div style="margin: 12pt 0cm"><strong><span style="font-size: 14pt; color: purple; font-family: tahoma"  Times New Roman?;??><span style="font-size: 14pt; color: purple; font-family: 幼圆">文件内容</span></strong></div>
<span>
<div>
<div style="border-right: #cccccc 1px solid; padding-right: 4px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 10pt; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; color: #000000; word-break: break-all; line-height: 16px; padding-top: 4px; border-bottom: #cccccc 1px solid; font-family: verdana,宋体; background-color: #eeeeee"><font color="#0000ff">&lt;?</font><font color="#800000">xml</font> <font color="#ff0000">version</font><font color="#0000ff">="1.0"</font> <font color="#ff0000">encoding</font><font color="#0000ff">="UTF-8"</font><font color="#0000ff">?&gt;</font> <br />
<font color="#0000ff">&lt;</font><font color="#800000">people</font><font color="#0000ff">&gt;</font> <br />
<br />
&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">person</font> <font color="#ff0000">personid</font><font color="#0000ff">="e01"</font> <font color="#ff0000">enable</font><font color="#0000ff">="true"</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">name</font><font color="#0000ff">&gt;</font>张三<font color="#0000ff">&lt;/</font><font color="#800000">name</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">tel</font><font color="#0000ff">&gt;</font>5128<font color="#0000ff">&lt;/</font><font color="#800000">tel</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">email</font><font color="#0000ff">&gt;</font>txq512@sina.com<font color="#0000ff">&lt;/</font><font color="#800000">email</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;<font color="#0000ff">&lt;/</font><font color="#800000">person</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">person</font> <font color="#ff0000">personid</font><font color="#0000ff">="e02"</font> <font color="#ff0000">enable</font><font color="#0000ff">="false"</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">name</font><font color="#0000ff">&gt;</font>meixin<font color="#0000ff">&lt;/</font><font color="#800000">name</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">tel</font><font color="#0000ff">&gt;</font>5252525<font color="#0000ff">&lt;/</font><font color="#800000">tel</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">email</font><font color="#0000ff">&gt;</font>wnight88@sina.com<font color="#0000ff">&lt;/</font><font color="#800000">email</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;<font color="#0000ff">&lt;/</font><font color="#800000">person</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">person</font> <font color="#ff0000">personid</font><font color="#0000ff">="e03"</font> <font color="#ff0000">enable</font><font color="#0000ff">="true"</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">name</font><font color="#0000ff">&gt;</font>yu<font color="#0000ff">&lt;/</font><font color="#800000">name</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">tel</font><font color="#0000ff">&gt;</font>5389654<font color="#0000ff">&lt;/</font><font color="#800000">tel</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">&lt;</font><font color="#800000">email</font><font color="#0000ff">&gt;</font>yu@188.net<font color="#0000ff">&lt;/</font><font color="#800000">email</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;<font color="#0000ff">&lt;/</font><font color="#800000">person</font><font color="#0000ff">&gt;</font> <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">&lt;/</font><font color="#800000">people</font><font color="#0000ff">&gt;</font> <br />
</div>
<br />
</div>
http://wnight88.blog.51cto.com/512204/163197/</span></span></span></span></strong>
<img src ="http://www.blogjava.net/caizh2009/aggbug/350042.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2011-05-11 22:34 <a href="http://www.blogjava.net/caizh2009/archive/2011/05/11/350042.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 框架的设计理念与设计模式分析</title><link>http://www.blogjava.net/caizh2009/archive/2011/02/15/344368.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 15 Feb 2011 08:13:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2011/02/15/344368.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/344368.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2011/02/15/344368.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/344368.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/344368.html</trackback:ping><description><![CDATA[<table style="border-collapse: collapse; word-wrap: break-word; " border="0" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td width="100%">
            <div id="art" width="100%" style="margin: 15px;">
            <p><strong>简介：</strong>&nbsp;Spring
            作为现在最优秀的框架之一，已被广泛的使用，并且有很多对其分析的文章。本文将从另外一个视角试图剖析出 Spring 框架的作者设计 Spring
            框架的骨骼架构的设计理念，有那几个核心组件？为什么需要这些组件？它们又是如何结合在一起构成 Spring 的骨骼架构？ Spring 的
            AOP 特性又是如何利用这些基础的骨骼架构来工作的？ Spring
            中又使用了那些设计模式来完成它的这种设计的？它的这种设计理念对对我们以后的软件设计有何启示？本文将详细解答这些问题。</p>
            <div>
            <p><a name="major1"><span class="atitle"><strong>Spring 的骨骼架构</strong></span></a></p>
            <p>Spring 总共有十几个组件，但是真正核心的组件只有几个，下面是 Spring 框架的总体架构图：</p>
            <br />
            <a name="fig1"><strong><font size="2" face="Arial">图 1 .Spring 框架的总体架构图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 1 .Spring 框架的总体架构图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image001.gif" height="354" width="512" /></font> <br />
            <p>从上图中可以看出 Spring 框架中的核心组件只有三个：Core、Context 和 Beans。它们构建起了整个 Spring 的骨骼架构。没有它们就不可能有 AOP、Web 等上层的特性功能。下面也将主要从这三个组件入手分析 Spring。</p>
            <p><a name="minor1.1"><span class="smalltitle"><strong>Spring 的设计理念</strong></span></a></p>
            <p>前面介绍了 Spring 的三个核心组件，如果再在它们三个中选出核心的话，那就非 Beans 组件莫属了，为何这样说，其实 Spring
            就是面向 Bean 的编程（BOP,Bean Oriented Programming），Bean 在 Spring 中才是真正的主角。</p>
            <p>Bean 在 Spring 中作用就像 Object 对 OOP 的意义一样，没有对象的概念就像没有面向对象编程，Spring 中没有
            Bean 也就没有 Spring 存在的意义。就像一次演出舞台都准备好了但是却没有演员一样。为什么要 Bean 这种角色 Bean 或者为何在
            Spring 如此重要，这由 Spring 框架的设计目标决定，Spring 为何如此流行，我们用 Spring 的原因是什么，想想你会发现原来
            Spring 解决了一个非常关键的问题他可以让你把对象之间的依赖关系转而用配置文件来管理，也就是他的依赖注入机制。而这个注入关系在一个叫
            Ioc 容器中管理，那 Ioc 容器中有又是什么就是被 Bean 包裹的对象。Spring 正是通过把对象包装在 Bean
            中而达到对这些对象管理以及一些列额外操作的目的。</p>
            <p>它这种设计策略完全类似于 Java 实现 OOP 的设计理念，当然了 Java 本身的设计要比 Spring
            复杂太多太多，但是都是构建一个数据结构，然后根据这个数据结构设计他的生存环境，并让它在这个环境中按照一定的规律在不停的运动，在它们的不停运动中设
            计一系列与环境或者与其他个体完成信息交换。这样想来回过头想想我们用到的其他框架都是大慨类似的设计理念。</p>
            <p><a name="minor1.2"><span class="smalltitle"><strong>核心组件如何协同工作</strong></span></a></p>
            <p>前面说 Bean 是 Spring 中关键因素，那 Context 和 Core 又有何作用呢？前面吧 Bean
            比作一场演出中的演员的话，那 Context 就是这场演出的舞台背景，而 Core
            应该就是演出的道具了。只有他们在一起才能具备能演出一场好戏的最基本的条件。当然有最基本的条件还不能使这场演出脱颖而出，还要他表演的节目足够的精
            彩，这些节目就是 Spring 能提供的特色功能了。</p>
            <p>我们知道 Bean 包装的是 Object，而 Object 必然有数据，如何给这些数据提供生存环境就是 Context 要解决的问题，对
            Context 来说他就是要发现每个 Bean 之间的关系，为它们建立这种关系并且要维护好这种关系。所以 Context 就是一个 Bean
            关系的集合，这个关系集合又叫 Ioc 容器，一旦建立起这个 Ioc 容器后 Spring 就可以为你工作了。那 Core
            组件又有什么用武之地呢？其实 Core 就是发现、建立和维护每个 Bean 之间的关系所需要的一些列的工具，从这个角度看来，Core 这个组件叫
            Util 更能让你理解。</p>
            <p>它们之间可以用下图来表示：</p>
            <br />
            <a name="fig2"><strong><font size="2" face="Arial">图 2. 三个组件关系</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 2. 三个组件关系" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image002.gif" height="230" width="435" /></font> <br />
            <p><a name="minor1.3"><span class="smalltitle"><strong>核心组件详解</strong></span></a></p>
            <p>这里将详细介绍每个组件内部类的层次关系，以及它们在运行时的时序顺序。我们在使用 Spring 是应该注意的地方。</p>
            <p><strong>Bean 组件</strong> </p>
            <p>前面已经说明了 Bean 组件对 Spring 的重要性，下面看看 Bean 这个组件式怎么设计的。Bean 组件在 Spring 的
            org.springframework.beans 包下。这个包下的所有类主要解决了三件事：Bean 的定义、Bean 的创建以及对 Bean
            的解析。对 Spring 的使用者来说唯一需要关心的就是 Bean 的创建，其他两个由 Spring 在内部帮你完成了，对你来说是透明的。</p>
            <p>Spring Bean 的创建时典型的工厂模式，他的顶级接口是 BeanFactory，下图是这个工厂的继承层次关系：</p>
            <br />
            <a name="fig3"><strong><font size="2" face="Arial">图 4. Bean 工厂的继承关系</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 4. Bean 工厂的继承关系" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image003.png" height="252" width="572" /></font> <br />
            <p>BeanFactory 有三个子类：ListableBeanFactory、HierarchicalBeanFactory 和
            AutowireCapableBeanFactory。但是从上图中我们可以发现最终的默认实现类是
            DefaultListableBeanFactory，他实现了所有的接口。那为何要定义这么多层次的接口呢？查阅这些接口的源码和说明发现，每个接口
            都有他使用的场合，它主要是为了区分在 Spring 内部在操作过程中对象的传递和转化过程中，对对象的数据访问所做的限制。例如
            ListableBeanFactory 接口表示这些 Bean 是可列表的，而 HierarchicalBeanFactory 表示的是这些
            Bean 是有继承关系的，也就是每个 Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean
            的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为。</p>
            <p>Bean 的定义主要有 BeanDefinition 描述，如下图说明了这些类的层次关系：</p>
            <br />
            <a name="fig4"><strong><font size="2" face="Arial">图 5. Bean 定义的类层次关系图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 5. Bean 定义的类层次关系图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image004.png" height="336" width="497" /></font> <br />
            <p>Bean 的定义就是完整的描述了在 Spring 的配置文件中你定义的 &lt;bean/&gt; 节点中所有的信息，包括各种子节点。当
            Spring 成功解析你定义的一个 &lt;bean/&gt; 节点后，在 Spring 的内部他就被转化成 BeanDefinition
            对象。以后所有的操作都是对这个对象完成的。</p>
            <p>Bean 的解析过程非常复杂，功能被分的很细，因为这里需要被扩展的地方很多，必须保证有足够的灵活性，以应对可能的变化。Bean 的解析主要就是对 Spring 配置文件的解析。这个解析过程主要通过下图中的类完成：</p>
            <br />
            <a name="fig5"><strong><font size="2" face="Arial">图 6. Bean 的解析类</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 6. Bean 的解析类" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image005.png" height="192" width="572" /></font> <br />
            <p>当然还有具体对 tag 的解析这里并没有列出。</p>
            <p><strong>Context 组件</strong> </p>
            <p>Context 在 Spring 的 org.springframework.context 包下，前面已经讲解了 Context 组件在
            Spring 中的作用，他实际上就是给 Spring 提供一个运行时的环境，用以保存各个对象的状态。下面看一下这个环境是如何构建的。</p>
            <p>ApplicationContext 是 Context 的顶级父类，他除了能标识一个应用环境的基本信息外，他还继承了五个接口，这五个接口主要是扩展了 Context 的功能。下面是 Context 的类结构图：</p>
            <br />
            <a name="fig6"><strong><font size="2" face="Arial">图 7. Context 相关的类结构图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 7. Context 相关的类结构图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image006.png" height="234" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image006.png" target="_blank"><font color="#4c6e94">图 7 的清晰版本</font></a>。）</p>
            <p>从上图中可以看出 ApplicationContext 继承了 BeanFactory，这也说明了 Spring 容器中运行的主体对象是
            Bean，另外 ApplicationContext 继承了 ResourceLoader 接口，使得 ApplicationContext
            可以访问到任何外部资源，这将在 Core 中详细说明。</p>
            <p>ApplicationContext 的子类主要包含两个方面：</p>
            <ol type="1">
                <li>ConfigurableApplicationContext 表示该 Context 是可修改的，也就是在构建 Context
                中用户可以动态添加或修改已有的配置信息，它下面又有多个子类，其中最经常使用的是可更新的 Context，即
                AbstractRefreshableApplicationContext 类。
                </li>
                <li>WebApplicationContext 顾名思义，就是为 web 准备的 Context 他可以直接访问到 ServletContext，通常情况下，这个接口使用的少。 </li>
            </ol>
            <p>再往下分就是按照构建 Context 的文件类型，接着就是访问 Context 的方式。这样一级一级构成了完整的 Context 等级层次。</p>
            <p>总体来说 ApplicationContext 必须要完成以下几件事：</p>
            <ul>
                <li>标识一个应用环境
                </li>
                <li>利用 BeanFactory 创建 Bean 对象
                </li>
                <li>保存对象关系表
                </li>
                <li>能够捕获各种事件 </li>
            </ul>
            <p>Context 作为 Spring 的 Ioc 容器，基本上整合了 Spring 的大部分功能，或者说是大部分功能的基础。</p>
            <p><strong>Core 组件</strong> </p>
            <p>Core 组件作为 Spring 的核心组件，他其中包含了很多的关键类，其中一个重要组成部分就是定义了资源的访问方式。这种把所有资源都抽象成一个接口的方式很值得在以后的设计中拿来学习。下面就重要看一下这个部分在 Spring 的作用。</p>
            <p>下图是 Resource 相关的类结构图：</p>
            <br />
            <a name="fig7"><strong><font size="2" face="Arial">图 8. Resource 相关的类结构图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 8. Resource 相关的类结构图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image007.png" height="235" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image007.png" target="_blank"><font color="#4c6e94">图 8 的清晰版本</font></a>。）</p>
            <p>从上图可以看出 Resource
            接口封装了各种可能的资源类型，也就是对使用者来说屏蔽了文件类型的不同。对资源的提供者来说，如何把资源包装起来交给其他人用这也是一个问题，我们看到
            Resource 接口继承了 InputStreamSource 接口，这个接口中有个 getInputStream 方法，返回的是
            InputStream 类。这样所有的资源都被可以通过 InputStream
            这个类来获取，所以也屏蔽了资源的提供者。另外还有一个问题就是加载资源的问题，也就是资源的加载者要统一，从上图中可以看出这个任务是由
            ResourceLoader 接口完成，他屏蔽了所有的资源加载者的差异，只需要实现这个接口就可以加载所有的资源，他的默认实现是
            DefaultResourceLoader。</p>
            <p>下面看一下 Context 和 Resource 是如何建立关系的？首先看一下他们的类关系图：</p>
            <br />
            <a name="fig8"><strong><font size="2" face="Arial">图 9. Context 和 Resource 的类关系图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 9. Context 和 Resource 的类关系图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image008.png" height="359" width="572" /></font> <br />
            <p>从上图可以看出，Context 是把资源的加载、解析和描述工作委托给了 ResourcePatternResolver 类来完成，他相当于一个接头人，他把资源的加载、解析和资源的定义整合在一起便于其他组件使用。Core 组件中还有很多类似的方式。</p>
            <p><strong>Ioc 容器如何工作</strong> </p>
            <p>前面介绍了 Core 组件、Bean 组件和 Context 组件的结构与相互关系，下面这里从使用者角度看一下他们是如何运行的，以及我们如何让 Spring 完成各种功能，Spring 到底能有那些功能，这些功能是如何得来的，下面介绍。</p>
            <p><strong>如何创建 BeanFactory 工厂</strong> </p>
            <p>正如图 2 描述的那样，Ioc 容器实际上就是 Context 组件结合其他两个组件共同构建了一个 Bean
            关系网，如何构建这个关系网？构建的入口就在 AbstractApplicationContext 类的 refresh
            方法中。这个方法的代码如下：</p>
            <br />
            <a name="listing1"><strong><font size="2" face="Arial">清单 1. AbstractApplicationContext.refresh</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        public void refresh() throws BeansException, IllegalStateException {
                        synchronized (this.startupShutdownMonitor) {
                        // Prepare this context for refreshing.
                        prepareRefresh();
                        // Tell the subclass to refresh the internal bean factory.
                        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
                        // Prepare the bean factory for use in this context.
                        prepareBeanFactory(beanFactory);
                        try {
                        // Allows post-processing of the bean factory in context subclasses.
                        postProcessBeanFactory(beanFactory);
                        // Invoke factory processors registered as beans in the context.
                        invokeBeanFactoryPostProcessors(beanFactory);
                        // Register bean processors that intercept bean creation.
                        registerBeanPostProcessors(beanFactory);
                        // Initialize message source for this context.
                        initMessageSource();
                        // Initialize event multicaster for this context.
                        initApplicationEventMulticaster();
                        // Initialize other special beans in specific context subclasses.
                        onRefresh();
                        // Check for listener beans and register them.
                        registerListeners();
                        // Instantiate all remaining (non-lazy-init) singletons.
                        finishBeanFactoryInitialization(beanFactory);
                        // Last step: publish corresponding event.
                        finishRefresh();
                        }
                        catch (BeansException ex) {
                        // Destroy already created singletons to avoid dangling resources.
                        destroyBeans();
                        // Reset 'active' flag.
                        cancelRefresh(ex);
                        // Propagate exception to caller.
                        throw ex;
                        }
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>这个方法就是构建整个 Ioc 容器过程的完整的代码，了解了里面的每一行代码基本上就了解大部分 Spring 的原理和功能了。</p>
            <p>这段代码主要包含这样几个步骤：</p>
            <ul>
                <li>构建 BeanFactory，以便于产生所需的&#8220;演员&#8221;
                </li>
                <li>注册可能感兴趣的事件
                </li>
                <li>创建 Bean 实例对象
                </li>
                <li>触发被监听的事件 </li>
            </ul>
            <p>下面就结合代码分析这几个过程。</p>
            <p>第二三句就是在创建和配置 BeanFactory。这里是 refresh 也就是刷新配置，前面介绍了 Context
            有可更新的子类，这里正是实现这个功能，当 BeanFactory 已存在是就更新，如果没有就新创建。下面是更新 BeanFactory
            的方法代码：</p>
            <br />
            <a name="listing2"><strong><font size="2" face="Arial">清单 2. AbstractRefreshableApplicationContext. refreshBeanFactory</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        protected final void refreshBeanFactory() throws BeansException {
                        if (hasBeanFactory()) {
                        destroyBeans();
                        closeBeanFactory();
                        }
                        try {
                        DefaultListableBeanFactory beanFactory = createBeanFactory();
                        beanFactory.setSerializationId(getId());
                        customizeBeanFactory(beanFactory);
                        loadBeanDefinitions(beanFactory);
                        synchronized (this.beanFactoryMonitor) {
                        this.beanFactory = beanFactory;
                        }
                        }
                        catch (IOException ex) {
                        throw new ApplicationContextException(
                        "I/O error parsing bean definition source for "
                        + getDisplayName(), ex);
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>这个方法实现了 AbstractApplicationContext 的抽象方法
            refreshBeanFactory，这段代码清楚的说明了 BeanFactory 的创建过程。注意 BeanFactory
            对象的类型的变化，前面介绍了他有很多子类，在什么情况下使用不同的子类这非常关键。BeanFactory 的原始对象是
            DefaultListableBeanFactory，这个非常关键，因为他设计到后面对这个对象的多种操作，下面看一下这个类的继承层次类图：</p>
            <br />
            <a name="fig9"><strong><font size="2" face="Arial">图 10. DefaultListableBeanFactory 类继承关系图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 10. DefaultListableBeanFactory 类继承关系图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image009.png" height="253" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image009.png" target="_blank"><font color="#4c6e94">图 10 的清晰版本</font></a>。）</p>
            <p>从这个图中发现除了 BeanFactory 相关的类外，还发现了与 Bean 的 register 相关。这在
            refreshBeanFactory 方法中有一行 loadBeanDefinitions(beanFactory)
            将找到答案，这个方法将开始加载、解析 Bean 的定义，也就是把用户定义的数据结构转化为 Ioc 容器中的特定数据结构。</p>
            <p>这个过程可以用下面时序图解释：</p>
            <br />
            <a name="fig10"><strong><font size="2" face="Arial">图 11. 创建 BeanFactory 时序图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 11. 创建 BeanFactory 时序图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image010.png" height="250" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image010.png" target="_blank"><font color="#4c6e94">图 11 的清晰版本</font></a>。）</p>
            <p>Bean 的解析和登记流程时序图如下：</p>
            <br />
            <a name="fig11"><strong><font size="2" face="Arial">图 12. 解析和登记 Bean 对象时序图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 12. 解析和登记 Bean 对象时序图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image011.png" height="368" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image011.png" target="_blank"><font color="#4c6e94">图 12 的清晰版本</font></a>。）</p>
            <p>创建好 BeanFactory 后，接下去添加一些 Spring 本身需要的一些工具类，这个操作在 AbstractApplicationContext 的 prepareBeanFactory 方法完成。</p>
            <p>AbstractApplicationContext 中接下来的三行代码对 Spring
            的功能扩展性起了至关重要的作用。前两行主要是让你现在可以对已经构建的 BeanFactory 的配置做修改，后面一行就是让你可以对以后再创建
            Bean 的实例对象时添加一些自定义的操作。所以他们都是扩展了 Spring 的功能，所以我们要学习使用 Spring 必须对这一部分搞清楚。</p>
            <p>其中在 invokeBeanFactoryPostProcessors 方法中主要是获取实现 BeanFactoryPostProcessor 接口的子类。并执行它的 postProcessBeanFactory 方法，这个方法的声明如下：</p>
            <br />
            <a name="listing3"><strong><font size="2" face="Arial">清单 3. BeanFactoryPostProcessor.postProcessBeanFactory</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
                        throws BeansException;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>它的参数是 beanFactory，说明可以对 beanFactory 做修改，这里注意这个 beanFactory 是
            ConfigurableListableBeanFactory 类型的，这也印证了前面介绍的不同 BeanFactory
            所使用的场合不同，这里只能是可配置的 BeanFactory，防止一些数据被用户随意修改。</p>
            <p>registerBeanPostProcessors 方法也是可以获取用户定义的实现了 BeanPostProcessor
            接口的子类，并执行把它们注册到 BeanFactory 对象中的 beanPostProcessors
            变量中。BeanPostProcessor
            中声明了两个方法：postProcessBeforeInitialization、postProcessAfterInitialization
            分别用于在 Bean 对象初始化时执行。可以执行用户自定义的操作。</p>
            <p>后面的几行代码是初始化监听事件和对系统的其他监听者的注册，监听者必须是 ApplicationListener 的子类。</p>
            <p><strong>如何创建 Bean 实例并构建 Bean 的关系网</strong> </p>
            <p>下面就是 Bean 的实例化代码，是从 finishBeanFactoryInitialization 方法开始的。</p>
            <br />
            <a name="listing4"><strong><font size="2" face="Arial">清单 4. AbstractApplicationContext.finishBeanFactoryInitialization</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        protected void finishBeanFactoryInitialization(
                        ConfigurableListableBeanFactory beanFactory) {
                        // Stop using the temporary ClassLoader for type matching.
                        beanFactory.setTempClassLoader(null);
                        // Allow for caching all bean definition metadata, not expecting further changes.
                        beanFactory.freezeConfiguration();
                        // Instantiate all remaining (non-lazy-init) singletons.
                        beanFactory.preInstantiateSingletons();
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>从上面代码中可以发现 Bean 的实例化是在 BeanFactory 中发生的。preInstantiateSingletons 方法的代码如下：</p>
            <br />
            <a name="listing5"><strong><font size="2" face="Arial">清单 5. DefaultListableBeanFactory.preInstantiateSingletons</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        public void preInstantiateSingletons() throws BeansException {
                        if (this.logger.isInfoEnabled()) {
                        this.logger.info("Pre-instantiating singletons in " + this);
                        }
                        synchronized (this.beanDefinitionMap) {
                        for (String beanName : this.beanDefinitionNames) {
                        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                        if (!bd.isAbstract() &amp;&amp; bd.isSingleton()
                        &amp;&amp; !bd.isLazyInit()) {
                        if (isFactoryBean(beanName)) {
                        final FactoryBean factory =
                        (FactoryBean) getBean(FACTORY_BEAN_PREFIX+ beanName);
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null
                        &amp;&amp; factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(
                        new PrivilegedAction&lt;Boolean&gt;() {
                        public Boolean run() {
                        return ((SmartFactoryBean) factory).isEagerInit();
                        }
                        }, getAccessControlContext());
                        }
                        else {
                        isEagerInit = factory instanceof SmartFactoryBean
                        &amp;&amp; ((SmartFactoryBean) factory).isEagerInit();
                        }
                        if (isEagerInit) {
                        getBean(beanName);
                        }
                        }
                        else {
                        getBean(beanName);
                        }
                        }
                        }
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>这里出现了一个非常重要的 Bean —— FactoryBean，可以说 Spring 一大半的扩展的功能都与这个 Bean
            有关，这是个特殊的 Bean 他是个工厂 Bean，可以产生 Bean 的 Bean，这里的产生 Bean 是指 Bean
            的实例，如果一个类继承 FactoryBean 用户可以自己定义产生实例对象的方法只要实现他的 getObject 方法。然而在 Spring
            内部这个 Bean 的实例对象是 FactoryBean，通过调用这个对象的 getObject 方法就能获取用户自定义产生的对象，从而为
            Spring 提供了很好的扩展性。Spring 获取 FactoryBean 本身的对象是在前面加上 &amp; 来完成的。</p>
            <p>如何创建 Bean 的实例对象以及如何构建 Bean 实例对象之间的关联关系式 Spring 中的一个核心关键，下面是这个过程的流程图。</p>
            <br />
            <a name="fig12"><strong><font size="2" face="Arial">图 13.Bean 实例创建流程图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 13.Bean 实例创建流程图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image012.gif" height="842" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image012.gif" target="_blank"><font color="#4c6e94">图 13 的清晰版本</font></a>。）</p>
            <p>如果是普通的 Bean 就直接创建他的实例，是通过调用 getBean 方法。下面是创建 Bean 实例的时序图：</p>
            <br />
            <a name="fig13"><strong><font size="2" face="Arial">图 14.Bean 实例创建时序图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 14.Bean 实例创建时序图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image013.png" height="490" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image013.png" target="_blank"><font color="#4c6e94">图 14 的清晰版本</font></a>。）</p>
            <p>还有一个非常重要的部分就是建立 Bean 对象实例之间的关系，这也是 Spring 框架的核心竞争力，何时、如何建立他们之间的关系请看下面的时序图：</p>
            <br />
            <a name="fig14"><strong><font size="2" face="Arial">图 15.Bean 对象关系建立</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 15.Bean 对象关系建立" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image014.png" height="453" width="572" /></font> <br />
            <p>（查看 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/origin_image014.png" target="_blank"><font color="#4c6e94">图 15 的清晰版本</font></a>。）</p>
            <p><strong>Ioc 容器的扩展点</strong> </p>
            <p>现在还有一个问题就是如何让这些 Bean 对象有一定的扩展性，就是可以加入用户的一些操作。那么有哪些扩展点呢？ Spring 又是如何调用到这些扩展点的？</p>
            <p>对 Spring 的 Ioc 容器来说，主要有这么几个。BeanFactoryPostProcessor，
            BeanPostProcessor。他们分别是在构建 BeanFactory 和构建 Bean 对象时调用。还有就是
            InitializingBean 和 DisposableBean 他们分别是在 Bean
            实例创建和销毁时被调用。用户可以实现这些接口中定义的方法，Spring 就会在适当的时候调用他们。还有一个是 FactoryBean
            他是个特殊的 Bean，这个 Bean 可以被用户更多的控制。</p>
            <p>这些扩展点通常也是我们使用 Spring 来完成我们特定任务的地方，如何精通 Spring 就看你有没有掌握好 Spring 有哪些扩展点，并且如何使用他们，要知道如何使用他们就必须了解他们内在的机理。可以用下面一个比喻来解释。</p>
            <p>我们把 Ioc
            容器比作一个箱子，这个箱子里有若干个球的模子，可以用这些模子来造很多种不同的球，还有一个造这些球模的机器，这个机器可以产生球模。那么他们的对应关
            系就是 BeanFactory 就是那个造球模的机器，球模就是 Bean，而球模造出来的球就是 Bean
            的实例。那前面所说的几个扩展点又在什么地方呢？ BeanFactoryPostProcessor
            对应到当造球模被造出来时，你将有机会可以对其做出设当的修正，也就是他可以帮你修改球模。而 InitializingBean 和
            DisposableBean 是在球模造球的开始和结束阶段，你可以完成一些预备和扫尾工作。BeanPostProcessor
            就可以让你对球模造出来的球做出适当的修正。最后还有一个
            FactoryBean，它可是一个神奇的球模。这个球模不是预先就定型了，而是由你来给他确定它的形状，既然你可以确定这个球模型的形状，当然他造出来
            的球肯定就是你想要的球了，这样在这个箱子里尼可以发现所有你想要的球</p>
            <p><strong>Ioc 容器如何为我所用</strong> </p>
            <p>前面的介绍了 Spring 容器的构建过程，那 Spring 能为我们做什么，Spring 的 Ioc 容器又能做什么呢？我们使用
            Spring 必须要首先构建 Ioc 容器，没有它 Spring 无法工作，ApplicatonContext.xml 就是 Ioc
            容器的默认配置文件，Spring 的所有特性功能都是基于这个 Ioc 容器工作的，比如后面要介绍的 AOP。</p>
            <p>Ioc 它实际上就是为你构建了一个魔方，Spring
            为你搭好了骨骼架构，这个魔方到底能变出什么好的东西出来，这必须要有你的参与。那我们怎么参与？这就是前面说的要了解 Spring
            中那有些扩展点，我们通过实现那些扩展点来改变 Spring 的通用行为。至于如何实现扩展点来得到我们想要的个性结果，Spring
            中有很多例子，其中 AOP 的实现就是 Spring 本身实现了其扩展点来达到了它想要的特性功能，可以拿来参考。</p>
            <div class="ibm-alternate-rule">
            <hr />
            </div>
            <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html#ibm-pcon"><font color="#4c6e94"><strong>回页首</strong></font></a></p>
            <p><a name="major2"><span class="atitle"><strong>Spring 中 AOP 特性详解</strong></span></a></p>
            <p><a name="minor2.1"><span class="smalltitle"><strong>动态代理的实现原理</strong></span></a></p>
            <p>要了解 Spring 的 AOP 就必须先了解的动态代理的原理，因为 AOP 就是基于动态代理实现的。动态代理还要从 JDK 本身说起。</p>
            <p>在 Jdk 的 java.lang.reflect 包下有个 Proxy 类，它正是构造代理类的入口。这个类的结构入下：</p>
            <br />
            <a name="fig15"><strong><font size="2" face="Arial">图 16. Proxy 类结构</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 16. Proxy 类结构" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image015.png" height="363" width="472" /></font> <br />
            <p>从上图发现最后面四个是公有方法。而最后一个方法 newProxyInstance 就是创建代理对象的方法。这个方法的源码如下：</p>
            <br />
            <a name="listing6"><strong><font size="2" face="Arial">清单 6. Proxy. newProxyInstance</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        public static Object newProxyInstance(ClassLoader loader,
                        Class&lt;?&gt;[] interfaces,
                        InvocationHandler h)
                        throws IllegalArgumentException {
                        if (h == null) {
                        throw new NullPointerException();
                        }
                        Class cl = getProxyClass(loader, interfaces);
                        try {
                        Constructor cons = cl.getConstructor(constructorParams);
                        return (Object) cons.newInstance(new Object[] { h });
                        } catch (NoSuchMethodException e) {
                        throw new InternalError(e.toString());
                        } catch (IllegalAccessException e) {
                        throw new InternalError(e.toString());
                        } catch (InstantiationException e) {
                        throw new InternalError(e.toString());
                        } catch (InvocationTargetException e) {
                        throw new InternalError(e.toString());
                        }
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>这个方法需要三个参数：ClassLoader，用于加载代理类的 Loader 类，通常这个 Loader 和被代理的类是同一个
            Loader
            类。Interfaces，是要被代理的那些那些接口。InvocationHandler，就是用于执行除了被代理接口中方法之外的用户自定义的操作，
            他也是用户需要代理的最终目的。用户调用目标方法都被代理到 InvocationHandler 类中定义的唯一方法 invoke
            中。这在后面再详解。</p>
            <p>下面还是看看 Proxy 如何产生代理类的过程，他构造出来的代理类到底是什么样子？下面揭晓啦。</p>
            <br />
            <a name="fig16"><strong><font size="2" face="Arial">图 17. 创建代理对象时序图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 17. 创建代理对象时序图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image016.png" height="470" width="534" /></font> <br />
            <p>其实从上图中可以发现正在构造代理类的是在 ProxyGenerator 的 generateProxyClass 的方法中。ProxyGenerator 类在 sun.misc 包下，感兴趣的话可以看看他的源码。</p>
            <p>假如有这样一个接口，如下：</p>
            <br />
            <a name="listing7"><strong><font size="2" face="Arial">清单 7. SimpleProxy 类</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        public interface SimpleProxy {
                        public void simpleMethod1();
                        public void simpleMethod2();
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>代理来生成的类结构如下：</p>
            <br />
            <a name="listing8"><strong><font size="2" face="Arial">清单 8. $Proxy2 类</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        public class $Proxy2 extends java.lang.reflect.Proxy implements SimpleProxy{
                        java.lang.reflect.Method m0;
                        java.lang.reflect.Method m1;
                        java.lang.reflect.Method m2;
                        java.lang.reflect.Method m3;
                        java.lang.reflect.Method m4;
                        int hashCode();
                        boolean equals(java.lang.Object);
                        java.lang.String toString();
                        void simpleMethod1();
                        void simpleMethod2();
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>这个类中的方法里面将会是调用 InvocationHandler 的 invoke 方法，而每个方法也将对应一个属性变量，这个属性变量 m 也将传给 invoke 方法中的 Method 参数。整个代理就是这样实现的。</p>
            <p><a name="minor2.2"><span class="smalltitle"><strong>Spring AOP 如何实现</strong></span></a></p>
            <p>从前面代理的原理我们知道，代理的目的是调用目标方法时我们可以转而执行 InvocationHandler 类的 invoke 方法，所以如何在 InvocationHandler 上做文章就是 Spring 实现 Aop 的关键所在。</p>
            <p>Spring 的 Aop 实现是遵守 Aop 联盟的约定。同时 Spring 又扩展了它，增加了如 Pointcut、Advisor 等一些接口使得更加灵活。</p>
            <p>下面是 Jdk 动态代理的类图：</p>
            <br />
            <a name="fig17"><strong><font size="2" face="Arial">图 18. Jdk 动态代理的类图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 18. Jdk 动态代理的类图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image017.png" height="276" width="572" /></font> <br />
            <p>上图清楚的显示了 Spring 引用了 Aop Alliance 定义的接口。姑且不讨论 Spring 如何扩展 Aop
            Alliance，先看看 Spring 如何实现代理类的，要实现代理类在 Spring 的配置文件中通常是这样定一个 Bean 的，如下：</p>
            <br />
            <a name="listing9"><strong><font size="2" face="Arial">清单 9. 配置代理类 Bean</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        &lt;bean id="testBeanSingleton"
                        class="org.springframework.aop.framework.ProxyFactoryBean"&gt;
                        &lt;property name="proxyInterfaces"&gt;
                        &lt;value&gt;
                        org.springframework.aop.framework.PrototypeTargetTests$TestBean
                        &lt;/value&gt;
                        &lt;/property&gt;
                        &lt;property name="target"&gt;&lt;ref local="testBeanTarget"&gt;&lt;/ref&gt; &lt;/property&gt;
                        &lt;property name="singleton"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
                        &lt;property name="interceptorNames"&gt;
                        &lt;list&gt;
                        &lt;value&gt;testInterceptor&lt;/value&gt;
                        &lt;value&gt;testInterceptor2&lt;/value&gt;
                        &lt;/list&gt;
                        &lt;/property&gt;
                        &lt;/bean&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p>配置上看到要设置被代理的接口，和接口的实现类也就是目标类，以及拦截器也就在执行目标方法之前被调用，这里 Spring 中定义的各种各样的拦截器，可以选择使用。</p>
            <p>下面看看 Spring 如何完成了代理以及是如何调用拦截器的。</p>
            <p>前面提到 Spring Aop 也是实现其自身的扩展点来完成这个特性的，从这个代理类可以看出它正是继承了 FactoryBean 的
            ProxyFactoryBean，FactoryBean 之所以特别就在它可以让你自定义对象的创建方法。当然代理对象要通过 Proxy
            类来动态生成。</p>
            <p>下面是 Spring 创建的代理对象的时序图：</p>
            <br />
            <a name="fig18"><strong><font size="2" face="Arial">图 19.Spring 代理对象的产生</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 19.Spring 代理对象的产生" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image018.png" height="355" width="572" /></font> <br />
            <p>Spring 创建了代理对象后，当你调用目标对象上的方法时，将都会被代理到 InvocationHandler 类的 invoke
            方法中执行，这在前面已经解释。在这里 JdkDynamicAopProxy 类实现了 InvocationHandler 接口。</p>
            <p>下面再看看 Spring 是如何调用拦截器的，下面是这个过程的时序图：</p>
            <br />
            <a name="fig19"><strong><font size="2" face="Arial">图 20.Spring 调用拦截器</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 20.Spring 调用拦截器" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image019.png" height="581" width="572" /></font> <br />
            <p>以上所说的都是 Jdk 动态代理，Spring 还支持一种 CGLIB 类代理，感兴趣自己看吧。</p>
            <div class="ibm-alternate-rule">
            <hr />
            </div>
            <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html#ibm-pcon"><font color="#4c6e94"><strong>回页首</strong></font></a></p>
            <p><a name="major3"><span class="atitle"><strong>Spring 中设计模式分析</strong></span></a></p>
            <p>Spring 中使用的设计模式也很多，比如工厂模式、单例模式、模版模式等，在《 Webx 框架的系统架构与设计模式》、《 Tomcat 的系统架构与模式设计分析》已经有介绍，这里就不赘述了。这里主要介绍代理模式和策略模式。</p>
            <p><a name="minor3.1"><span class="smalltitle"><strong>代理模式</strong></span></a></p>
            <p><strong>代理模式原理</strong> </p>
            <p>代理模式就是给某一个对象创建一个代理对象，而由这个代理对象控制对原对象的引用，而创建这个代理对象就是可以在调用原对象是可以增加一些额外的操作。下面是代理模式的结构：</p>
            <br />
            <a name="fig20"><strong><font size="2" face="Arial">图 21. 代理模式的结构</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 21. 代理模式的结构" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image020.png" height="245" width="398" /></font> <br />
            <ul>
                <li>Subject：抽象主题，它是代理对象的真实对象要实现的接口，当然这可以是多个接口组成。
                </li>
                <li>ProxySubject：代理类除了实现抽象主题定义的接口外，还必须持有所代理对象的引用
                </li>
                <li>RealSubject：被代理的类，是目标对象。 </li>
            </ul>
            <p><strong>Spring 中如何实现代理模式</strong> </p>
            <p>Spring Aop 中 Jdk 动态代理就是利用代理模式技术实现的。在 Spring 中除了实现被代理对象的接口外，还会有
            org.springframework.aop.SpringProxy 和
            org.springframework.aop.framework.Advised 两个接口。Spring 中使用代理模式的结构图如下：</p>
            <br />
            <a name="fig21"><strong><font size="2" face="Arial">图 22. Spring 中使用代理模式的结构图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 22. Spring 中使用代理模式的结构图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image021.gif" height="260" width="441" /></font> <br />
            <p>$Proxy 就是创建的代理对象，而 Subject 是抽象主题，代理对象是通过 InvocationHandler 来持有对目标对象的引用的。</p>
            <p>Spring 中一个真实的代理对象结构如下：</p>
            <br />
            <a name="listing10"><strong><font size="2" face="Arial">清单 10 代理对象 $Proxy4</font></strong></a><br />
            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">
                        public class $Proxy4 extends java.lang.reflect.Proxy implements
                        org.springframework.aop.framework.PrototypeTargetTests$TestBean
                        org.springframework.aop.SpringProxy
                        org.springframework.aop.framework.Advised
                        {
                        java.lang.reflect.Method m16;
                        java.lang.reflect.Method m9;
                        java.lang.reflect.Method m25;
                        java.lang.reflect.Method m5;
                        java.lang.reflect.Method m2;
                        java.lang.reflect.Method m23;
                        java.lang.reflect.Method m18;
                        java.lang.reflect.Method m26;
                        java.lang.reflect.Method m6;
                        java.lang.reflect.Method m28;
                        java.lang.reflect.Method m14;
                        java.lang.reflect.Method m12;
                        java.lang.reflect.Method m27;
                        java.lang.reflect.Method m11;
                        java.lang.reflect.Method m22;
                        java.lang.reflect.Method m3;
                        java.lang.reflect.Method m8;
                        java.lang.reflect.Method m4;
                        java.lang.reflect.Method m19;
                        java.lang.reflect.Method m7;
                        java.lang.reflect.Method m15;
                        java.lang.reflect.Method m20;
                        java.lang.reflect.Method m10;
                        java.lang.reflect.Method m1;
                        java.lang.reflect.Method m17;
                        java.lang.reflect.Method m21;
                        java.lang.reflect.Method m0;
                        java.lang.reflect.Method m13;
                        java.lang.reflect.Method m24;
                        int hashCode();
                        int indexOf(org.springframework.aop.Advisor);
                        int indexOf(org.aopalliance.aop.Advice);
                        boolean equals(java.lang.Object);
                        java.lang.String toString();
                        void sayhello();
                        void doSomething();
                        void doSomething2();
                        java.lang.Class getProxiedInterfaces();
                        java.lang.Class getTargetClass();
                        boolean isProxyTargetClass();
                        org.springframework.aop.Advisor; getAdvisors();
                        void addAdvisor(int, org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvisor(org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void setTargetSource(org.springframework.aop.TargetSource);
                        org.springframework.aop.TargetSource getTargetSource();
                        void setPreFiltered(boolean);
                        boolean isPreFiltered();
                        boolean isInterfaceProxied(java.lang.Class);
                        boolean removeAdvisor(org.springframework.aop.Advisor);
                        void removeAdvisor(int)throws org.springframework.aop.framework.AopConfigException;
                        boolean replaceAdvisor(org.springframework.aop.Advisor,
                        org.springframework.aop.Advisor)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvice(org.aopalliance.aop.Advice)
                        throws org.springframework.aop.framework.AopConfigException;
                        void addAdvice(int, org.aopalliance.aop.Advice)
                        throws org.springframework.aop.framework.AopConfigException;
                        boolean removeAdvice(org.aopalliance.aop.Advice);
                        java.lang.String toProxyConfigString();
                        boolean isFrozen();
                        void setExposeProxy(boolean);
                        boolean isExposeProxy();
                        }
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            <p><a name="minor3.2"><span class="smalltitle"><strong>策略模式</strong></span></a></p>
            <p><strong>策略模式原理</strong> </p>
            <p>策略模式顾名思义就是做某事的策略，这在编程上通常是指完成某个操作可能有多种方法，这些方法各有千秋，可能有不同的适应的场合，然而这些操作方法都有可能用到。各一个操作方法都当作一个实现策略，使用者可能根据需要选择合适的策略。</p>
            <p>下面是策略模式的结构：</p>
            <br />
            <a name="fig22"><strong><font size="2" face="Arial">图 23. 策略模式的结构</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 23. 策略模式的结构" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image022.png" height="223" width="458" /></font> <br />
            <ul>
                <li>Context：使用不同策略的环境，它可以根据自身的条件选择不同的策略实现类来完成所要的操作。它持有一个策略实例的引用。创建具体策略对象的方法也可以由他完成。
                </li>
                <li>Strategy：抽象策略，定义每个策略都要实现的策略方法
                </li>
                <li>ConcreteStrategy：具体策略实现类，实现抽象策略中定义的策略方法 </li>
            </ul>
            <p><strong>Spring 中策略模式的实现</strong> </p>
            <p>Spring 中策略模式使用有多个地方，如 Bean 定义对象的创建以及代理对象的创建等。这里主要看一下代理对象创建的策略模式的实现。</p>
            <p>前面已经了解 Spring 的代理方式有两个 Jdk 动态代理和 CGLIB 代理。这两个代理方式的使用正是使用了策略模式。它的结构图如下所示：</p>
            <br />
            <a name="fig23"><strong><font size="2" face="Arial">图 24. Spring 中策略模式结构图</font></strong></a><br />
            <font size="2" face="Arial"><img alt="图 24. Spring 中策略模式结构图" src="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/image023.png" height="345" width="572" /></font> <br />
            <p>在上面结构图中与标准的策略模式结构稍微有点不同，这里抽象策略是 AopProxy 接口，Cglib2AopProxy 和
            JdkDynamicAopProxy 分别代表两种策略的实现方式，ProxyFactoryBean 就是代表 Context
            角色，它根据条件选择使用 Jdk 代理方式还是 CGLIB 方式，而另外三个类主要是来负责创建具体策略对象，ProxyFactoryBean
            是通过依赖的方法来关联具体策略对象的，它是通过调用策略对象的 getProxy(ClassLoader classLoader)
            方法来完成操作。</p>
            <div class="ibm-alternate-rule">
            <hr />
            </div>
            <p class="ibm-ind-link ibm-back-to-top"><a class="ibm-anchor-up-link" href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html#ibm-pcon"><font color="#4c6e94"><strong>回页首</strong></font></a></p>
            <p><a name="major4"><span class="atitle"><strong>总结</strong></span></a></p>
            <p>本文通过从 Spring 的几个核心组件入手，试图找出构建 Spring 框架的骨骼架构，进而分析 Spring
            在设计的一些设计理念，是否从中找出一些好的设计思想，对我们以后程序设计能提供一些思路。接着再详细分析了 Spring
            中是如何实现这些理念的，以及在设计模式上是如何使用的。</p>
            <p>通过分析 Spring 给我一个很大的启示就是其这套设计理念其实对我们有很强的借鉴意义，它通过抽象复杂多变的对象，进一步做规范，然后根据它定义的这套规范设计出一个容器，容器中构建它们的复杂关系，其实现在有很多情况都可以用这种类似的处理方法。</p>
            <p>虽然我很想把我对 Spring 的想法完全阐述清楚，但是所谓&#8220;书不尽言，言不尽意。&#8221;，有什么不对或者不清楚的地方大家还是看看其源码吧。</p>
            <!-- CMA ID: 495409 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file:  dw-article-6.0-beta.xsl --></div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<p style="line-height: 150%; margin: 5px;">
</p>
&nbsp;<font color="#000099"><strong>原文地址</strong></font>
<a href="http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html" target="_blank">http://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/index.html</a>
<img src ="http://www.blogjava.net/caizh2009/aggbug/344368.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2011-02-15 16:13 <a href="http://www.blogjava.net/caizh2009/archive/2011/02/15/344368.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java反射详解</title><link>http://www.blogjava.net/caizh2009/archive/2011/01/13/342941.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 13 Jan 2011 09:09:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2011/01/13/342941.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/342941.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2011/01/13/342941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/342941.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/342941.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Java的反射机制是Java特性之一，反射机制是构建框架技术的基础所在。灵活掌握Java反射机制，对大家以后学习框架技术有很大的帮助。&nbsp;&nbsp;那么什么是Java的反射呢？&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大家都知道，要让Java程序能够运行，那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载，是不...&nbsp;&nbsp;<a href='http://www.blogjava.net/caizh2009/archive/2011/01/13/342941.html'>阅读全文</a><img src ="http://www.blogjava.net/caizh2009/aggbug/342941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2011-01-13 17:09 <a href="http://www.blogjava.net/caizh2009/archive/2011/01/13/342941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java对象序列化（整理篇）</title><link>http://www.blogjava.net/caizh2009/archive/2011/01/13/342921.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 13 Jan 2011 05:29:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2011/01/13/342921.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/342921.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2011/01/13/342921.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/342921.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/342921.html</trackback:ping><description><![CDATA[<span id="ArticleContent1_ArticleContent1_lblContent">
<p>&nbsp;在网上看了很多有关序列化的文
章，我自己也写了两篇，现在感觉这些文章都没有很好的把序列化说清楚(包括我自己在内)，所以在此我将总结前人以及自己的经验，用更浅显易懂的语言来描述
该机制，当然，仍然会有不好的地方，希望你看后可以指出，作为一名程序员应该具有不断探索的精神和强烈的求知欲望！</p>
<p>序列化概述：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
简单来说序列化就是一种用来处理对象流的机制，所谓对象流也就是将对象的内容进行流化，流的概念这里不用多说(就是I/O)，我们可以对流化后的对象进行
读写操作，也可将流化后的对象传输于网络之间(注：要想将对象传输于网络必须进行流化)！在对对象流进行读写操作时会引发一些问题，而序列化机制正是用来
解决这些问题的！</p>
<p>问题的引出：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
如上所述，读写对象会有什么问题呢？比如：我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗？别急，其中一个最大的问题就是对象引用！举个例子
来说：假如我有两个类，分别是A和B，B类中含有一个指向A类对象的引用，现在我们对两个类进行实例化{ A a = new A(); B b =
new B();
}，这时在内存中实际上分配了两个空间，一个存储对象a，一个存储对象b，接下来我们想将它们写入到磁盘的一个文件中去，就在写入文件时出现了问题！因为
对象b包含对对象a的引用，所以系统会自动的将a的数据复制一份到b中，这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时，内存分配了三个
空间，而对象a同时在内存中存在两份，想一想后果吧，如果我想修改对象a的数据的话，那不是还要搜索它的每一份拷贝来达到对象数据的一致性，这不是我们所
希望的！</p>
<p>以下序列化机制的解决方案：</p>
<p>1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)</p>
<p>2.当要保存一个对象时，先检查该对象是否被保存了。</p>
<p>3.如果以前保存过，只需写入"与已经保存的具有序列号x的对象相同"的标记，否则，保存该对象</p>
<p>通过以上的步骤序列化机制解决了对象引用的问题！</p>
<p>序列化的实现：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
将需要被序列化的类实现Serializable接口，该接口没有需要实现的方法，implements
Serializable只是为了标注该对象是可被序列化的，然后使用一个输出流(如：FileOutputStream)来构造一个
ObjectOutputStream(对象流)对象，接着，使用ObjectOutputStream对象的writeObject(Object
obj)方法就可以将参数为obj的对象写出(即保存其状态)，要恢复的话则用输入流。</p>
<p>例子：</p>
<p>import java.io.*;</p>
<p>public class Test <br />
{<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) <br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Employee harry = new Employee("Harry Hacker", 50000);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Manager manager1 = new Manager("Tony Tester", 80000);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; manager1.setSecretary(harry);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Employee[] staff = new Employee[2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; staff[0] = harry;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; staff[1] = manager1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream out = new ObjectOutputStream(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new FileOutputStream("employee.dat"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.writeObject(staff);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectInputStream in = new ObjectInputStream(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new FileInputStream("employee.dat"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Employee[] newStaff = (Employee[])in.readObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in.close();<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *通过harry对象来加薪<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *将在secretary上反映出来<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newStaff[0].raiseSalary(10);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; newStaff.length; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(newStaff[i]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
}</p>
<p>class Employee implements Serializable<br />
{<br />
&nbsp;&nbsp;&nbsp; public Employee(String n, double s)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name = n;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; salary = s;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; *加薪水<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public void raiseSalary(double byPercent)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double raise = salary * byPercent / 100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; salary += raise;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public String toString()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getClass().getName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "[name = "+ name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ",salary = "+ salary<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "]";<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private String name;<br />
&nbsp;&nbsp;&nbsp; private double salary;<br />
}</p>
<p>class Manager extends Employee<br />
{<br />
&nbsp;&nbsp;&nbsp; public Manager(String n, double s)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(n, s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; secretary = null;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp; *设置秘书<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; public void setSecretary(Employee s)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; secretary = s;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public String toString()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.toString()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "[secretary = "+ secretary<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "]";<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; //secretary代表秘书<br />
&nbsp;&nbsp;&nbsp; private Employee secretary;&nbsp;<br />
}</p>
<p>修改默认的序列化机制：&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在
序列化的过程中，有些数据字段我们不想将其序列化，对于此类字段我们只需要在定义时给它加上transient关键字即可，对于transient字段序
列化机制会跳过不会将其写入文件，当然也不可被恢复。但有时我们想将某一字段序列化，但它在SDK中的定义却是不可序列化的类型，这样的话我们也必须把他
标注为transient，可是不能写入又怎么恢复呢？好在序列化机制为包含这种特殊问题的类提供了如下的方法定义：</p>
<p>private&nbsp;void readObject(ObjectInputStream in) throws </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IOException, ClassNotFoundException;</p>
<p>private void writeObject(ObjectOutputStream out) throws</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IOException;</p>
<p>(注：这些方法定义时必须是私有的，因为不需要你显示调用，序列化机制会自动调用的)</p>
<p>使用以上方法我们可以手动对那些你又想序列化又不可以被序列化的数据字段进行写出和读入操作。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面是一个典型的例子，java.awt.geom包中的Point2D.Double类就是不可序列化的，因为该类没有实现Serializable接口，在我的例子中将把它当作LabeledPoint类中的一个数据字段，并演示如何将其序列化！</p>
<p>import java.io.*;<br />
import java.awt.geom.*;</p>
<p>public class TransientTest <br />
{<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) <br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(label);//写入前<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream out = new ObjectOutputStream(new<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileOutputStream("Label.txt"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.writeObject(label);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(label);//写入后<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectInputStream in = new ObjectInputStream(new<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileInputStream("Label.txt"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LabeledPoint label1 = (LabeledPoint)in.readObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(label1);//读出并加1.0后<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
}</p>
<p>class LabeledPoint implements Serializable<br />
{<br />
&nbsp;&nbsp;&nbsp; public LabeledPoint(String str, double x, double y)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label = str;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point = new Point2D.Double(x, y);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private void writeObject(ObjectOutputStream out) throws IOException<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *必须通过调用defaultWriteObject()方法来写入<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *对象的描述以及那些可以被序列化的字段<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.defaultWriteObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.writeDouble(point.getX());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.writeDouble(point.getY());<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private void readObject(ObjectInputStream in)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws IOException, ClassNotFoundException<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *必须调用defaultReadObject()方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in.defaultReadObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double x = in.readDouble() + 1.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double y = in.readDouble() + 1.0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point = new Point2D.Double(x, y);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public String toString()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getClass().getName()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "[label = "+ label<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ", point.getX() = "+ point.getX()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ", point.getY() = "+ point.getY()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "]";<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private&nbsp; String label;<br />
&nbsp;&nbsp;&nbsp; transient private Point2D.Double point;<br />
}<br />
&nbsp;</p>
<p>&nbsp;</p>
</span>
<br />
<div style="font-size: 14px; line-height: 25px;"><strong>作者Blog：</strong><a id="ArticleContent1_ArticleContent1_AuthorBlogLink" href="http://blog.csdn.net/hdAptechIvan/" target="_blank">http://blog.csdn.net/hdAptechIvan/</a></div>
<img src ="http://www.blogjava.net/caizh2009/aggbug/342921.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2011-01-13 13:29 <a href="http://www.blogjava.net/caizh2009/archive/2011/01/13/342921.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中文汉字排序</title><link>http://www.blogjava.net/caizh2009/archive/2010/12/17/340974.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 17 Dec 2010 05:22:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/12/17/340974.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/340974.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/12/17/340974.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/340974.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/340974.html</trackback:ping><description><![CDATA[<p><span style="color: #808080;"><span style="color: #00ff00;"><span style="color: #339966;">// Collator 类是用来执行区分语言环境的 String 比较的，这里选择使用CHINA&nbsp;&nbsp;&nbsp;</span>
&nbsp;</span>
&nbsp;&nbsp;&nbsp;</span>
</p>
<p><span style="color: #ff6600;"> Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);&nbsp;</span>
</p>
<p><span style="color: #ff6600;">TreeMap tree=new TreeMap(cmp);</span>
<span style="color: #808080;"><span style="color: #ff6600;"> &nbsp;&nbsp;&nbsp; </span>
<br />
</span>
</p>
<p><span style="color: #808080;"><span style="color: #ff6600;">&nbsp; String[] arr = {"张三", "李四", "王五"};&nbsp;&nbsp;&nbsp;</span>
&nbsp;&nbsp;&nbsp; </span>
</p>
<p><span style="color: #808080;"><span style="color: #339966;">// 使根据指定比较器产生的顺序对指定对象数组进行排序。&nbsp;</span>
&nbsp;&nbsp;&nbsp;&nbsp;</span>
</p>
<p><span style="color: #ff6600;">&nbsp;&nbsp; Arrays.sort(arr, cmp);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
</p>
<p><span style="color: #ff6600;">&nbsp; for (int i = 0; i &lt; arr.length; i++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
</p>
<p><span style="color: #ff6600;">&nbsp;&nbsp;&nbsp; System.out.println(arr[i]);</span>
</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="color: #808080;">
</span></p>
<p>&lt;script&gt;<br />
&nbsp;names = ["张三", "李四", "王五", "刘六"];<br />
&nbsp;names.sort(function(a,b){return a.localeCompare(b)});//a,b 为数组a的某两个值，自动传入<br />
&nbsp;alert(names);<br />
&lt;/script&gt;</p>
<p>&nbsp;</p>
<p>另:</p>
<p>
</p>
<h4>示例文本：</h4>
<p><br />
<strong><br />
String&nbsp;[]&nbsp;test&nbsp;=&nbsp;new&nbsp;String[]&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"作业",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"测试",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"test",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"我们",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"。空",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"镂空",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"[",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"浏",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"皙"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
</strong>
</p>
<h4>jdk&nbsp;版本：</h4>
<p>&nbsp;1.5.6</p>
<h4>开发平台：</h4>
<p>&nbsp;Eclipse&nbsp;3.1</p>
<h4>关键字：&nbsp;中文排序</h4>
<p>&nbsp;</p>
<h3>概述</h3>
<p><br />
我们在应用程序中可能会经常遇到对中文排序的问题，例如姓名列表，词汇表等等。对中文排序，我们使用比较多的是根据汉语拼音发音来确定顺序。<br />
<br />
我们可能会经常使用&nbsp; </p>
<div class="codeStyle">
<ol>
    <li>java.util.<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/util/Set.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Set</span>
    </span>
    </a>
    </strong>
    </li>
</ol>
</div>
<p>&nbsp;接口， </p>
<div class="codeStyle">
<ol>
    <li>java.util.<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/util/Arrays.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Arrays</span>
    </span>
    </a>
    </strong>
    .sort((T[]&nbsp;a,&nbsp;<span style="color: #ff0000;">Comparator</span>
    &lt;?&nbsp;<strong><span style="color: #0000ff;">super</span>
    </strong>
    &nbsp;T&gt;&nbsp;c)) </li>
</ol>
</div>
<p>&nbsp;等类或方法对含有中文字符的对象进行排序，但是这些在默认情况下都是调用&nbsp; </p>
<div class="codeStyle">
<ol>
    <li><strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
    </span>
    </a>
    </strong>
    .CompareTo(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
    </span>
    </a>
    </strong>
    ) </li>
</ol>
</div>
<p>方法，这个方法是比较2个字符的&nbsp;codepoint&nbsp;value，如果第一个字符的值小于第二个，则在排序结果中第一个会在前面，反之亦然。</p>
<h3>
<div class="codeStyle">
<ol>
    <li>java.text.<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/Collator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Collator</span>
    </span>
    </a>
    </strong>
    </li>
</ol>
</div>
接口及其实现类</h3>
<p><br />
其实&nbsp;java&nbsp;中提供了和语言相关的类，即&nbsp;Collator&nbsp;接口及其实现类。 </p>
<div class="codeStyle">
<ol>
    <li>java.text.<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
    </span>
    </a>
    </strong>
    </li>
</ol>
</div>
<p>&nbsp;是一个具体类，它实现了&nbsp;Comparator&nbsp;接口中的&nbsp;compare(Object,&nbsp;Object)&nbsp;方法。
RuleBasedCollator&nbsp;根据根据特定语言的默认规则比较字符，也可以按照指定的规则来比较，请参阅&nbsp;java&nbsp;API&nbsp;获取此类的详细信
息。<br />
如果我们需要对一个有中文的数组进行排序，则可以使用这个类。请看如下示例代码：</p>
<div class="codeStyle">
<ol>
    <li><strong><span style="color: #0000ff;">import</span>
    </strong>
    &nbsp;java.util.*; </li>
    <li><strong><span style="color: #0000ff;">import</span>
    </strong>
    &nbsp;java.text.*; </li>
    <li><strong><span style="color: #0000ff;">public</span>
    </strong>
    &nbsp;<strong><span style="color: #0000ff;">class</span>
    </strong>
    &nbsp;Test </li>
    <li>{ </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
    </span>
    </a>
    </strong>
    &nbsp;[]&nbsp;test&nbsp;=&nbsp;<strong><span style="color: #0000ff;">new</span>
    </strong>
    &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
    </span>
    </a>
    </strong>
    []&nbsp;{ </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"作业"</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"测试"</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"test"</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"我们"</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"。空"</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"镂空"</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"["</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"浏"</span>
    , </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"皙"</span>
    </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.util.<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/util/Arrays.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Arrays</span>
    </span>
    </a>
    </strong>
    .sort(test,&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
    </span>
    </a>
    </strong>
    )<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/Collator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Collator</span>
    </span>
    </a>
    </strong>
    .getInstance(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/util/Locale.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Locale</span>
    </span>
    </a>
    </strong>
    .CHINA)); </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/System.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">System</span>
    </span>
    </a>
    </strong>
    .out.println(<span style="color: #ff33ff;">"============"</span>
    ); </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">for</span>
    </strong>
    (<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
    </span>
    </a>
    </strong>
    &nbsp;key&nbsp;:&nbsp;test) </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/System.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">System</span>
    </span>
    </a>
    </strong>
    .out.println(key); </li>
    <li>} </li>
</ol>
</div>
<p><br />
<br />
以上代码的输出结果为：<br />
<strong><br />
============<br />
[<br />
test<br />
。空<br />
测试<br />
我们<br />
作业<br />
浏<br />
镂空<br />
皙<br />
</strong>
<br />
<br />
大家可能会发现只有一部分汉字是按照汉语拼音排序了，还有几个没有。</p>
<h3>问题分析：</h3>
<p><br />
GB2312:<br />
在简体中文中我们使用比较多的字符集是&nbsp;GB2312-80，简称为&nbsp;GB2312，这个字符集包含了目前最常用的汉字共计&nbsp;6736&nbsp;个。其中的汉字分为两大类：</p>
<ul>
    常用汉字
</ul>
<p>&nbsp;</p>
<ul>
    次常用汉字
</ul>
<p><br />
<br />
常用汉字按照汉语拼音来排序，而次常用汉字按照笔画部首进行排序。<br />
<br />
简体汉字在&nbsp;Unicode&nbsp;中一般是按照&nbsp;gb2312&nbsp;的码点值的顺序来放置的，所以如果是常用汉字&nbsp;java&nbsp;就能够很准确的进行排序，但如果是次常用汉字，则就会出现问题。在以上示例中，"镂"，"皙"&nbsp;属于次常用字。</p>
<h3>解决方案：</h3>
<p><br />
RuleBasedCollator&nbsp;类&nbsp;getRules()&nbsp;方法可以返回对应语言的规则设置。简体中文对应的规则是&nbsp;gb2312&nbsp;所对应的字符。</p>
<ol><br />
    我们可以把其中的全部汉字提取出来</ol>
    <p>&nbsp;</p>
    <ol>对这些汉字重新排序</ol>
        <p>&nbsp;</p>
        <ol>利用RuleBasedCollator(String&nbsp;rules)&nbsp;构造器新建一个定制的&nbsp;RuleBasedCollator</ol>
            <p>&nbsp;</p>
            <h3>参考代码</h3>
            <p><br />
            在以下的代码中，我把排过序的汉字直接作为&nbsp;String&nbsp;对象放在类里面了，如果要让代码变得简洁一些，则可以把完整的规则（特殊字符＋排序汉字）存为文件。</p>
            <div class="codeStyle">
            <ol>
                <li><strong><span style="color: #0000ff;">package</span>
                </strong>
                &nbsp;sorting; </li>
                <li><strong><span style="color: #0000ff;">import</span>
                </strong>
                &nbsp;java.util.*; </li>
                <li><strong><span style="color: #0000ff;">import</span>
                </strong>
                &nbsp;java.text.*; </li>
                <li><em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;*&nbsp;@author&nbsp;GaoJianMin</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;*</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;*/</span>
                </em>
                </li>
                <li><strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">class</span>
                </strong>
                &nbsp;ChineseGB2312Collator </li>
                <li>{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;a&nbsp;customized&nbsp;RuleBasedCollator&nbsp;with&nbsp;Chinese&nbsp;characters&nbsp;(GB2312)&nbsp;sorted&nbsp;correctly</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">static</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">final</span>
                </strong>
                &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
                </span>
                </a>
                </strong>
                &nbsp;getFixedGB2312Collator() </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
                </span>
                </a>
                </strong>
                &nbsp;fixedGB2312Collator&nbsp;=<strong><span style="color: #0000ff;">null</span>
                </strong>
                ; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">try</span>
                </strong>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixedGB2312Collator&nbsp;=&nbsp;<strong><span style="color: #0000ff;">new</span>
                </strong>
                &nbsp;java.text.<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
                </span>
                </a>
                </strong>
                ( </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChineseGB2312Collator.getGB2312SpecialChars()&nbsp;+ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GB2312Chars </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<strong><span style="color: #0000ff;">catch</span>
                </strong>
                (<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/ParseException.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">ParseException</span>
                </span>
                </a>
                </strong>
                &nbsp;e) </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace(); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">return</span>
                </strong>
                &nbsp;fixedGB2312Collator; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;the&nbsp;special&nbsp;characters&nbsp;in&nbsp;GB2312&nbsp;charset.</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">static</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">final</span>
                </strong>
                &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;getGB2312SpecialChars() </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
                </span>
                </a>
                </strong>
                &nbsp;zh_CNCollator&nbsp;=&nbsp;(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
                </span>
                </a>
                </strong>
                )<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/Collator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Collator</span>
                </span>
                </a>
                </strong>
                .getInstance(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/util/Locale.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Locale</span>
                </span>
                </a>
                </strong>
                .CHINA); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">//index&nbsp;2125&nbsp;is&nbsp;the&nbsp;last&nbsp;symbol&nbsp;"╋"</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">return</span>
                </strong>
                &nbsp;zh_CNCollator.getRules().substring(0,2125); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;6763&nbsp;Chinese&nbsp;characters&nbsp;in&nbsp;GB2312&nbsp;charset</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">static</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">final</span>
                </strong>
                &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;GB2312Chars&nbsp;= </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"&lt;吖&lt;阿&lt;啊&lt;
                锕&lt;嗄&lt;哎&lt;哀&lt;唉&lt;埃&lt;挨&lt;锿&lt;捱&lt;皑&lt;癌&lt;嗳&lt;矮&lt;蔼&lt;
                霭&lt;艾&lt;爱&lt;砹&lt;隘&lt;嗌&lt;嫒&lt;碍&lt;暧&lt;瑷&lt;安&lt;桉&lt;氨&lt;庵&lt;
                谙&lt;鹌&lt;鞍&lt;俺&lt;埯&lt;铵&lt;揞&lt;犴&lt;岸&lt;按&lt;案&lt;胺&lt;暗&lt;黯&lt;
                肮&lt;昂&lt;盎&lt;凹&lt;坳&lt;敖&lt;嗷&lt;廒&lt;獒&lt;遨&lt;熬&lt;翱&lt;聱&lt;螯&lt;
                鳌&lt;鏖&lt;拗&lt;袄&lt;媪&lt;岙&lt;傲&lt;奥&lt;骜&lt;澳&lt;懊&lt;鏊"</span>
                &nbsp;+ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"&lt;八&lt;巴&lt;叭&lt;
                扒&lt;吧&lt;岜&lt;芭&lt;疤&lt;捌&lt;笆&lt;粑&lt;拔&lt;茇&lt;菝&lt;跋&lt;魃&lt;把&lt;
                钯&lt;靶&lt;坝&lt;爸&lt;罢&lt;鲅&lt;霸&lt;灞&lt;掰&lt;白&lt;百&lt;佰&lt;柏&lt;捭&lt;
                摆&lt;呗&lt;败&lt;拜&lt;稗&lt;扳&lt;班&lt;般&lt;颁&lt;斑&lt;搬&lt;瘢&lt;癍&lt;阪&lt;
                坂&lt;板&lt;版&lt;钣&lt;舨&lt;办&lt;半&lt;伴&lt;扮&lt;拌&lt;绊&lt;瓣&lt;邦&lt;帮&lt;
                梆&lt;浜&lt;绑&lt;榜&lt;膀&lt;蚌&lt;傍&lt;棒&lt;谤&lt;蒡&lt;磅&lt;镑&lt;勹&lt;包&lt;
                孢&lt;苞&lt;胞&lt;煲&lt;龅&lt;褒&lt;雹&lt;宝&lt;饱&lt;保&lt;鸨&lt;堡&lt;葆&lt;褓&lt;
                报&lt;抱&lt;豹&lt;趵&lt;鲍&lt;暴&lt;爆&lt;陂&lt;卑&lt;杯&lt;悲&lt;碑&lt;鹎&lt;北&lt;
                贝&lt;狈&lt;邶&lt;备&lt;背&lt;钡&lt;倍&lt;悖&lt;被&lt;惫&lt;焙&lt;辈&lt;碚&lt;蓓&lt;
                褙&lt;鞴&lt;鐾&lt;奔&lt;贲&lt;锛&lt;本&lt;苯&lt;畚&lt;坌&lt;笨&lt;崩&lt;绷&lt;嘣&lt;
                甭&lt;泵&lt;迸&lt;甏&lt;蹦&lt;逼&lt;荸&lt;鼻&lt;匕&lt;比&lt;吡&lt;妣&lt;彼&lt;秕&lt;
                俾&lt;笔&lt;舭&lt;鄙&lt;币&lt;必&lt;毕&lt;闭&lt;庇&lt;畀&lt;哔&lt;毖&lt;荜&lt;陛&lt;
                毙&lt;狴&lt;铋&lt;婢&lt;庳&lt;敝&lt;萆&lt;弼&lt;愎&lt;筚&lt;滗&lt;痹&lt;蓖&lt;裨&lt;
                跸&lt;辟&lt;弊&lt;碧&lt;箅&lt;蔽&lt;壁&lt;嬖&lt;篦&lt;薜&lt;避&lt;濞&lt;臂&lt;髀&lt;
                璧&lt;襞&lt;边&lt;砭&lt;笾&lt;编&lt;煸&lt;蝙&lt;鳊&lt;鞭&lt;贬&lt;扁&lt;窆&lt;匾&lt;
                碥&lt;褊&lt;卞&lt;弁&lt;忭&lt;汴&lt;苄&lt;拚&lt;便&lt;变&lt;缏&lt;遍&lt;辨&lt;辩&lt;
                辫&lt;灬&lt;杓&lt;彪&lt;标&lt;飑&lt;髟&lt;骠&lt;膘&lt;瘭&lt;镖&lt;飙&lt;飚&lt;镳&lt;
                表&lt;婊&lt;裱&lt;鳔&lt;憋&lt;鳖&lt;别&lt;蹩&lt;瘪&lt;宾&lt;彬&lt;傧&lt;斌&lt;滨&lt;
                缤&lt;槟&lt;镔&lt;濒&lt;豳&lt;摈&lt;殡&lt;膑&lt;髌&lt;鬓&lt;冫&lt;冰&lt;兵&lt;丙&lt;
                邴&lt;秉&lt;柄&lt;炳&lt;饼&lt;禀&lt;并&lt;病&lt;摒&lt;拨&lt;波&lt;玻&lt;剥&lt;钵&lt;
                饽&lt;啵&lt;脖&lt;菠&lt;播&lt;伯&lt;孛&lt;驳&lt;帛&lt;泊&lt;勃&lt;亳&lt;钹&lt;铂&lt;
                舶&lt;博&lt;渤&lt;鹁&lt;搏&lt;箔&lt;膊&lt;踣&lt;薄&lt;礴&lt;跛&lt;簸&lt;擘&lt;檗&lt;
                逋&lt;钸&lt;晡&lt;醭&lt;卜&lt;卟&lt;补&lt;哺&lt;捕&lt;不&lt;布&lt;步&lt;怖&lt;钚&lt;
                部&lt;埠&lt;瓿&lt;簿"</span>
                &nbsp;;</li>
            </ol>
            </div>
            <div><span style="color: #ff33ff;">
            <ol>
                <li>} </li>
                <li><strong><span style="color: #0000ff;">package</span>
                </strong>
                &nbsp;sorting; </li>
                <li><strong><span style="color: #0000ff;">import</span>
                </strong>
                &nbsp;java.util.*; </li>
                <li><strong><span style="color: #0000ff;">import</span>
                </strong>
                &nbsp;java.text.*; </li>
                <li><em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;*&nbsp;@author&nbsp;GaoJianMin</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;*</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;*/</span>
                </em>
                </li>
                <li><strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">class</span>
                </strong>
                &nbsp;ChineseGB2312Comparator&nbsp;<strong><span style="color: #0000ff;">implements</span>
                </strong>
                &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/util/Comparator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Comparator</span>
                </span>
                </a>
                </strong>
                &lt;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &gt;,&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/Comparable.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Comparable</span>
                </span>
                </a>
                </strong>
                &lt;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &gt;&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">private</span>
                </strong>
                &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/text/RuleBasedCollator.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">RuleBasedCollator</span>
                </span>
                </a>
                </strong>
                &nbsp;GB2312Collator&nbsp;= </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ChineseGB2312Collator.getFixedGB2312Collator(); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">private</span>
                </strong>
                &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;str1; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;str1</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;ChineseGB2312Comparator(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;str1)&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">this</span>
                </strong>
                .str1&nbsp;=&nbsp;str1; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;ChineseGB2312Comparator()&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">this</span>
                </strong>
                .str1=<span style="color: #ff33ff;">""</span>
                ; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;str1</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;str2</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;an&nbsp;integer&nbsp;indicatint&nbsp;the&nbsp;comparison&nbsp;result</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;java.util.Comparator#compare(Object,&nbsp;Object)</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">int</span>
                </strong>
                &nbsp;compare(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;str1,&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;str2)&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">return</span>
                </strong>
                &nbsp;GB2312Collator.compare(str1,&nbsp;str2); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<em><span style="color: #339900;">/**</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;str2</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;an&nbsp;integer&nbsp;indicatint&nbsp;the&nbsp;comparison&nbsp;result</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;@see&nbsp;java.lang.Comparable#compareTo(Object)</span>
                </em>
                </li>
                <li><em><span style="color: #339900;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span>
                </em>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">int</span>
                </strong>
                &nbsp;compareTo(<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;str2)&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">return</span>
                </strong>
                &nbsp;GB2312Collator.compare(str1,&nbsp;str2); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;} </li>
                <li>} </li>
                <li><br />
                <br />
                </li>
            </ol>
            <h3>测试代码及结果</h3>
            <br />
            代码：<br />
            <div class="codeStyle">
            <ol>
                <li><strong><span style="color: #0000ff;">import</span>
                </strong>
                &nbsp;java.util.*; </li>
                <li><strong><span style="color: #0000ff;">import</span>
                </strong>
                &nbsp;java.text.*; </li>
                <li><strong><span style="color: #0000ff;">public</span>
                </strong>
                &nbsp;<strong><span style="color: #0000ff;">class</span>
                </strong>
                &nbsp;Test </li>
                <li>{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;[]&nbsp;test&nbsp;=&nbsp;<strong><span style="color: #0000ff;">new</span>
                </strong>
                &nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                []&nbsp;{ </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"作业"</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"测试"</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"test"</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"我们"</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"。空"</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"镂空"</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"["</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"浏"</span>
                , </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff33ff;">"皙"</span>
                </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}; </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java.util.<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/util/Arrays.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">Arrays</span>
                </span>
                </a>
                </strong>
                .sort(test,&nbsp;<strong><span style="color: #0000ff;">new</span>
                </strong>
                &nbsp;ChineseGB2312Comparator()); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/System.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">System</span>
                </span>
                </a>
                </strong>
                .out.println(<span style="color: #ff33ff;">"============"</span>
                ); </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><span style="color: #0000ff;">for</span>
                </strong>
                (<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/String.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">String</span>
                </span>
                </a>
                </strong>
                &nbsp;key&nbsp;:&nbsp;test) </li>
                <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://vtyi.javaeye.com/source/jdk142/java/lang/System.java.html" target="_blank"><span class="classLink"><span style="text-decoration: underline;">System</span>
                </span>
                </a>
                </strong>
                .out.println(key); </li>
                <li>} </li>
            </ol>
            </div>
            <br />
            <br />
            ChineseGB2312Comparator&nbsp;类同时实现了&nbsp;Comparator,&nbsp;Comparable&nbsp;接口，这样以后能够使用&nbsp;compare,&nbsp;compareTo&nbsp;方法的时候都可以使用这个类。</span></div>
<img src ="http://www.blogjava.net/caizh2009/aggbug/340974.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-12-17 13:22 <a href="http://www.blogjava.net/caizh2009/archive/2010/12/17/340974.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Struts1和Struts2的区别和对比:</title><link>http://www.blogjava.net/caizh2009/archive/2010/12/14/340702.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 14 Dec 2010 13:55:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/12/14/340702.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/340702.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/12/14/340702.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/340702.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/340702.html</trackback:ping><description><![CDATA[<span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">Action 类:</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类编程而不是接口。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 2 Action类可以实现一个Action接口，也可实现其他接口，使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去 实现 常用的接口。Action接口不是必须的，任何有execute标识的POJO对象都可以用作Struts2的Action对象。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">线程模式:</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts1 Action是单例模式并且必须是线程安全的，因为仅有Action的一个实例来处理所有的请求。单例策略限制了Struts1 Action能作的事，并且要在开发时特别小心。Action资源必须是线程安全的或同步的。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts2 Action对象为每一个请求产生一个实例，因此没有线程安全问题。（实际上，servlet容器给每个请求产生许多可丢弃的对象，并且不会导致性能和垃圾回收问题）</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">Servlet 依赖:</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 2 Action不依赖于容器，允许Action脱离容器单独被测试。如果需要，Struts2 Action仍然可以访问初始的request和response。但是，其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">可测性:</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API（这使得测试要依赖于容器）。一个第三方扩展－－Struts TestCase－－提供了一套Struts1的模拟对象（来进行测试）。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 2 Action可以通过初始化、设置属性、调用方法来测试，&#8220;依赖注入&#8221;支持也使测试更容易。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">捕获输入:</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm，开发者经 常创建多余的类捕获输入。动态Bean（DynaBeans）可以作为创建传统ActionForm的选择，但是，开发者可能是在重新描述(创建)已经存 在的JavaBean（仍然会导致有冗余的javabean）。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 2直接使用Action属性作为输入属性，消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型，包括业务对象，能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入对象的引用。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">表达式语言：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts1 整合了JSTL，因此使用JSTL EL。这种EL有基本对象图遍历，但是对集合和索引属性的支持很弱。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts2可以使用JSTL，但是也支持一个更强大和灵活的表达式语言－－"Object Graph Notation Language" (OGNL).</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">绑定值到页面（view）:</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 1使用标准JSP机制把对象绑定到页面中来访问。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 2 使用 "ValueStack"技术，使taglib能够访问值而不需要把你的页面（view）和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面（view）。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">类型转换：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils进行类型转换。每个类一个转换器，对每一个实例来说是不可配置的。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">校验：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts 1支持在ActionForm的validate方法中手动校验，或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容，但不能校验子对象。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验，来支持chain校验子属性</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">Action执行的控制：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts1支持每一个模块有单独的Request Processors（生命周期），但是模块中的所有Action必须共享相同的生命周期。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&#8226; Struts2支持通过拦截器堆栈（Interceptor Stacks）为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。</span>
<img src ="http://www.blogjava.net/caizh2009/aggbug/340702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-12-14 21:55 <a href="http://www.blogjava.net/caizh2009/archive/2010/12/14/340702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javac -classpath的使用</title><link>http://www.blogjava.net/caizh2009/archive/2010/10/19/335634.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 19 Oct 2010 14:32:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/10/19/335634.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/335634.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/10/19/335634.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/335634.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/335634.html</trackback:ping><description><![CDATA[<span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">javac -classpath的使用：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">javac：如果当前你要编译的java文件中引用了其它的类(比如说：继承)，但该引用类的.class文件不在当前目录下，这种情况下就需要在javac命令后面加上-classpath参数，通过使用以下三种类型的方法 来指导编译器在编译的时候去指定的路径下查找引用类。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(1).绝对路径：javac -classpath c:\junit3.8.1\junit.jar&nbsp;&nbsp; Xxx.java</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(2).相对路径：javac -classpath ..\junit3.8.1\Junit.javr&nbsp; Xxx.java</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(3).系统变量：javac -classpath %CLASSPATH% Xxx.java (注意：%CLASSPATH%表示使用系统变量CLASSPATH的值进行查找，这里假设Junit.jar的路径就包含在CLASSPATH系统变量中)</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">javac 绝对路径的使用：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">javac：假设你要编译的类文件名叫：HelloWorld.java，其完全路径为：D:\java\HelloWorld.java。但你所在的当前目录是：C:\Documents and Settings\peng&gt;。如果想在这里执行编译，会有什么结果呢？</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(1).C:\Documents and Settings\peng&gt; javac HelloWorld.java 这时编译器会给出如下的错误提示信息：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">error: cannot read: HelloWorld.java</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">这是因为默认情况下javac是在当前目录下查找类文件，很明显这个路径不是我们存放类文件的地方，所以就会报错了</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(2).C:\Documents and Settings\peng&gt;javac D:\java\HelloWorld.java</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">这时编译成功。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">所以，只要你执行javac命令的目录不是类文件存放的目录，你就必须在javac命令中显式地指定类文件的路径。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">java -classpath的使用：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">java：假设我们的CLASSPATH设置为：D:\peng\java\pro ，在该目录下有三个文件：HelloWorld.java / HelloWorldExtendsTestCase / HelloWorldExtendsHelloWorld。这三个文件的类声明分别如下：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">HelloWorld.java ：public class HelloWorld</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">HelloWorldExtendsHelloWorld.java ：public class HelloWorldExtendsHelloWorld extends HelloWorld</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">HelloWorldExtendsTestCase.java：public class HelloWorldExtendsTestCase extends junit.framework.TestCase</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 假设我们已经按照上面关于javac -classpath和javac 绝对路径的使用，顺利地完成了三个文件地编译。现在我们在C:\Documents and Settings\peng&gt;目录下执行这三个.class文件</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(1).C:\Documents and Settings\peng&gt;java&nbsp; HelloWorld</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hello World</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">可以看到执行成功。为什么我们在 C:\Documents and Settings\peng&gt;执行命令，JVM能够找到D:\peng\java\pro\HelloWorld.class文件呢？这是因为我们配置了系统变量CLASSPATH，并且指向了目录：D:\peng\java\pro 。所以JVM会默认去该目录下加载类文件，而不需要指定.class文件的绝对路径了。</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(2).C:\Documents and Settings\peng&gt;java HelloWorldExtendsHelloWorld</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hello World</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">可以看到执行成功了。HelloWorldExtendsHelloWorld继承了HelloWorld类，所以在执行时JVM会先查找在CLASSPATH下是否存在一个HelloWorld.class文件，因为我们已经成功编译了HelloWorld 类了，所以可以成功执行HelloWorldExtendsHelloWorld.class</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(3).C:\Documents and Settings\peng&gt;java HelloWorldExtendsTestCase</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;&nbsp;&nbsp; Exception in thread "main" java.lang.NoClassDefFoundError: junit/framework/TestCase</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">可以看到程序抛出异常了，提示找不到junit.framework.TestCase文件。为什么同样在:\peng\java\pro 下，HelloWorldExtendsHelloWorld.class就可以成功执行，而这个就不行了呢？这是因为：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; junit.framework.TestCase.class文件并不存在于当前目录下，所以为了能够让程序成功运行，我们必须通过指定CLASSPATH的方式，让JVM可以找到junit.framework.TestCase这个类，如(4)：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(4). C:\Documents and Settings\peng&gt;java -classpath %CLASSPATH% HelloWorldExtendsTestCase</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hello World</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">总结：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(1).何时需要使用-classpath：当你要编译或执行的类引用了其它的类，但被引用类的.class文件不在当前目录下时，就需要通过-classpath来引入类</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">(2).何时需要指定路径：当你要编译的类所在的目录和你执行javac命令的目录不是同一个目录时，就需要指定源文件的路径(CLASSPATH是用来指定.class路径的，不是用来指定.java文件的路径的)</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">[转自：</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">http://blog.csdn.net/pengpenglin/</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">http://www.blogjava.net/pengpenglin/</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; "><br />
</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">]</span><span  style="font-family: Arial, sans-serif, Helvetica, Tahoma; font-size: 12px; line-height: 18px; ">&nbsp;</span>
<img src ="http://www.blogjava.net/caizh2009/aggbug/335634.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-10-19 22:32 <a href="http://www.blogjava.net/caizh2009/archive/2010/10/19/335634.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVAC 命令详解(http://www.cnblogs.com/jeffchen/archive/2008/01/16/1041783.html)</title><link>http://www.blogjava.net/caizh2009/archive/2010/10/19/335633.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 19 Oct 2010 14:31:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/10/19/335633.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/335633.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/10/19/335633.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/335633.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/335633.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis">
<h2 style="margin-top: 10px; font-size: 1.1em; ">结构</h2>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; "><strong>javac</strong> [ options ] [ sourcefiles ] [ @files ]
</pre>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">参数可按任意次序排列。</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; "><dl><dt><code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">options</font></code></dt><dd>命令行选项。</dd><dt><code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">sourcefiles</font></code></dt><dd>一个或多个要编译的源文件（例如 MyClass.java）。</dd><dt><code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">@files</font></code></dt><dd>一个或多个对源文件进行列表的文件。</dd></dl></blockquote></blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="description">
<h2 style="margin-top: 10px; font-size: 1.1em; ">说明</h2>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a></span><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; "><a name="synopsis">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">javac</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">有两种方法可将源代码文件名传递给 javac：</p>
<ul>
    <li style="font-size: 10pt; font-style: normal; ">如果源文件数量少，在命令行上列出文件名即可。</li>
    <li style="font-size: 10pt; font-style: normal; ">如果源文件数量多，则将源文件名列在一个文件中，名称间用空格或回车行来进行分隔。然后在 javac 命令行中使用该列表文件名，文件名前冠以 @ 字符。</li>
</ul>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">源代码文件名称必须含有&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">.java</font></code>&nbsp;后缀，类文件名称必须含有&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">.class</font></code>&nbsp;后缀，源文件和类文件都必须有识别该类的根名。例如，名为&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">MyClass</font></code>&nbsp;的类将写在名为&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">MyClass.java</font></code>的源文件中，并被编译为字节码类文件&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">MyClass.class</font></code>。</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">内部类定义产生附加的类文件。这些类文件的名称将内部类和外部类的名称结合在一起，例如<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">MyClass$MyInnerClass.class</font></code>。</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">应当将源文件安排在反映其包树结构的目录树中。例如，如果将所有的源文件放在 /workspace 中，那么&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">com.mysoft.mypack.MyClass</font></code>&nbsp;的代码应该在 \workspace\com\mysoft\mypack\MyClass.java 中。</p>
</a>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; "><a name="synopsis">缺省情况下，编译器将每个类文件与其源文件放在同一目录中。可用 -d 选项（请参阅后面的</a><a href="http://www.iplab.cs.tsukuba.ac.jp/~liuxj/jdk1.2/zh/docs/tooldocs/win32/javac.html#options" style="color: #0066ff; text-decoration: none; ">选项</a><a name="synopsis">）指定其它目标目录。</a></p>
<a name="synopsis">工具读取用 Java 编程语言编写的类和接口定义，并将它们编译成字节码类文件。</a></blockquote><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="searching">
<h2 style="margin-top: 10px; font-size: 1.1em; ">查找类型</h2>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">当编译源文件时，编译器常常需要它还没有识别出的类型的有关信息。对于源文件中使用、扩展或实现的每个类或接口，编译器都需要其类型信息。这包括在源文件中没有明确提及、但通过继承提供信息的类和接口。</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">例如，当扩展&nbsp;<strong>java.applet.Applet</strong>&nbsp;时还要用到&nbsp;<strong>Applet</strong>&nbsp;的祖先类：<strong>java.awt.Panel</strong>&nbsp;、<strong>java.awt.Container</strong>、&nbsp;<strong>java.awt.Component</strong>&nbsp;和&nbsp;<strong>java.awt.Object</strong>。</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">当编译器需要类型信息时，它将查找定义类型的源文件或类文件。编译器先在自举类及扩展类中查找，然后在用户类路径中查找。用户类路径通过两种途径来定义：通过设置&nbsp;<strong>CLASSPATH</strong>&nbsp;环境变量或使用&nbsp;<strong>-classpath</strong>&nbsp;命令行选项。（有关详细资料，请参阅设置类路径）。如果使用&nbsp;<strong>-sourcepath</strong>&nbsp;选项，则编译器在<strong>&nbsp;sourcepath</strong>&nbsp;指定的路径中查找源文件；否则，编译器将在用户类路径中查找类文件和源文件。可用<strong>-bootclasspath</strong>&nbsp;和&nbsp;<strong>-extdirs</strong>&nbsp;选项来指定不同的自举类或扩展类；参阅下面的联编选项。</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">成功的类型搜索可能生成类文件、源文件或两者兼有。以下是&nbsp;<strong>javac</strong>&nbsp;对各种情形所进行的处理：</p>
<ul>
    <li style="font-size: 10pt; font-style: normal; "><em>搜索结果只生成类文件而没有源文件：</em>&nbsp;<strong>javac</strong>&nbsp;使用类文件。</li>
    <li style="font-size: 10pt; font-style: normal; "><em>搜索结果只生成源文件而没有类文件：</em>&nbsp;<strong>javac</strong>&nbsp;编译源文件并使用由此生成的类文件。</li>
    <li style="font-size: 10pt; font-style: normal; "><em>搜索结果既生成源文件又生成类文件：<strong>&nbsp;</strong>确定类文件是否过时。若类文件已过时，则&nbsp;<strong>javac</strong>重新编译源文件并使用更新后的类文件。否则，&nbsp;<strong>javac</strong>&nbsp;直接使用类文件。
    <p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">缺省情况下，只要类文件比源文件旧，&nbsp;<strong>javac</strong>&nbsp;就认为它已过时。（&nbsp;<strong>-Xdepend</strong>&nbsp;选项指定相对来说较慢但却比较可靠的过程。）</p>
    </em>javac</li>
</ul>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">注意：&nbsp;<strong>javac</strong>&nbsp;可以隐式编译一些没有在命令行中提及的源文件。用&nbsp;<strong>-verbose</strong>&nbsp;选项可跟踪自动编译。</p>
</blockquote></a></span>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="commandlineargfile" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><a name="synopsis" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a></p>
<span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis">
<h2 style="margin-top: 10px; font-size: 1.1em; ">文件列表</h2>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">为缩短或简化&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">javac</font></code>&nbsp;命令，可以指定一个或多个每行含有一个文件名的文件。在命令行中，采用 '<tt><font face="新宋体">@</font></tt>' 字符加上文件名的方法将它指定为文件列表。当 javac 遇到以 `<tt><font face="新宋体">@</font></tt>' 字符开头的参数时，它对那个文件中所含文件名的操作跟对命令行中文件名的操作是一样的。这使得 Windows 命令行长度不再受限制。</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">例如，可以在名为&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">sourcefiles</font></code>&nbsp;的文件中列出所有源文件的名称。该文件可能形如：</p>
<pre style="margin-top: 0px; margin-bottom: 0px; ">     MyClass1.java
MyClass2.java
MyClass3.java
</pre>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">然后可用下列命令运行编译器：</p>
<pre style="margin-top: 0px; margin-bottom: 0px; ">     C:&gt; <strong>javac @sourcefiles</strong>
</pre>
</blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="options">
<h2 style="margin-top: 10px; font-size: 1.1em; ">选项</h2>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">编译器有一批标准选项，目前的开发环境支持这些标准选项，将来的版本也将支持它。还有一批附加的非标准选项是目前的虚拟机实现所特有的，将来可能要有变化。非标准选项以&nbsp;<strong>-X</strong>&nbsp;打头。</p>
</blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="standard">
<h2 style="margin-top: 10px; font-size: 1.1em; ">标准选项</h2>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; "><dl><dt><strong>-classpath</strong>&nbsp;<em>类路径</em></dt><dd>设置用户类路径，它将覆盖&nbsp;<strong>CLASSPATH</strong>&nbsp;环境变量中的用户类路径。若既未指定<strong>CLASSPATH</strong>&nbsp;又未指定&nbsp;<strong>-classpath</strong>，则用户类路径由当前目录构成。有关详细信息，请参阅设置类路径。
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">若未指定&nbsp;<strong>-sourcepath</strong>&nbsp;选项，则将在用户类路径中查找类文件和源文件。</p>
</dd><dt><strong>-d</strong>&nbsp;<em>目录</em></dt><dd>设置类文件的目标目录。如果某个类是一个包的组成部分，则&nbsp;<strong>javac</strong>&nbsp;将把该类文件放入反映包名的子目录中，必要时创建目录。例如，如果指定&nbsp;<strong>-d c:\myclasses</strong>&nbsp;并且该类名叫<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">com.mypackage.MyClass</font></code>，那么类文件就叫作<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">c:\myclasses\com\mypackage\MyClass.class</font></code>。
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">若未指定&nbsp;<strong>-d</strong>&nbsp;选项，则&nbsp;<strong>javac</strong>&nbsp;将把类文件放到与源文件相同的目录中。</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">注意：&nbsp;<strong>-d</strong>&nbsp;选项指定的目录不会被自动添加到用户类路径中。</p>
</dd><dt><strong>-deprecation</strong></dt><dd>显示每种不鼓励使用的成员或类的使用或覆盖的说明。没有给出&nbsp;<strong>-deprecation</strong>&nbsp;选项的话，&nbsp;<strong>javac</strong>&nbsp;将显示这类源文件的名称：这些源文件使用或覆盖不鼓励使用的成员或类。</dd><dt><strong>-encoding</strong></dt><dd>设置源文件编码名称，例如&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">EUCJIS/SJIS</font></code>。若未指定&nbsp;<strong>-encoding</strong>&nbsp;选项，则使用平台缺省的转换器。</dd><dt><strong>-g</strong></dt><dd>生成所有的调试信息，包括局部变量。缺省情况下，只生成行号和源文件信息。</dd><dt><strong>-g:none</strong></dt><dd>不生成任何调试信息。</dd><dt><strong>-g:</strong><em>{关键字列表}</em></dt><dd>只生成某些类型的调试信息，这些类型由逗号分隔的关键字列表所指定。有效的关键字有：<dl><dt><strong>source</strong></dt><dd>源文件调试信息</dd><dt><strong>lines</strong></dt><dd>行号调试信息</dd><dt><strong>vars</strong></dt><dd>局部变量调试信息</dd></dl></dd><dt><strong>-nowarn</strong></dt><dd>禁用警告信息。</dd><dt><strong>-O</strong></dt><dd>优化代码以缩短执行时间。使用&nbsp;<strong>-O</strong>&nbsp;选项可能使编译速度下降、生成更大的类文件并使程序难以调试。
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">在 JDK 1.2 以前的版本中，javac 的&nbsp;<strong>-g</strong>&nbsp;选项和&nbsp;<strong>-O</strong>&nbsp;选项不能一起使用。在 JDK 1.2 中，可以将&nbsp;<strong>-g</strong>&nbsp;和&nbsp;<strong>-O</strong>&nbsp;选项结合起来，但可能会得到意想不到的结果，如丢失变量或重新定位代码或丢失代码。<strong>-O</strong>&nbsp;选项不再自动打开&nbsp;<strong>-depend</strong>&nbsp;或关闭&nbsp;<strong>-g</strong>&nbsp;选项。同样，&nbsp;<strong>-O</strong>&nbsp;选项也不再允许进行跨类内嵌。</p>
</dd><dt><strong>-sourcepath</strong>&nbsp;<em>源路径</em></dt><dd>指定用以查找类或接口定义的源代码路径。与用户类路径一样，源路径项用分号 (<strong>;</strong>) 进行分隔，它们可以是目录、JAR 归档文件或 ZIP 归档文件。如果使用包，那么目录或归档文件中的本地路径名必须反映包名。
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">注意：通过类路径查找的类，如果找到了其源文件，则可能会自动被重新编译。</p>
</dd><dt><strong>-verbose</strong></dt><dd>冗长输出。它包括了每个所加载的类和每个所编译的源文件的有关信息。</dd></dl></blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="crosscomp-options">
<h3 style="font-size: 10pt; border-bottom-width: 0px; border-bottom-style: dotted; border-bottom-color: #d6d6d6; color: #000000; background-color: transparent; ">联编选项</h3>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">缺省情况下，类是根据与&nbsp;<strong>javac</strong>&nbsp;一起发行的 JDK 自举类和扩展类来编译。但&nbsp;<strong>javac</strong>&nbsp;也支持<em>联编</em>，在联编中，类是根据其它 Java平台实现的自举类和扩展类来进行编译的。联编时，&nbsp;<strong>-bootclasspath</strong>&nbsp;和&nbsp;<strong>-extdirs</strong>&nbsp;的使用很重要；请参阅下面的联编程序示例。</p>
<dl><dt><strong>-target</strong>&nbsp;<em>版本</em></dt><dd>生成将在指定版本的虚拟机上运行的类文件。缺省情况下生成与 1.1 和 1.2 版本的虚拟机都兼容的类文件。JDK 1.2 中的&nbsp;<strong>javac</strong>&nbsp;所支持的版本有：<dl><dt><strong>1.1</strong></dt><dd>保证所产生的类文件与 1.1 和 1.2 版的虚拟机兼容。这是缺省状态。</dd><dt><strong>1.2</strong></dt><dd>生成的类文件可在 1.2 版的虚拟机上运行，但不能在 1.1 版的虚拟机上运行。</dd></dl></dd><dt><strong>-bootclasspath</strong>&nbsp;<em>自举类路径</em></dt><dd>根据指定的自举类集进行联编。和用户类路径一样，自举类路径项用分号 (<strong>;</strong>) 进行分隔，它们可以是目录、JAR 归档文件或 ZIP 归档文件。</dd><dt><strong>-extdirs</strong>&nbsp;<em>目录</em></dt><dd>根据指定的扩展目录进行联编。<em>目录</em>是以分号分隔的目录列表。在指定目录的每个 JAR 归档文件中查找类文件。</dd></dl></blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="nonstandard">
<h3 style="font-size: 10pt; border-bottom-width: 0px; border-bottom-style: dotted; border-bottom-color: #d6d6d6; color: #000000; background-color: transparent; ">非标准选项</h3>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; "><dl><dt><strong>-X</strong></dt><dd>显示非标准选项的有关信息并退出。</dd><dt><strong>-Xdepend</strong></dt><dd>递归地搜索所有可获得的类，以寻找要重编译的最新源文件。该选项将更可靠地查找需要编译的类，但会使编译进程的速度大为减慢。</dd><dt><strong>-Xstdout</strong></dt><dd>将编译器信息送到<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">System.out</font></code>&nbsp;中。缺省情况下，编译器信息送到&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">System.err</font></code>&nbsp;中。</dd><dt><strong>-Xverbosepath</strong></dt><dd>说明如何搜索路径和标准扩展以查找源文件和类文件。</dd><dt><strong>-J</strong><em>选项</em></dt><dd>将<em>选项</em>传给&nbsp;<strong>javac</strong>&nbsp;调用的&nbsp;<strong>java</strong>&nbsp;启动器。例如，&nbsp;<strong>-J-Xms48m</strong>&nbsp;将启动内存设为 48 兆字节。虽然它不以&nbsp;<strong>-X</strong>&nbsp;开头，但它并不是&nbsp;<strong>javac</strong>&nbsp;的&#8216;标准选项&#8217;。用<strong>&nbsp;-J</strong>&nbsp;将选项传给执行用 Java 编写的应用程序的虚拟机是一种公共约定。
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">注意：&nbsp;<strong>CLASSPATH</strong>&nbsp;、&nbsp;<strong>-classpath</strong>&nbsp;、&nbsp;<strong>-bootclasspath</strong>&nbsp;和&nbsp;<strong>-extdirs</strong>&nbsp;并&nbsp;<em>不</em>&nbsp;指定用于运行&nbsp;<strong>javac</strong>&nbsp;的类。如此滥用编译器的实现通常没有任何意义而且总是很危险的。如果确实需要这样做，可用&nbsp;<strong>-J</strong>&nbsp;选项将选项传给基本的&nbsp;<strong>java</strong>&nbsp;启动器。</p>
</dd></dl></blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="examples">
<h2 style="margin-top: 10px; font-size: 1.1em; ">程序示例</h2>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="simpleexamples">
<h3 style="font-size: 10pt; border-bottom-width: 0px; border-bottom-style: dotted; border-bottom-color: #d6d6d6; color: #000000; background-color: transparent; ">编译简单程序</h3>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">一个源文件&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">Hello.java</font></code>&nbsp;，它定义了一个名叫&nbsp;<strong>greetings.Hello</strong>&nbsp;的类。<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">greetings</font></code>&nbsp;目录是源文件和类文件两者的包目录，且它不是当前目录。这让我们可以使用缺省的用户类路径。它也使我们没必要用&nbsp;<strong>-d</strong>&nbsp;选项指定单独的目标目录。</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt; <strong>dir</strong>
greetings/
C:&gt; <strong>dir greetings</strong>
Hello.java
C:&gt; <strong>cat greetings\Hello.java</strong>
package greetings;
public class Hello {
public static void main(String[] args) {
for (int i=0; i &lt; args.length; i++) {
System.out.println("Hello " + args[i]);
}
}
}
C:&gt; <strong>javac greetings\Hello.java</strong>
C:&gt; <strong>dir greetings</strong>
Hello.class   Hello.java
C:&gt; <strong>java greetings.Hello World Universe Everyone</strong>
Hello World
Hello Universe
Hello Everyone
</pre>
</blockquote></blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="multiple-example">
<h3 style="font-size: 10pt; border-bottom-width: 0px; border-bottom-style: dotted; border-bottom-color: #d6d6d6; color: #000000; background-color: transparent; ">编译多个源文件</h3>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">该示例编译&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">greetings</font></code>&nbsp;包中的所有源文件。</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt; <strong>dir</strong>
greetings\
C:&gt; <strong>dir greetings</strong>
Aloha.java         GutenTag.java      Hello.java         Hi.java
C:&gt; <strong>javac greetings\*.java</strong>
C:&gt; <strong>dir greetings</strong>
Aloha.class         GutenTag.class      Hello.class         Hi.class
Aloha.java          GutenTag.java       Hello.java          Hi.java
</pre>
</blockquote></blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="userclasspath">
<h3 style="font-size: 10pt; border-bottom-width: 0px; border-bottom-style: dotted; border-bottom-color: #d6d6d6; color: #000000; background-color: transparent; ">指定用户类路径</h3>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">对前面示例中的某个源文件进行更改后，重新编译它：</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt; <strong>cd</strong>
\examples
C:&gt; <strong>javac greetings\Hi.java</strong>
</pre>
</blockquote>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">由于&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">greetings.Hi</font></code>&nbsp;引用了&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">greetings</font></code>&nbsp;包中其它的类，编译器需要找到这些其它的类。上面的示例能运行是因为缺省的用户类路径刚好是含有包目录的目录。但是，假设我们想重新编译该文件并且不关心我们在哪个目录中的话， 我们需要将&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">\examples</font></code>&nbsp;添加到用户类路径中。可以通过设置<strong>CLASSPATH</strong>&nbsp;达到此目的，但这里我们将使用&nbsp;<strong>-classpath</strong>&nbsp;选项来完成。</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt;<strong>javac -classpath \examples \examples\greetings\Hi.java</strong>
</pre>
</blockquote>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">如果再次将&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">greetings.Hi</font></code>&nbsp;改为使用标题实用程序，该实用程序也需要通过用户类路径来进行访问：</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt;<strong>javac -classpath \examples:\lib\Banners.jar \
\examples\greetings\Hi.java</strong>
</pre>
</blockquote>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">要执行&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">greetings</font></code>&nbsp;中的类，需要访问&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">greetings</font></code>&nbsp;和它所使用的类。</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt;<strong>java -classpath \examples:\lib\Banners.jar greetings.Hi</strong>
</pre>
</blockquote></blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="separating">
<h3 style="font-size: 10pt; border-bottom-width: 0px; border-bottom-style: dotted; border-bottom-color: #d6d6d6; color: #000000; background-color: transparent; ">将源文件和类文件分开</h3>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">将源文件和类文件置于不同的目录下经常是很有意义的，特别是在大型的项目中。我们用&nbsp;<strong>-d</strong>&nbsp;选项来指明单独的类文件目标位置。由于源文件不在用户类路径中，所以用&nbsp;<strong>-sourcepath</strong>&nbsp;选项来协助编译器查找它们。</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt; <strong>dir</strong>
classes\  lib\      src\
C:&gt; <strong>dir src</strong>
farewells\
C:&gt; <strong>dir src\farewells</strong>
Base.java      GoodBye.java
C:&gt; <strong>dir lib</strong>
Banners.jar
C:&gt; <strong>dir classes</strong>
C:&gt; <strong>javac -sourcepath src -classpath classes:lib\Banners.jar \
src\farewells\GoodBye.java -d classes</strong>
C:&gt; <strong>dir classes</strong>
farewells\
C:&gt; <strong>dir classes\farewells</strong>
Base.class      GoodBye.class
</pre>
</blockquote>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">注意：编译器也编译了&nbsp;<code style="font-family: 'Courier New', Courier, monospace; font-size: 10pt; "><font face="新宋体">src\farewells\Base.java</font></code>，虽然我们没有在命令行中指定它。要跟踪自动编译，可使用&nbsp;<strong>-verbose</strong>&nbsp;选项。</p>
</blockquote></a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="crosscomp-example">
<h3 style="font-size: 10pt; border-bottom-width: 0px; border-bottom-style: dotted; border-bottom-color: #d6d6d6; color: #000000; background-color: transparent; ">联编程序示例</h3>
</a></span><span style="color: #333333; font-family: Verdana, Arial, sans-serif, 'Lucida Grande'; font-size: 13px; line-height: 18px; "><a name="synopsis"><blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">这里我们用 JDK 1.2 的&nbsp;<strong>javac</strong>&nbsp;来编译将在 1.1 版的虚拟机上运行的代码。</p>
<blockquote style="background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: transparent; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #f4f4f4; border-right-color: #f4f4f4; border-bottom-color: #f4f4f4; border-left-color: #f4f4f4; color: #5b5b5b; margin-left: 25px; padding-left: 11px; padding-right: 11px; padding-top: 0px; padding-bottom: 0px; margin-top: 10px; margin-bottom: 10px; font-style: normal; font-size: 10pt; line-height: 19px; background-position: initial initial; background-repeat: initial initial; ">
<pre style="margin-top: 0px; margin-bottom: 0px; ">C:&gt; <strong>javac -target 1.1 -bootclasspath jdk1.1.7\lib\classes.zip \
-extdirs "" OldCode.java</strong>
</pre>
</blockquote><strong>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">-target 1.1</p>
<p style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px; ">JDK 1.2&nbsp;<strong>javac</strong>&nbsp;在缺省状态下也将根据 1.2 版的自举类来进行编译，因此我们需要告诉<strong>javac</strong>&nbsp;让它根据 JDK 1.1 自举类来进行编译。可用&nbsp;<strong>-bootclasspath</strong>&nbsp;和&nbsp;<strong>-extdirs</strong>&nbsp;选项来达到此目的。不这样做的话，可能会使编译器根据 1.2 版的 API 来进行编译。由于 1.1 版的虚拟机上可能没有该 1.2 版的 API，因此运行时将出错。</p>
</strong>选项可确保生成的类文件与 1.1 版的虚拟机兼容。在 JDK1.2 中， 缺省情况下&nbsp;<strong>javac</strong>&nbsp;编译生成的文件是与 1.1 版的虚拟机兼容的，因此并非严格地需要该选项。然而，由于别的编译器可能采用其它的缺省设置，所以提供这一选项将不失为是个好习惯。</blockquote></a></span>
<img src ="http://www.blogjava.net/caizh2009/aggbug/335633.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-10-19 22:31 <a href="http://www.blogjava.net/caizh2009/archive/2010/10/19/335633.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java虚拟机参数详解</title><link>http://www.blogjava.net/caizh2009/archive/2010/10/19/335589.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 19 Oct 2010 09:07:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/10/19/335589.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/335589.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/10/19/335589.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/335589.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/335589.html</trackback:ping><description><![CDATA[<p>
<p style="font-family: verdana; font-size: 12px; line-height: 20px; color: #666666; ">下面的讨论以Windows平台的Sun MicroSystem实现的java5虚拟机为蓝本，其他操作系统或其他公司实现的虚拟机参数会有部分不同，但大部分含义都和Windows上的类似。Java5与以前版本相比，虚拟机参数大部分保持了向前兼容，同时也增加了一些新的参数，本文将对这些参数的作用作详细描述，使虚拟机能更符合运行环境的需要，获得更好的性能和稳定性。</p>
<p style="font-family: verdana; font-size: 12px; line-height: 20px; color: #666666; ">Java在运行已编译完成的类时，是通过java虚拟机来装载和执行的，java虚拟机通过操作系统命令JAVA_HOME\bin\java &#8211;option 来启动，-option为虚拟机参数，JAVA_HOME为JDK安装路径，通过这些参数可对虚拟机的运行状态进行调整，掌握参数的含义可对虚拟机的运行模式有更深入理解。<br />
<br />
<br />
虚拟机参数分为基本和扩展两类，在命令行中输入JAVA_HOME\bin\java 就可得到基本参数列表，<br />
<br />
在命令行输入JAVA_HOME\bin\java &#8211;X 就可得到扩展参数列表。<br />
<br />
基本参数说明：<br />
<br />
<br />
-client，-server<br />
<br />
这两个参数用于设置虚拟机使用何种运行模式，client模式启动比较快，但运行时性能和内存管理效率不如server模式，通常用于客户端应用程序。相反，server模式启动比client慢，但可获得更高的运行性能。<br />
<br />
在windows上，缺省的虚拟机类型为client模式，如果要使用server模式，就需要在启动虚拟机时加-server参数，以获得更高性能，对服务器端应用，推荐采用server模式，尤其是多个CPU的系统。在Linux，Solaris上缺省采用server模式。<br />
<br />
<br />
-hotspot<br />
<br />
含义与client相同，jdk1.4以前使用的参数，jdk1.4开始不再使用，代之以client。<br />
<br />
<br />
-classpath,-cp<br />
<br />
虚拟机在运行一个类时，需要将其装入内存，虚拟机搜索类的方式和顺序如下：<br />
<br />
Bootstrap classes，Extension classes，User classes。<br />
<br />
Bootstrap 中的路径是虚拟机自带的jar或zip文件，虚拟机首先搜索这些包文件，用System.getProperty("sun.boot.class.path")可得到虚拟机搜索的包名。<br />
<br />
<br />
Extension是位于jre\lib\ext目录下的jar文件，虚拟机在搜索完Bootstrap后就搜索该目录下的jar文件。用System. getProperty("java.ext.dirs&#8221;)可得到虚拟机使用Extension搜索路径。<br />
<br />
User classes搜索顺序为当前目录、环境变量 CLASSPATH、-classpath。<br />
<br />
-classpath告知虚拟机搜索目录名、jar文档名、zip文档名，之间用分号;分隔。<br />
<br />
例如当你自己开发了公共类并包装成一个common.jar包，在使用common.jar中的类时，就需要用-classpath common.jar 告诉虚拟机从common.jar中查找该类，否则虚拟机就会抛出java.lang.NoClassDefFoundError异常，表明未找到类定义。<br />
<br />
在运行时可用System.getProperty(&#8220;java.class.path&#8221;)得到虚拟机查找类的路径。<br />
<br />
<br />
使用-classpath后虚拟机将不再使用CLASSPATH中的类搜索路径，如果-classpath和CLASSPATH都没有设置，则虚拟机使用当前路径(.)作为类搜索路径。<br />
<br />
<br />
推荐使用-classpath来定义虚拟机要搜索的类路径，而不要使用环境变量CLASSPATH的搜索路径，以减少多个项目同时使用CLASSPATH时存在的潜在冲突。例如应用1要使用a1.0.jar中的类G，应用2要使用a2.0.jar中的类G,a2.0.jar是a1.0.jar的升级包，当a1.0.jar，a2.0.jar都在CLASSPATH中，虚拟机搜索到第一个包中的类G时就停止搜索，如果应用1应用2的虚拟机都从CLASSPATH中搜索，就会有一个应用得不到正确版本的类G。<br />
<br />
<br />
<br />
-D&lt;propertyName&gt;=value<br />
<br />
在虚拟机的系统属性中设置属性名/值对，运行在此虚拟机之上的应用程序可用System.getProperty(&#8220;propertyName&#8221;)得到value的值。<br />
<br />
如果value中有空格，则需要用双引号将该值括起来，如-Dname=&#8221;space string&#8221;。<br />
<br />
该参数通常用于设置系统级全局变量值，如配置文件路径，应为该属性在程序中任何地方都可访问。<br />
<br />
<br />
-verbose[:class|gc|jni]<br />
<br />
在输出设备上显示虚拟机运行信息。<br />
<br />
verbose和verbose:class含义相同，输出虚拟机装入的类的信息，显示的信息格式如下：<br />
<br />
[Loaded java.io.FilePermission$1 from shared objects file]<br />
<br />
当虚拟机报告类找不到或类冲突时可用此参数来诊断来查看虚拟机从装入类的情况。<br />
<br />
<br />
-verbose:gc在虚拟机发生内存回收时在输出设备显示信息，格式如下：<br />
<br />
[Full GC 268K-&gt;168K(1984K), 0.0187390 secs]<br />
<br />
该参数用来监视虚拟机内存回收的情况。<br />
<br />
<br />
-verbose:jni在虚拟机调用native方法时输出设备显示信息，格式如下：<br />
<br />
[Dynamic-linking native method HelloNative.sum ... JNI]<br />
<br />
该参数用来监视虚拟机调用本地方法的情况，在发生jni错误时可为诊断提供便利。<br />
<br />
<br />
<br />
-version<br />
<br />
显示可运行的虚拟机版本信息然后退出。一台机器上装有不同版本的JDK时<br />
<br />
<br />
<br />
-showversion<br />
<br />
显示版本信息以及帮助信息。<br />
<br />
<br />
<br />
-ea[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />
<br />
-enableassertions[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />
<br />
从JDK1.4开始，java可支持断言机制，用于诊断运行时问题。通常在测试阶段使断言有效，在正式运行时不需要运行断言。断言后的表达式的值是一个逻辑值，为true时断言不运行，为false时断言运行，抛出java.lang.AssertionError错误。<br />
<br />
上述参数就用来设置虚拟机是否启动断言机制，缺省时虚拟机关闭断言机制，用-ea可打开断言机制，不加&lt;packagename&gt;和classname时运行所有包和类中的断言，如果希望只运行某些包或类中的断言，可将包名或类名加到-ea之后。例如要启动包com.foo.util中的断言，可用命令 &#8211;ea:com.foo.util 。<br />
<br />
<br />
-da[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />
<br />
-disableassertions[:&lt;packagename&gt;...|:&lt;classname&gt;]<br />
<br />
用来设置虚拟机关闭断言处理，packagename和classname的使用方法和-ea相同。<br />
<br />
<br />
<br />
-esa | -enablesystemassertions<br />
<br />
设置虚拟机显示系统类的断言。<br />
<br />
<br />
-dsa | -disablesystemassertions<br />
<br />
设置虚拟机关闭系统类的断言。<br />
<br />
<br />
-agentlib:&lt;libname&gt;[=&lt;options&gt;]<br />
<br />
该参数是JDK5新引入的，用于虚拟机装载本地代理库。<br />
<br />
Libname为本地代理库文件名，虚拟机的搜索路径为环境变量PATH中的路径，options为传给本地库启动时的参数，多个参数之间用逗号分隔。在Windows平台上虚拟机搜索本地库名为libname.dll的文件，在Unix上虚拟机搜索本地库名为libname.so的文件，搜索路径环境变量在不同系统上有所不同，Linux、SunOS、IRIX上为LD_LIBRARY_PATH，AIX上为LIBPATH，HP-UX上为SHLIB_PATH。<br />
<br />
<br />
例如可使用-agentlib:hprof来获取虚拟机的运行情况，包括CPU、内存、线程等的运行数据，并可输出到指定文件中，可用-agentlib:hprof=help来得到使用帮助列表。在jre\bin目录下可发现hprof.dll文件。<br />
<br />
<br />
-agentpath:&lt;pathname&gt;[=&lt;options&gt;]<br />
<br />
设置虚拟机按全路径装载本地库，不再搜索PATH中的路径。其他功能和agentlib相同。<br />
<br />
<br />
<br />
-javaagent:&lt;jarpath&gt;[=&lt;options&gt;]<br />
<br />
虚拟机启动时装入java语言设备代理。Jarpath文件中的mainfest文件必须有Agent-Class属性。代理类要实现public static void premain(String agentArgs, Instrumentation inst)方法。当虚拟机初始化时，将按代理类的说明顺序调用premain方法。<br />
<br />
参见：java.lang.instrument<br />
<br />
<br />
<br />
扩展参数说明<br />
<br />
<br />
-Xmixed<br />
<br />
设置-client模式虚拟机对使用频率高的方式进行Just-In-Time编译和执行，对其他方法使用解释方式执行。该方式是虚拟机缺省模式。<br />
<br />
<br />
<br />
-Xint<br />
<br />
设置-client模式下运行的虚拟机以解释方式执行类的字节码，不将字节码编译为本机码。<br />
<br />
<br />
-Xbootclasspath:path<br />
<br />
-Xbootclasspath/a:path<br />
<br />
-Xbootclasspath/p:path<br />
<br />
改变虚拟机装载缺省系统运行包rt.jar而从-Xbootclasspath中设定的搜索路径中装载系统运行类。除非你自己能写一个运行时，否则不会用到该参数。<br />
<br />
/a:将在缺省搜索路径后加上path 中的搜索路径。<br />
<br />
/p:在缺省搜索路径前先搜索path中的搜索路径。<br />
<br />
<br />
-Xnoclassgc<br />
<br />
关闭虚拟机对class的垃圾回收功能。<br />
<br />
<br />
-Xincgc<br />
<br />
启动增量垃圾收集器，缺省是关闭的。增量垃圾收集器能减少偶然发生的长时间的垃圾回收造成的暂停时间。但增量垃圾收集器和应用程序并发执行，因此会占用部分CPU在应用程序上的功能。<br />
<br />
<br />
-Xloggc:&lt;file&gt;<br />
<br />
将虚拟机每次垃圾回收的信息写到日志文件中，文件名由file指定，文件格式是平文件，内容和-verbose:gc输出内容相同。<br />
<br />
<br />
<br />
<br />
-Xbatch<br />
<br />
虚拟机的缺省运行方式是在后台编译类代码，然后在前台执行代码，使用-Xbatch参数将关闭虚拟机后台编译，在前台编译完成后再执行。<br />
<br />
<br />
<br />
-Xms&lt;size&gt;<br />
<br />
设置虚拟机可用内存堆的初始大小，缺省单位为字节，该大小为1024的整数倍并且要大于1MB，可用k(K)或m(M)为单位来设置较大的内存数。初始堆大小为2MB。<br />
<br />
例如：-Xms6400K，-Xms256M<br />
<br />
<br />
<br />
-Xmx&lt;size&gt;<br />
<br />
设置虚拟机内存堆的最大可用大小，缺省单位为字节。该值必须为1024整数倍，并且要大于2MB。可用k(K)或m(M)为单位来设置较大的内存数。缺省堆最大值为64MB。<br />
<br />
例如：-Xmx81920K，-Xmx80M<br />
<br />
当应用程序申请了大内存运行时虚拟机抛出java.lang.OutOfMemoryError: Java heap space错误，就需要使用-Xmx设置较大的可用内存堆。<br />
<br />
<br />
-Xss&lt;size&gt;<br />
<br />
设置线程栈的大小，缺省单位为字节。与-Xmx类似，也可用K或M来设置较大的值。通常操作系统分配给线程栈的缺省大小为1MB。<br />
<br />
另外也可在java中创建线程对象时设置栈的大小，构造函数原型为Thread(ThreadGroup group, Runnable target, String name, long stackSize)。<br />
<br />
<br />
<br />
-Xprof<br />
<br />
输出CPU运行时的诊断信息。<br />
<br />
<br />
<br />
-Xfuture<br />
<br />
对类文件进行严格格式检查，以保证类代码符合类代码规范。为保持向后兼容，虚拟机缺省不进行严格的格式检查。<br />
<br />
<br />
-Xrs<br />
<br />
减少虚拟机中操作系统的信号（singals）的使用。该参数通常用在虚拟机以后台服务方式运行时使用（如Servlet）。<br />
<br />
<br />
<br />
-Xcheck:jni<br />
<br />
调用JNI函数时进行附加的检查，特别地虚拟机将校验传递给JNI函数参数的合法性，在本地代码中遇到非法数据时，虚拟机将报一个致命错误而终止。使用该参数后将造成性能下降。</p>
</p>
<img src ="http://www.blogjava.net/caizh2009/aggbug/335589.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-10-19 17:07 <a href="http://www.blogjava.net/caizh2009/archive/2010/10/19/335589.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>web.xml中获取全局参数</title><link>http://www.blogjava.net/caizh2009/archive/2010/09/30/333564.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 30 Sep 2010 08:38:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/09/30/333564.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/333564.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/09/30/333564.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/333564.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/333564.html</trackback:ping><description><![CDATA[http://blog.csdn.net/wjp553650958/archive/2009/08/30/4499540.aspx<br />
<span style="font-family: andale mono,times;"><span style="font-size: medium;">读取容器配置参数---context-param和init-param区别</span></span>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">web.xml里面可以定义两种参数：<br />
(1)application范围内的参数，存放在servletcontext中，在web.xml中配置如下：&nbsp; &lt;context-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;context/param&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;avalible during application&lt;/param-value&gt;</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;name1&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;value1&lt;/param-value&gt;<br />
&nbsp; &lt;/context-param&gt;</span></span></p>
<p><br />
<span style="font-family: andale mono,times;"><span style="font-size: medium;">(2)servlet范围内的参数，只能在servlet的init()方法中取得，在web.xml中配置如下：</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&nbsp;&lt;servlet&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-name&gt;MainServlet&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;servlet-class&gt;com.wes.controller.MainServlet&lt;/servlet-class&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;param1&lt;/param-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;avalible in servlet init()&lt;/param-value&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;load-on-startup&gt;0&lt;/load-on-startup&gt;<br />
&nbsp;&lt;/servlet&gt;</span></span></p>
<p><br />
<span style="font-family: andale mono,times;"><span style="font-size: medium;">在servlet中可以通过代码分别取用：</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">package com.wes.controller;</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">import javax.servlet.ServletException;<br />
import javax.servlet.http.HttpServlet;</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">public class MainServlet extends HttpServlet ...{</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&nbsp;&nbsp;&nbsp; public MainServlet() ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super();<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void init() throws ServletException ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("下面的两个参数param1是在servlet中存放的");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(this.getInitParameter("param1"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("下面的参数是存放在servletcontext中的");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(getServletContext().getInitParameter("context/param"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">第
一种参数在servlet里面可以通过getServletContext().getInitParameter("context/param")得
到?(在servlet的init()方法中通过this.getInitParameter("param1")取得)</span></span></p>
<p><br />
<span style="font-family: andale mono,times;"><span style="font-size: medium;">第二种参数只能在servlet的init()方法中通过this.getInitParameter("param1")取得</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">---------------------------------------------------------------------</span></span></p>
<p><br />
<span style="font-family: andale mono,times;"><span style="font-size: medium;">ServletContextListener实现读取web.xml中context-param信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2009年03月27日 星期五 22:37<br />
&nbsp; 用部署文件来存储配置参数在Java中是一种很流行的做法。</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">配置参数一般存放在context-param元素中，每一个context-param元素代表了一个键值对。</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">我
们可以通过实现ServletContextListener接口读取该键值对中的值，在web应用程序初始化的时候，调用
ServletContextListener的contextInitialized()方法，所以我们我们可以重写该方法，实现读取操作。可以这样实
现：</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">public class AppListener implements ServletContextListener {</span></span></p>
<p><br />
<span style="font-family: andale mono,times;"><span style="font-size: medium;">public void contextInitialized(ServletContextEvent sce) {<br />
&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyConfig config = new MyConfig();//存放配置信息，用Map实现<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enumeration parameters =&nbsp; sce.getServletContext().getInitParameterNames();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(parameters.hasMoreElements()){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String name =&nbsp; (String) parameters.nextElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; config.addKeyTValue(name, sce.getServletContext().getInitParameter(name));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; </span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //相应的键值对存到map中<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; config.addKeyValue(parameter, sc.getInitParameter(parameter)); <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; } catch(Exception e) {<br />
&nbsp;&nbsp;&nbsp; System.out.println("com.shou error:" + e.getMessage());<br />
&nbsp;&nbsp; }<br />
}</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">public void contextDestroyed(ServletContextEvent arg0) {</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">}<br />
}</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&nbsp;MyConfig类：(Singleton Config)<br />
package com.myapp;</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">import java.util.Collection;<br />
import java.util.HashMap;<br />
import java.util.Map;<br />
import java.util.Set;</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">/**<br />
&nbsp;*<br />
&nbsp;* @author Administrator<br />
&nbsp;*/</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">public class MyConfig{<br />
&nbsp;&nbsp;&nbsp; public static MyConfig myconfig;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static HashMap config = new HashMap();</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&nbsp;&nbsp;&nbsp; public static HashMap getConfig() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return config;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static MyConfig getInstance(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(myconfig==null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myconfig = new MyConfig();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return myconfig;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public static void setConfig(HashMap config) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyConfig.config = config;<br />
&nbsp;&nbsp;&nbsp; }</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&nbsp;&nbsp;&nbsp;&nbsp; public HashMap addKeyTValue(String name,String value){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.config.put(name, value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.config;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">接着，必须在web.xml中配置相应的监听类，才能在初始化的时候，自动调用该方法。如：</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">&lt;listener&gt;<br />
&lt;listener-class&gt;com.myapp.MyListener&lt;/listener-class&gt;<br />
&lt;/listener&gt;</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">这样就可以在任何一个JSP页面，通过EL表达式或JSTL读到context-param中的内容。</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">有的网友说在web.xml内定义&lt;listener&gt;元素时得注意下列两点：<br />
&lt;listener&gt;元素必须出现在任何Context起始参数（由&lt;context-param&gt;元素所定义）之后。<br />
&lt;listener&gt;元素必须出现在任何Servlet实体（由&lt;servlet&gt;元素所定义）之前。</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">但是我在TOMCAT5.5 +　J2EE 5下配置web.xml并没有按照上述的严格限制也能成功读取信息。</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">难道是版本的问题吗。</span></span></p>
<p><span style="font-family: andale mono,times;"><span style="font-size: medium;">在Struts 1.X下，通过一个自定义的Singleton Config类，可以让web.xml中的配置参数在整个应用程序里都能被共享。</span></span></p>
<br />
<img src ="http://www.blogjava.net/caizh2009/aggbug/333564.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-09-30 16:38 <a href="http://www.blogjava.net/caizh2009/archive/2010/09/30/333564.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat中web.xml文件的详细说明 </title><link>http://www.blogjava.net/caizh2009/archive/2010/09/30/333555.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 30 Sep 2010 08:06:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/09/30/333555.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/333555.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/09/30/333555.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/333555.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/333555.html</trackback:ping><description><![CDATA[<p>Tomcat中web.xml文件的详细说明 <br />
&lt;?xml version="1.0" encoding="GB2312"?&gt; &lt;!-- <br />
Web.xml依次定议了如下元素： <br />
&lt;web-app&gt; <br />
&lt;display-name&gt;&lt;/display-name&gt; 定义了WEB应用的名字 <br />
&lt;description&gt;&lt;/description&gt; 声明WEB应用的描述信息 <br />
&lt;filter&gt;&lt;/filter&gt; <br />
&lt;filter-mapping&gt;&lt;/filter-mapping&gt; <br />
&lt;servlet&gt;&lt;/servlet&gt; <br />
&lt;servlet-mapping&gt;&lt;/servlet-mapping&gt; <br />
&lt;session-config&gt;&lt;/session-config&gt; <br />
&lt;welcome-file-list&gt;&lt;/welcome-file-list&gt; <br />
&lt;taglib&gt;&lt;/taglib&gt; <br />
&lt;resource-ref&gt;&lt;/resource-ref&gt; <br />
&lt;security-constraint&gt;&lt;/security-constraint&gt; <br />
&lt;login-config&gt;&lt;/login-config&gt; <br />
&lt;/web-app&gt; <br />
在web.xml中元素定义的先后顺序不能颠倒，否则Tomcat服务器可能会抛出SAXParseException. <br />
--&gt; <br />
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems,Inc.//DTD Web Application 2.3//EN" "<a href="http://java.sun.com/dtd/web-app_2_3.dtd">http://java.sun.com/dtd/web-app_2_3.dtd</a>"&gt; <br />
&lt;web-app&gt; </p>
<p>&lt;display-name&gt;Sample Application&lt;/display-name&gt; </p>
<p>&lt;description&gt; <br />
This is a Sample Application <br />
&lt;/description&gt; </p>
<p>&lt;!-- <br />
filter 配置Servlet过滤器 <br />
filter-name 定义过滤器的名字。当有多个过滤器时，不能同名 <br />
filter-class 指定实现这一过滤的类，这个类负责具体的过滤事务 <br />
--&gt; <br />
&lt;filter&gt; <br />
&lt;filter-name&gt;SampleFilter&lt;/filter-name&gt; <br />
&lt;filter-class&gt;mypack.SampleFilter&lt;/filter-class&gt; <br />
&lt;/filter&gt; </p>
<p>&lt;!-- <br />
filter-mapping 设定过滤器负责过滤的URL <br />
filter-name 过滤器名。这里的名字一定要和filter中的过滤器名匹配 <br />
url-pattern 指定过滤器负责过滤的URL <br />
--&gt; <br />
&lt;filter-mapping&gt; <br />
&lt;filter-name&gt;SampleFilter&lt;/filter-name&gt; <br />
&lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt; <br />
&lt;/filter-mapping&gt; </p>
<p>&lt;!-- <br />
servlet 配置Servlet. <br />
servlet-name 定义Servlet的名字 <br />
servlet-class 指定实现这个servlet的类 <br />
init-param 定义Servlet的初始化参数和参数值，可有多个init-param。在servlet类中通过getInitParamenter(String name)方法访问初始化参数 <br />
load-on-startup 指定当Web应用启动时，装载Servlet的次序。 <br />
当值为正数或零时：Servlet容器先加载数值小的servlet，再依次加载其他数值大的servlet. <br />
当值为负或未定义：Servlet容器将在Web客户首次访问这个servlet时加载它 <br />
--&gt; <br />
&lt;servlet&gt; <br />
&lt;servlet-name&gt;SampleServlet&lt;/servlet-name&gt; <br />
&lt;servlet-class&gt;mypack.SampleServlet&lt;/servlet-class&gt; <br />
&lt;init-param&gt; <br />
&lt;param-name&gt;initParam1&lt;/param-name&gt; <br />
&lt;param-value&gt;2&lt;/param-value&gt; <br />
&lt;/init-param&gt; <br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt; <br />
&lt;/servlet&gt; </p>
<p>&lt;!-- <br />
配置servlet映射（下面代码为SampleServlet指定的相对URL为"/sample": <br />
servlet-name 指定servlet的名字，这里的名字应该和&lt;Servlet&gt;元素中定义的名字匹配。 <br />
url-pattern 指定访问这个servlet的URL。只需给出相对路径。 <br />
--&gt; <br />
&lt;servlet-mapping&gt; <br />
&lt;servlet-name&gt;SampleServlet&lt;/servlet-name&gt; <br />
&lt;url-pattern&gt;/sample&lt;/url-pattern&gt; <br />
&lt;/servlet-mapping&gt; </p>
<p>&lt;!--配置session session用来设定HttpSession的生命周期。单位（秒）--&gt; <br />
&lt;session-config&gt; <br />
&lt;session-timeout&gt;30&lt;/session-timeout&gt; <br />
&lt;/session-config&gt; </p>
<p>&lt;!--配置Wel0come0文件清单--&gt; <br />
&lt;welcome-file-list&gt; <br />
&lt;welcome-file&gt;login.jsp&lt;/welcome-file&gt; <br />
&lt;welcome-file&gt;index.htm&lt;/welcome-file&gt; <br />
&lt;/welcome-file-list&gt; </p>
<p>&lt;!-- <br />
配置Tag Library <br />
taglib-uri 设定Tag Library的唯一标识符，在Web应用中将根据这一标识符来引用Tag Library <br />
taglib-location 指定和Tag Library对应的TLD文件的位置 <br />
--&gt; <br />
&lt;taglib&gt; <br />
&lt;taglib-uri&gt;/mytaglib&lt;/taglib-uri&gt; <br />
&lt;taglib-location&gt;/WEB-INF/mytaglib.tld&lt;/taglib-location&gt; <br />
&lt;/taglib&gt; </p>
<p>&lt;!-- <br />
配置资源引用 <br />
description 对所引用的资源的说明 <br />
res-ref-name 指定所引用资源的JNDI名字 <br />
res-type 指定所引用资源的类名字 <br />
res-auth 指定管理所引用资源的Manager,它有两个可选值： <br />
Container：由容器来创建和管理resource <br />
Application:同WEB应用来创建和管理Resource <br />
--&gt; <br />
&lt;resource-ref&gt; <br />
&lt;description&gt;DB Connection&lt;/description&gt; <br />
&lt;res-ref-name&gt;jdbc/sampleDB&lt;/res-ref-name&gt; <br />
&lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt; <br />
&lt;res-auth&gt;Container&lt;/res-auth&gt; <br />
&lt;/resource-ref&gt; </p>
<p>&lt;!-- <br />
配置安全约束（以下代码指定当用户访问该WEB应用下的所有资源时，必须具备guest角色） <br />
web-resource-collection 声明受保护的WEB资源 <br />
auth-constraint 声明可以访问受保护资源的角色，可以包含多个&lt;role-name&gt;子元素 </p>
<p>web-resource-name 标识受保护的WEB资源 <br />
url-pattern 指定受保护的URL路径 <br />
--&gt; <br />
&lt;Security-constraint&gt; <br />
&lt;web-resource-collection&gt; <br />
&lt;web-resource-name&gt;sample appliction&lt;/web-resource-name&gt; <br />
&lt;url-pattern&gt;/*&lt;/url-pattern&gt; <br />
&lt;/web-resource-collection&gt; <br />
&lt;auth-constraint&gt; <br />
&lt;role-name&gt;guest&lt;/role-name&gt; <br />
&lt;/auth-constraint&gt; <br />
&lt;/Security-constraint&gt; </p>
<p><br />
&lt;!-- <br />
配置安全验证登录界面：指定当WEB客户访问受保护的WEB资源时，系统弹出的登录对话框的类型。 <br />
auth-method 指定验证方法，它有三个可选值：BASIC(基本验证)、DIGEST(摘要验证)、FORM(表单验证) <br />
realm-name 设定安全域的名称 <br />
form-login-config 当验证方法为FORM时，配置验证网页和出错网页 <br />
form-login-page 当验证方法为FORM时，设定验证网页 <br />
form-error-page 当验证方法为FORM时，设定出错网页 <br />
--&gt; <br />
&lt;login-config&gt; <br />
&lt;auth-method&gt;FORM&lt;/auth-method&gt; <br />
&lt;realm-name&gt; <br />
Tomcat Server Configuration form-Based Authentication Area <br />
&lt;/realm-name&gt; <br />
&lt;form-login-config&gt; <br />
&lt;form-login-page&gt;/login.jsp&lt;/form-login-page&gt; <br />
&lt;form-error-page&gt;/error.jsp&lt;/form-error-page&gt; <br />
&lt;/form-login-config&gt; <br />
&lt;/login-config&gt; </p>
<p>&lt;!--配置对安全验证角色的引用--&gt; <br />
&lt;security-role&gt; <br />
&lt;description&gt; <br />
The role that is required to log into the sample application <br />
&lt;/description&gt; <br />
&lt;role-name&gt;guest&lt;/role-name&gt; <br />
&lt;/security-role&gt; <br />
&lt;/web-app&gt; </p>
<img src ="http://www.blogjava.net/caizh2009/aggbug/333555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-09-30 16:06 <a href="http://www.blogjava.net/caizh2009/archive/2010/09/30/333555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java定时器 web</title><link>http://www.blogjava.net/caizh2009/archive/2010/09/30/333545.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 30 Sep 2010 06:56:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/09/30/333545.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/333545.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/09/30/333545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/333545.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/333545.html</trackback:ping><description><![CDATA[http://wangguorui89.javaeye.com/blog/428345<br />
<h3><a href="http://callan.javaeye.com/blog/123374">Java定时器在Web中的应用</a></h3>
关键字: java, 定时器, timertask
<p>在web中,定时器的启动一般随web server的启动而启动,一般有两种方法.</p>
<p>方法一：在web.xml里配置一个Servlet，并设置其随web server的启动而启动。然后在该Servlet的init()方法里启动定时器，在destory()方法里销毁定时器。<br />
方法二：在web.xml里配置一个Listener,然后在该Listener的初始化方法里启动定时器，在其销毁的方法朝左销毁定时器。</p>
<div>在servlet中启动定时器</div>
<div>java 代码</div>
<div>
<ol>
    <li>import&nbsp;java.io.IOException; &nbsp;&nbsp; </li>
    <li>import&nbsp;java.util.Timer; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.RequestDispatcher; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.ServletContext; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.ServletException; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.http.HttpServlet; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.http.HttpServletRequest; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.http.HttpServletResponse; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>import&nbsp;org.apache.commons.lang.StringUtils; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>public&nbsp;class&nbsp;ConvergeDataServlet&nbsp;extends&nbsp;HttpServlet&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;long&nbsp;serialVersionUID&nbsp;=&nbsp;1L; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Timer&nbsp;timer1&nbsp;=&nbsp;null; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Task&nbsp;task1; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Constructor&nbsp;of&nbsp;the&nbsp;object. &nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ConvergeDataServlet()&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp; </li>
    <li><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Destruction&nbsp;of&nbsp;the&nbsp;servlet.&nbsp;<br />
    </span>&nbsp;</span> </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;destroy()&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.destroy();&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(timer1!=null){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer1.cancel(); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;doGet(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;ServletException,&nbsp;IOException&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;doPost(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;ServletException,&nbsp;IOException&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doGet(request,&nbsp;response);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;init方法启动定时器 &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init()&nbsp;throws&nbsp;ServletException&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletContext&nbsp;context&nbsp;=&nbsp;getServletContext(); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;(true为用定时间刷新缓存) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;startTask&nbsp;=&nbsp;getInitParameter("startTask"); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;定时刷新时间(分钟) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Long&nbsp;delay&nbsp;=&nbsp;Long.parseLong(getInitParameter("delay")); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;启动定时器 &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(startTask.equals("true")){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer1&nbsp;=&nbsp;new&nbsp;Timer(true); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;task1&nbsp;=&nbsp;new&nbsp;Task(context); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer1.schedule(task1,&nbsp;delay&nbsp;*&nbsp;60&nbsp;*&nbsp;1000,&nbsp;delay&nbsp;*&nbsp;60&nbsp;*&nbsp;1000); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>} &nbsp;&nbsp; </li>
</ol>
</div>
<p>&nbsp;定时执行操作</p>
<div>java 代码</div>
<div>
<ol>
    <li>&nbsp;&nbsp; </li>
    <li>/** &nbsp; </li>
    <li>&nbsp;*&nbsp; &nbsp; </li>
    <li>&nbsp;*&nbsp;@author&nbsp;callan &nbsp; </li>
    <li>&nbsp;*/&nbsp;&nbsp; </li>
    <li>import&nbsp;java.util.TimerTask; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.ServletContext; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>public&nbsp;class&nbsp;Task&nbsp;extends&nbsp;TimerTask{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;ServletContext&nbsp;context; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;boolean&nbsp;isRunning&nbsp;=&nbsp;true; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Task(ServletContext&nbsp;context){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.context&nbsp;=&nbsp;context; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run()&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(isRunning){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>} &nbsp;&nbsp; </li>
</ol>
</div>
<p>在web.xml配置这个servlet为服务启动时就调用servlet</p>
<font>&lt;servlet&gt;&lt;/servlet&gt;<br />
&nbsp;&nbsp;<font>&lt; servlet &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt; servlet-name &gt;taskservlet&lt; /&nbsp;servlet-name &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; servlet-class &gt;com.task&lt; /servlet-class &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-name &gt;startTask&lt; /param-name &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-value &gt;true&lt; /param-value &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; /init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-name &gt;intervalTime&lt; /param-name &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-value &gt;1&lt; /param-value &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; /init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; load-on-startup &gt;300&lt; /load-on-startup &gt;<br />
&nbsp; &lt; /servlet &gt;</font></font>
<p>&lt;servlet&gt;&lt;/servlet&gt;</p>
<br />
<img src ="http://www.blogjava.net/caizh2009/aggbug/333545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-09-30 14:56 <a href="http://www.blogjava.net/caizh2009/archive/2010/09/30/333545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java定时器在Web中的应用</title><link>http://www.blogjava.net/caizh2009/archive/2010/09/30/333538.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 30 Sep 2010 05:53:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/09/30/333538.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/333538.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/09/30/333538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/333538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/333538.html</trackback:ping><description><![CDATA[http://callan.javaeye.com/blog/123374<br />
关键字: java, 定时器, timertask
<p>在web中,定时器的启动一般随web server的启动而启动,一般有两种方法.</p>
<p>方法一：在web.xml里配置一个Servlet，并设置其随web server的启动而启动。然后在该Servlet的init()方法里启动定时器，在destory()方法里销毁定时器。<br />
方法二：在web.xml里配置一个Listener,然后在该Listener的初始化方法里启动定时器，在其销毁的方法朝左销毁定时器。</p>
<div>在servlet中启动定时器</div>
<div>java 代码</div>
<div>
<ol>
    <li>import&nbsp;java.io.IOException; &nbsp;&nbsp; </li>
    <li>import&nbsp;java.util.Timer; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.RequestDispatcher; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.ServletContext; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.ServletException; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.http.HttpServlet; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.http.HttpServletRequest; &nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.http.HttpServletResponse; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>import&nbsp;org.apache.commons.lang.StringUtils; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>public&nbsp;class&nbsp;ConvergeDataServlet&nbsp;extends&nbsp;HttpServlet&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;long&nbsp;serialVersionUID&nbsp;=&nbsp;1L; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Timer&nbsp;timer1&nbsp;=&nbsp;null; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Task&nbsp;task1; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Constructor&nbsp;of&nbsp;the&nbsp;object. &nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ConvergeDataServlet()&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/** &nbsp; </li>
    <li><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Destruction&nbsp;of&nbsp;the&nbsp;servlet.&nbsp;<br />
    </span>&nbsp;</span> </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;destroy()&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super.destroy();&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(timer1!=null){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer1.cancel(); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;doGet(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;ServletException,&nbsp;IOException&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;doPost(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;ServletException,&nbsp;IOException&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doGet(request,&nbsp;response);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;init方法启动定时器 &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init()&nbsp;throws&nbsp;ServletException&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ServletContext&nbsp;context&nbsp;=&nbsp;getServletContext(); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;(true为用定时间刷新缓存) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;startTask&nbsp;=&nbsp;getInitParameter("startTask"); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;定时刷新时间(分钟) &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Long&nbsp;delay&nbsp;=&nbsp;Long.parseLong(getInitParameter("delay")); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;启动定时器 &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(startTask.equals("true")){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer1&nbsp;=&nbsp;new&nbsp;Timer(true); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;task1&nbsp;=&nbsp;new&nbsp;Task(context); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timer1.schedule(task1,&nbsp;delay&nbsp;*&nbsp;60&nbsp;*&nbsp;1000,&nbsp;delay&nbsp;*&nbsp;60&nbsp;*&nbsp;1000); &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>} &nbsp;&nbsp; </li>
</ol>
</div>
<p>&nbsp;定时执行操作</p>
<div>java 代码</div>
<div>
<ol>
    <li>&nbsp;&nbsp; </li>
    <li>/** &nbsp; </li>
    <li>&nbsp;*&nbsp; &nbsp; </li>
    <li>&nbsp;*&nbsp;@author&nbsp;callan &nbsp; </li>
    <li>&nbsp;*/&nbsp;&nbsp; </li>
    <li>import&nbsp;java.util.TimerTask; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>import&nbsp;javax.servlet.ServletContext; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>public&nbsp;class&nbsp;Task&nbsp;extends&nbsp;TimerTask{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;ServletContext&nbsp;context; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;boolean&nbsp;isRunning&nbsp;=&nbsp;true; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Task(ServletContext&nbsp;context){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.context&nbsp;=&nbsp;context; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;run()&nbsp;{ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(isRunning){ &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp; </li>
    <li>&nbsp;&nbsp; </li>
    <li>} &nbsp;&nbsp; </li>
</ol>
</div>
<p>在web.xml配置这个servlet为服务启动时就调用servlet</p>
<font>&lt;servlet&gt;&lt;/servlet&gt;<br />
&nbsp;&nbsp;<font>&lt; servlet &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt; servlet-name &gt;taskservlet&lt; /&nbsp;servlet-name &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; servlet-class &gt;com.task&lt; /servlet-class &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-name &gt;startTask&lt; /param-name &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-value &gt;true&lt; /param-value &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; /init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-name &gt;intervalTime&lt; /param-name &gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt; param-value &gt;1&lt; /param-value &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; /init-param &gt;<br />
&nbsp;&nbsp;&nbsp; &lt; load-on-startup &gt;300&lt; /load-on-startup &gt;<br />
&nbsp; &lt; /servlet &gt;</font></font>
<p>&lt;servlet&gt;&lt;/servlet&gt;</p>
<img src ="http://www.blogjava.net/caizh2009/aggbug/333538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-09-30 13:53 <a href="http://www.blogjava.net/caizh2009/archive/2010/09/30/333538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用servlet显示图片</title><link>http://www.blogjava.net/caizh2009/archive/2010/09/25/332814.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Sat, 25 Sep 2010 05:43:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/09/25/332814.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/332814.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/09/25/332814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/332814.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/332814.html</trackback:ping><description><![CDATA[最近，公司用servlet做一个跟踪图片点击技术的模块，我个人略有心得想和大家分享，<br />
&nbsp;不知大家愿意审视。<br />
&nbsp;这个模块挺大，我仅说说用servlet显示图片部分。我先说说用servlet显示图片的一个流程：<br />
&nbsp;1.&nbsp;设置response的输出类型：<br />
&nbsp;&nbsp;&nbsp;&nbsp;对应的语句--response.setContentType("image/gif;charset=GB2312")&nbsp;，response&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;便能输出gif图片，"image/gif;charset=GB2312"便是输出类型，当然你可以输出<br />
&nbsp;&nbsp;&nbsp;&nbsp;"image/jpg;charset=GB2312"类型文件。<br />
&nbsp;2.&nbsp;得到文件流：<br />
&nbsp;&nbsp;&nbsp;&nbsp;servlet是以流的形式件图片文件从服务器读出，通过response将流发到浏览器的。<br />
&nbsp;3.&nbsp;得到输出流：<br />
&nbsp;&nbsp;&nbsp;&nbsp;对应的语句--OutputStream&nbsp;output&nbsp;=&nbsp;response.getOutputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;当然，处理图片文件需要以二进制形式的流。<br />
&nbsp;4.&nbsp;文件流的编码（但也不一定必须编码的，如果不是文件流，则必须编码）<br />
&nbsp;&nbsp;&nbsp;&nbsp;所以我给大家一个用编码的代码和不用编码的代码.<br />
顺便说一句，sun公司仅提供了jpg图片文件的编码api。<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;　我想基本流程都讲完了，下面我把代码拿给大家看一下，大家自然一目了然了：<br />
package&nbsp;xjw.personal.servet;<br />
import&nbsp;java.io.*;<br />
import&nbsp;javax.servlet.*;<br />
import&nbsp;javax.servlet.http.*;<br />
import&nbsp;com.sun.image.codec.jpeg.*;//sun公司仅提供了jpg图片文件的编码api<br />
import&nbsp;javax.imageio.stream.*;<br />
import&nbsp;java.awt.*;<br />
import&nbsp;java.awt.image.BufferedImage;<br />
public&nbsp;class&nbsp;ShowPicture&nbsp;&nbsp;extends&nbsp;HttpServlet<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;String&nbsp;GIF="image/gif;charset=GB2312";//设定输出的类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;String&nbsp;JPG="image/jpeg;charset=GB2312"；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;init()&nbsp;&nbsp;throws&nbsp;ServletException<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;doGet(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;IOException,&nbsp;ServletException<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doPost(request,&nbsp;response);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;doPost(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throws&nbsp;IOException,&nbsp;ServletException<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;spec=request.getParameter("spec");//输出图片的类型的标志<br />
&nbsp;int&nbsp;int_spec=Integer.parseInt(spec);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(spec==1)&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;imagePath="/jfgg/b1.jpg";//图片相对web应用的位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;imagePath="/jfgg/b2.gif";//图片相对web应用的位置<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;output&nbsp;=&nbsp;response.getOutputStream();//得到输出流<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(imagePath.toLowerCase().endsWith(".jpg"))//使用编码处理文件流的情况：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.setContentType(JPG);//设定输出的类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//得到图片的真实路径&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imagePath&nbsp;=&nbsp;getServletContext().getRealPath(imagePath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//得到图片的文件流<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;imageIn&nbsp;=&nbsp;new&nbsp;FileInputStream(new&nbsp;File(imagePath));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//得到输入的编码器，将文件流进行jpg格式编码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JPEGImageDecoder&nbsp;decoder&nbsp;=&nbsp;JPEGCodec.createJPEGDecoder(imageIn);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//得到编码后的图片对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage&nbsp;image&nbsp;=&nbsp;decoder.decodeAsBufferedImage();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//得到输出的编码器<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JPEGImageEncoder&nbsp;encoder&nbsp;=&nbsp;JPEGCodec.createJPEGEncoder(output);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;encoder.encode(image);//对图片进行输出编码<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageIn.close();//关闭文件流<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(imagePath.toLowerCase().endsWith(".gif"))//不使用编码处理文件流的情况：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;response.setContentType(GIF);<br />
&nbsp;&nbsp;&nbsp;&nbsp;ServletContext&nbsp;context&nbsp;=&nbsp;getServletContext();//得到背景对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;imageIn=context.getResourceAsStream(imagePath);//文件流<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedInputStream&nbsp;bis=new&nbsp;BufferedInputStream(imageIn);//输入缓冲流<br />
&nbsp;&nbsp;&nbsp;&nbsp;BufferedOutputStream&nbsp;bos=new&nbsp;BufferedOutputStream(output);//输出缓冲流<br />
&nbsp;&nbsp;&nbsp;&nbsp;byte&nbsp;data[]=new&nbsp;byte[4096];//缓冲字节数<br />
&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;size=0;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;size=bis.read(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(size!=-1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bos.write(data,0,size);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size=bis.read(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;bis.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;bos.flush();//清空输出缓冲流<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bos.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
最后是如何调用，你可以简单的映射一下servelt，我就将servet的名映射为<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowPic,&nbsp;&nbsp;于是下代码调用<br />
&lt;html&gt;<br />
&lt;body&gt;<br />
&lt;img&nbsp;src="ShowPic?spec=2"&gt;&lt;/a&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这样图片便显示在htm上了，本人研究java的时间不长，如有问题，尽情指正。
<img src ="http://www.blogjava.net/caizh2009/aggbug/332814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-09-25 13:43 <a href="http://www.blogjava.net/caizh2009/archive/2010/09/25/332814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>英文自我介绍</title><link>http://www.blogjava.net/caizh2009/archive/2010/09/20/332513.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Mon, 20 Sep 2010 05:17:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/09/20/332513.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/332513.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/09/20/332513.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/332513.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/332513.html</trackback:ping><description><![CDATA[一、完整的自我介绍1<br />
Good morning !<br />
It is really my honor to have this
opportunity for an interview,I hope I can make a good performance today.
I&#8217;m confident that I can succeed.Now I will introduce myself briefly.<br />
<br />
I
am 26 years old,born in shandong province .I was graduated from qingdao
university. My major is electronic and i got my bachelor degree after
my graduation in the year of 2003.I spend most of my time on study,I
have passed CET4/6 . and I have acquired basic knowledge of my major
during my school time.In July 2003, I began work for a small private
company as a technical support engineer in QingDao city.Because I&#8217;m
capable of more responsibilities, so I decided to change my job.And in
August 2004,I left QingDao to BeiJing and worked for a foreign
enterprise as a automation software test engineer.Because I want to
change my working environment, I&#8217;d like to find a job which is more
challenging. Morover Motorola is a global company, so I feel I can gain
the most from working in this kind of company ennvironment. That is the
reason why I come here to compete for this position.<br />
<br />
I think I&#8217;m a good team player and I&#8217;m a person of great honesty to others. Also I am able to work under great pressure.<br />
<br />
That&#8217;s all. Thank you for giving me the chance.<br />
<br />
完整的自我介绍2<br />
good
morning, my name is jack, it is really a great honor to have this
opportunity for a interview, i would like to answer whatever you may
raise, and i hope i can make a good performance today, eventually enroll
in this prestigious university in september. now i will introduce
myself briefly.<br />
<br />
i am 21 years old,born in heilongjiang province
,northeast of china,and i am curruently a senior student at beijing XX
uni.my major is packaging engineering.and i will receive my bachelor
degree after my graduation in june.in the past 4 years,i spend most of
my time on study,i have passed CET4/6 with an ease. and i have acquired
basic knowledge of packaging and publishing both in theory and in
practice. besides, i have attend several packaging exhibition hold in
Beijing, this is our advantage study here, i have taken a tour to some
big factory and company. through these i have a deeply understanding of
domestic packaging industry. compared to developed countries such as us,
unfortunately, although we have made extraordinary progress since
1978,our packaging industry are still underdeveloped, mess, unstable,
the situation of employees in this field are awkard.&nbsp; <br />
<br />
but i have
full confidence in a bright future if only our economy can keep the
growth pace still. i guess you maybe interested in the reason itch to
law, and what is my plan during graduate study life, i would like to
tell you that pursue law is one of my lifelong goal,i like my major
packaging and i won&#8217;t give up,if i can pursue my master degree here i
will combine law with my former education. i will work hard in
thesefields ,patent ,trademark, copyright, on the base of my years study
in department of p&amp;p.<br />
<br />
my character? i cannot describe it
well, but i know i am optimistic and confident. sometimes i prefer to
stay alone, reading, listening to music, but i am not lonely, i like to
chat with my classmates, almost talk everything ,my favorite pastime is
valleyball,playing cards or surf online. through college life,i learn
how to balance between study and entertainment. by the way, i was a
actor of our amazing drama club. i had a few glorious memory on stage.
that is my pride.<br />
<br />
二、模板1：自我介绍(self-introduction)<br />
Good morning. I am glad to be here for this interview.&nbsp; <br />
<br />
First
let me introduce myself. My name is ***, 24. I come from ******,the
capital of *******Province. I graduated from the ******* department of
*****University in July ,2001.In the past two years I have been
preparing for the postgraduate examination while I have been teaching
*****in NO.****middle School and I was a head-teacher of a class in
junior grade two.Now all my hard work has got a result since I have a
chance to be interview by you . I am open-minded ,quick in thought and
very fond of history.In my spare time,I have broad interests like many
other youngsters.I like reading books, especially those about
*******.Frequently I exchange with other people by making comments in
the forum on line.In addition ,during my college years,I was once a
Net-bar technician.So, I have a comparatively good command of network
application.I am able to operate the computer well.I am skillful in
searching for information in Internet.I am a football fan for
years.Italian team is my favorite.<br />
<br />
Anyway,I feel great pity for
our country&#8217;s team. I always believe that one will easily lag behind
unless he keeps on learning .Of course, if I am given a chance to study
****** in this famous University,I will stare no effort to master a good
command of advance ******.<br />
<br />
模板2：自我介绍(self-introduction)<br />
Good afternoon .I am of great hornor to stand here and introduce myself to you .<br />
<br />
First
of all ,my english name is &#8230;and my chinese name is ..If you are going
to have a job interview ,you must say much things which can show your
willness to this job ,such as ,it is my long cherished dream to be &#8230;and I
am eager to get an opportunity to do&#8230;and then give some examples which
can give evidence to .then you can say something about your hobbies .and
it is best that the hobbies have something to do with the job.<br />
<br />
What
is more important is do not forget to communicate with the
interviewee,keeping a smile and keeping your talks interesting and funny
can contribute to the success.<br />
<br />
I hope you will give them a wonderful speech .Good luck to you !<br />
<br />
三、面试现场提问环节：<br />
1. What is your greatest strength?（你最突出的优点是什么？）<br />
这是很多面试
考官喜欢问的一个问题，这是你展示自己的最佳机会，不要吹嘘自己或过于自负，但要让雇主知道你相信自己，你知道自己的优点。如可答：&#8220;我认为我最大的优点
是能够执着地尽力把事情办好。当做完一件工作而其成果又正合我的预想时，我会有一种真正的成就感。我给自己定了一些高目标。比如说，我要成为出色的毕业
生。尽管在大学一年级时我启动慢了些，但最终我以优等论文完成了学业。&#8221;<br />
I feel that my strongest asset is
my ability to stick to things to get them done. I feel a real sense of
accomplishment when I finish a job and it turns out just as I&#8217;d planned.
I&#8217;ve set some high goals for myself. For example, I want to graduate
with highest distinction. And even though I had a slow start in my
freshman year, I made up for it by doing an honor&#8217;s thesis.<br />
<br />
2. What is your greatest weakness?（你最大的弱点是什么？）<br />
你不应该说你没有任何弱点，以此来回避这个问题。每个人都有弱点，最佳策略是承认你的弱点，但同时表明你在予以改进，并有克服弱点的计划。可能的话，你可说出一项可能会给公司带来好处的弱点，如可说：&#8220;我是一个完美主义者。工作做得不漂亮，我是不会撒手的。&#8221;<br />
I&#8217;m such a perfectionist that I will not stop until a job is well done.<br />
I'm married and I have two beautiful children. I'm interested in cricket, history and bird watching.<br />
I graduated from university with a Business Management degree with high marks. I studied&nbsp; <br />
courses such as accounting and English. I've got two years' work experience, first as a clerk and&nbsp; <br />
then as a manager in a factory in the capital, so I can easily do the duties of this job. I'm also very&nbsp; <br />
skilled with computers.&nbsp; <br />
&nbsp;<br />
我
结婚了，有两个漂亮的孩子。我喜欢打板球，喜欢历史，喜欢观察野鸟。我的大学专业是商务管理，并且成绩优秀。在校时我研读的课程有会计，英语等。我有两年
的工作经验。第一份工作是做一名普通的职员，第二次是在工厂里做管理人员。所以我可以胜任这份工作。另外，我的电脑技术也很不错。&nbsp; <br />
I'm efficient; when I have a project to do, I do it thoroughly and on
time. For example, I always double-check my reports. I like to be
organized; in my last managerial position I had many duties so I
organized a schedule and prioritized my jobs. I'm a fast learner: I
didn't know anything about computers before university, it was difficult
at first but I studied hard, got high marks and can use it effectively
now&#8230;. I believe that problems are really challenges and that I can solve
them.&nbsp; <br />
&nbsp;<br />
我做事有效率。当我做一个项目时，我考虑很周到并且按时完工。比如，我总是对报告进行二度确认。我做事有条理。在我
上一份工作中，我是管理人员，我有许多事情要做，所以我自己列了一个做事提纲并且按事情的轻重缓急来安排时间。我学习能力很强。在大学前我不懂电脑，对我
来说，起初很困难，但我用功学习电脑并且得到了高分，所以现在对电脑驾轻就熟。我认为，工作中的问题是有挑战性的，但我可以解决。&nbsp; <br />
<br />
<br />
&nbsp;<br />
老师点评：<br />
This is an excellent answer. It gives a lot of additional information which is not on the CV<br />
It gives specific details, examples and evidence of key skills and qualities&nbsp; <br />
It reveals the personality and values of the candidate (for example, 'problems are really challenges')<br />
It shows a problem-solving approach and self-management skills.&nbsp; <br />
<img src ="http://www.blogjava.net/caizh2009/aggbug/332513.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-09-20 13:17 <a href="http://www.blogjava.net/caizh2009/archive/2010/09/20/332513.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>排序算法复习（Java实现）(一）： 插入，冒泡，选择，Shell,快速排序</title><link>http://www.blogjava.net/caizh2009/archive/2010/09/07/331331.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 07 Sep 2010 09:38:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/09/07/331331.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/331331.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/09/07/331331.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/331331.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/331331.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 为了便于管理，先引入个基础类：package&nbsp;algorithms;/**&nbsp;*&nbsp;@author&nbsp;yovn&nbsp;*&nbsp;*/public&nbsp;abstract&nbsp;class&nbsp;Sorter&lt;E&nbsp;extends&nbsp;Comparable&lt;E&gt;&gt;&nbsp;{...&nbsp;&nbsp;<a href='http://www.blogjava.net/caizh2009/archive/2010/09/07/331331.html'>阅读全文</a><img src ="http://www.blogjava.net/caizh2009/aggbug/331331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-09-07 17:38 <a href="http://www.blogjava.net/caizh2009/archive/2010/09/07/331331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 为什么覆写equals的时候一定要覆写hashCode?</title><link>http://www.blogjava.net/caizh2009/archive/2010/08/27/330035.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 27 Aug 2010 01:51:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/08/27/330035.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/330035.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/08/27/330035.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/330035.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/330035.html</trackback:ping><description><![CDATA[经常在论坛上面看到覆写hashCode函数的问题，很多情况下是一些开发者不了解hash code，或者和equals一起用的时候不太清楚为啥一定要复写hashCode。
<p>&nbsp;&nbsp; &nbsp;对于hash code的理论我不想多说，这个话题太大。我只想说用hash code的原因只有一个：<strong>效率</strong>。理论的说法它的复杂度只有O(1)。试想我们把元素放在线性表里面，每次要找一个元素必须从头一个一个的找它的复杂度有O(n)。如果放在平衡二叉树，复杂度也有O(log n)。</p>
<p>&nbsp;&nbsp; 为啥很多地方说&#8220;覆写equals的时候一定要覆写hashCode&#8221;。说到这里我知道很多人知道有个原则：<strong>如果a.equals(b)那么要确保a.hashCode()==b.hashCode()</strong>。为什么？hashCode和我写的程序的业务逻辑毫无关系，为啥我要override?&nbsp;要我说<strong>如果你的class永远不可能放在hash code为基础的容器内，不必劳神，您真的不必override hashCode() :)</strong></p>
<p>&nbsp;&nbsp; &nbsp;说得准确一点放在HashMap和Hashtable里面如果是作为value而不是作为key的话也是不必override
hashCode了。至于HashSet，实际上它只是忽略value的HashMap,每次HashSet.add(o)其实就是
HashMap.put(o, dummyObject)。</p>
<p>&nbsp;&nbsp; &nbsp;那为什么放到Hash容器里面要overide hashCode呢？因为每次get的时候HashMap既要看equals是不是true也要看hash code是不是一致，put的时候也是要看equals和hash code。</p>
<p>&nbsp;&nbsp; &nbsp;如果说到这里您还是不太明白，咱就举个例子：</p>
<p>&nbsp;&nbsp; &nbsp;譬如把一个自己定义的class
Foo{...}放到HashMap。实际上HashMap也是把数据存在一个数组里面，所以在put函数里面，HashMap会调
Foo.hashCode()算出作为这个元素在数组里面的下标，然后把key和value封装成一个对象放到数组。等一下，万一2个对象算出来的
hash
code一样怎么办？会不会冲掉？先回答第2个问题，会不会冲掉就要看Foo.equals()了，如果equals()也是true那就要冲掉了。万一
是false,就是所谓的collision了。当2个元素hashCode一样但是equals为false的时候，那个HashMap里面的数组的这
个元素就变成了链表。也就是hash code一样的元素在一个链表里面，链表的头在那个数组里面。</p>
<p>回过来说get的时候，HashMap也先调key.hashCode()算出数组下标，然后看equals是不是true，所以就涉及了equals。</p>
<p>&nbsp;&nbsp;
&nbsp;反观假设如果a.equals(b)但是a.hashCode()!=b.hashCode()的话，在put元素a之后，我们又用一个
a.equals(b)但是b.hashCode()!=a.hashCode()的b元素作为key来get的时候就找不到a了。如果
a.hashCode()==b.hashCode()但是!a.equals(b)倒是不要紧，这2个元素会collision然后被放到链表，只是效
率变差。</p>
<p>&nbsp;&nbsp;这里有个非常简化版的HashMap实现帮助大家理解。</p>
<p><span style="font-family: monospace; font-size: small;"><span style="white-space: pre-wrap;"><span style="font-size: small;">
<div>
<div>
<div><a href="http://blog.csdn.net/michaellufhl/archive/2010/08/23/5833188.aspx#" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a href="http://blog.csdn.net/michaellufhl/archive/2010/08/23/5833188.aspx#" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy to clipboard</a><a href="http://blog.csdn.net/michaellufhl/archive/2010/08/23/5833188.aspx#" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a href="http://blog.csdn.net/michaellufhl/archive/2010/08/23/5833188.aspx#" onclick="dp.sh.Toolbar.Command('About',this);return false;">?</a></div>
</div>
<ol start="1">
    <li><span>/*&nbsp;</span></li>
    <li>&nbsp;*&nbsp;Just&nbsp;to&nbsp;demonstrate&nbsp;hash&nbsp;map&nbsp;mechanism,&nbsp;&nbsp;</li>
    <li>&nbsp;*&nbsp;Please&nbsp;do&nbsp;not&nbsp;use&nbsp;it&nbsp;in&nbsp;your&nbsp;commercial&nbsp;product.&nbsp;</li>
    <li>&nbsp;*&nbsp;</li>
    <li>&nbsp;*&nbsp;@author&nbsp;Shengyuan&nbsp;Lu&nbsp;卢声远&nbsp;&lt;michaellufhl@yahoo.com.cn&gt;&nbsp;</li>
    <li>&nbsp;*/&nbsp;&nbsp;</li>
    <li>public&nbsp;class&nbsp;SimpleHashMap&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;ArrayList&lt;LinkedList&lt;Entry&gt;&gt;&nbsp;entries&nbsp;=&nbsp;new&nbsp;ArrayList&lt;LinkedList&lt;Entry&gt;&gt;();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Each&nbsp;key-value&nbsp;is&nbsp;encapsulated&nbsp;by&nbsp;Entry.&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;class&nbsp;Entry&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;key;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;value;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Entry(Object&nbsp;key,&nbsp;Object&nbsp;value)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.key&nbsp;=&nbsp;key;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.value&nbsp;=&nbsp;value;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;put(Object&nbsp;key,&nbsp;Object&nbsp;value)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LinkedList&lt;Entry&gt;&nbsp;e&nbsp;=&nbsp;entries.get(key.hashCode());&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e&nbsp;!=&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(Entry&nbsp;entry&nbsp;:&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(entry.key.equals(key))&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entry.value&nbsp;=&nbsp;value;//&nbsp;Match&nbsp;in&nbsp;lined&nbsp;list&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.addFirst(new&nbsp;Entry(key,&nbsp;value));//&nbsp;Add&nbsp;the&nbsp;entry&nbsp;to&nbsp;the&nbsp;list&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Put&nbsp;the&nbsp;new&nbsp;entry&nbsp;in&nbsp;array&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LinkedList&lt;Entry&gt;&nbsp;newEntry&nbsp;=&nbsp;new&nbsp;LinkedList&lt;Entry&gt;();&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newEntry.add(new&nbsp;Entry(key,&nbsp;value));&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entries.add(key.hashCode(),&nbsp;newEntry);&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;get(Object&nbsp;key)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LinkedList&lt;Entry&gt;&nbsp;e&nbsp;=&nbsp;entries.get(key.hashCode());&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(e&nbsp;!=&nbsp;null)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(Entry&nbsp;entry&nbsp;:&nbsp;e)&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(entry.key.equals(key))&nbsp;{&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;entry.value;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;null;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;/**&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Do&nbsp;we&nbsp;need&nbsp;to&nbsp;override&nbsp;equals()&nbsp;and&nbsp;hashCode()&nbsp;for&nbsp;SimpleHashMap&nbsp;itself?&nbsp;&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;I&nbsp;don't&nbsp;know&nbsp;either:)&nbsp;</li>
    <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</li>
    <li>}&nbsp;&nbsp;</li>
</ol>
</div>
<textarea style="display: none;" cols="50" rows="15" name="code" class="java">/*
* Just to demonstrate hash map mechanism,
* Please do not use it in your commercial product.
*
* @author Shengyuan Lu 卢声远 &lt;michaellufhl@yahoo.com.cn&gt;
*/
public class SimpleHashMap {
ArrayList&lt;LinkedList&lt;Entry&gt;&gt; entries = new ArrayList&lt;LinkedList&lt;Entry&gt;&gt;();
/**
* Each key-value is encapsulated by Entry.
*/
static class Entry {
Object key;
Object value;
public Entry(Object key, Object value) {
this.key = key;
this.value = value;
}
}
void put(Object key, Object value) {
LinkedList&lt;Entry&gt; e = entries.get(key.hashCode());
if (e != null) {
for (Entry entry : e) {
if (entry.key.equals(key)) {
entry.value = value;// Match in lined list
return;
}
}
e.addFirst(new Entry(key, value));// Add the entry to the list
} else {
// Put the new entry in array
LinkedList&lt;Entry&gt; newEntry = new LinkedList&lt;Entry&gt;();
newEntry.add(new Entry(key, value));
entries.add(key.hashCode(), newEntry);
}
}
Object get(Object key) {
LinkedList&lt;Entry&gt; e = entries.get(key.hashCode());
if (e != null) {
for (Entry entry : e) {
if (entry.key.equals(key)) {
return entry.value;
}
}
}
return null;
}
/**
* Do we need to override equals() and hashCode() for SimpleHashMap itself?
* I don't know either:)
*/
}
</textarea> </span></span></span></p>
<p><span style="font-family: monospace; font-size: small;"><span style="white-space: pre-wrap;"><span style="font-size: small;"><br />
</span></span></span></p>
<p><span style="font-family: monospace;"><span style="white-space: pre-wrap;">这个问题的权威阐释可以参考Bloch的&lt;Effective Java&gt;的 </span></span>Item 9: Always override&nbsp;<em>hashCode</em>&nbsp;when you override&nbsp;<em>equals</em></p>
<img src ="http://www.blogjava.net/caizh2009/aggbug/330035.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-08-27 09:51 <a href="http://www.blogjava.net/caizh2009/archive/2010/08/27/330035.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 数据库设计三大范式应用实例剖析</title><link>http://www.blogjava.net/caizh2009/archive/2010/07/08/325534.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 08 Jul 2010 03:13:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/07/08/325534.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/325534.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/07/08/325534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/325534.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/325534.html</trackback:ping><description><![CDATA[<span style="font-family: verdana,sans-serif; font-size: 14px; line-height: 21px;">
<p style="margin: 1em 0px 0.5em; padding: 0px;">引言<br />
<br />
数据库的设计范式是数据库设计所需要满足的规范，满足这些规范的数据库是简洁的、结构明晰的，同时，不会发生插入（insert）、删除
（delete）和更新（update）操作异常。反之则是乱七八糟，不仅给数据库的编程人员制造麻烦，而且面目可憎，可能存储了大量不需要的冗余信息。<br />
<br />
设计范式是不是很难懂呢？非也，大学教材上给我们一堆数学公式我们当然看不懂，也记不住。所以我们很多人就根本不按照范式来设计数据库。<br />
<br />
实质上，设计范式用很形象、很简洁的话语就能说清楚，道明白。本文将对范式进行通俗地说明，并以笔者曾经设计的一个简单论坛的数据库为例来讲解怎样将这
些范式应用于实际工程。<br />
<br />
范式说明<br />
<br />
第一范式（1NF）：数据库表中的字段都是单一属性的，不可再分。这个单一属性
由基本类型构成，包括整型、实数、字符型、逻辑型、日期型等。<br />
<br />
例如，如下的数据库表是符合第一范式的：<br />
</p>
<table align="center" border="1" cellpadding="2" cellspacing="0" width="90%">
    <tbody>
        <tr>
            <td>字段1</td>
            <td>字段2</td>
            <td>字段3</td>
            <td>字段4</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
<br />
而这样的数据库表是不符合第一范式的：<br />
<br />
<table align="center" border="1" cellpadding="2" cellspacing="0" width="90%">
    <tbody>
        <tr>
            <td>字段1</td>
            <td>字段2</td>
            <td colspan="2">字段3</td>
            <td>字段4</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>字段3.1</td>
            <td>字段3.2</td>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
<p style="margin: 1em 0px 0.5em; padding: 0px;"><br />
很显然，在当前的任何关系数据库管理系
统（DBMS）中，傻瓜也不可能做出不符合第一范式的数据库，因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此，你想在现有的DBMS中
设计出不符合第一范式的数据库都是不可能的。<br />
<br />
第二范式（2NF）：数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖（部
分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况），也即所有非关键字段都完全依赖于任意一组候选关键字。</p>
<table align="left" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td valign="top">&nbsp;</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
<br />
<br />
假定选课关系表为SelectCourse(学号, 姓名, 年龄, 课程名称, 成绩, 学分)，关键字为组合关键字(学号,
课程名称)，因为存在如下决定关系：<br />
<br />
(学号, 课程名称) &#8594; (姓名, 年龄, 成绩, 学分)<br />
<br />
这个数据库表
不满足第二范式，因为存在如下决定关系：<br />
<br />
(课程名称) &#8594; (学分)<br />
<br />
(学号) &#8594; (姓名, 年龄)<br />
<br />
即存在组合关键字中的字段决定非关键字的情况。<br />
<br />
由于不符合2NF，这个选课关系表会存在如下问题：<br />
<br />
(1)
数据冗余：<br />
<br />
同一门课程由n个学生选修，"学分"就重复n-1次；同一个学生选修了m门课程，姓名和年龄就重复了m-1次。<br />
<br />
(2) 更新异常：<br />
<br />
若调整了某门课程的学分，数据表中所有行的"学分"值都要更新，否则会出现同一门课程学分不同的情况。<br />
<br />
(3) 插入异常：<br />
<br />
假设要开设一门新的课程，暂时还没有人选修。这样，由于还没有"学号"关键字，课程名称和学分也无法记录入数据
库。<br />
<br />
(4) 删除异常：<br />
<br />
假设一批学生已经完成课程的选修，这些选修记录就应该从数据库表中删除。但是，与此同
时，课程名称和学分信息也被删除了。很显然，这也会导致插入异常。&nbsp;<br />
<br />
把选课关系表SelectCourse改为如下三个表：<br />
<br />
学生：Student(学号, 姓名, 年龄)；<br />
<br />
课程：Course(课程名称, 学分)；<br />
<br />
选课关
系：SelectCourse(学号, 课程名称, 成绩)。<br />
<br />
这样的数据库表是符合第二范式的，消除了数据冗余、更新异常、插入异常
和删除异常。<br />
<br />
另外，所有单关键字的数据库表都符合第二范式，因为不可能存在组合关键字。<br />
<br />
第三范式（3NF）：在
第二范式的基础上，数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖，指的是如果存在"A &#8594; B &#8594;
C"的决定关系，则C传递函数依赖于A。因此，满足第三范式的数据库表应该不存在如下依赖关系：<br />
<br />
关键字段 &#8594; 非关键字段x &#8594;
非关键字段y<br />
<br />
假定学生关系表为Student(学号, 姓名, 年龄, 所在<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="color: #000000;">学院</span></a>,&nbsp;<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>地点,&nbsp;<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>电话)，关键字为单一关键字"学号"，因为存在如下决定关系：<br />
<br />
(学号) &#8594;
(姓名, 年龄, 所在<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>,&nbsp;<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>地点,&nbsp;<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>电话)<br />
<br />
这个数据库是
符合2NF的，但是不符合3NF，因为存在如下决定关系：<br />
<br />
(学号) &#8594; (所在<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>) &#8594; (<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>地点,&nbsp;<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>电话)<br />
<br />
即存在非关键
字段"<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>地点"、"<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>电话"对关键字段"学号"的传递函数依
赖。<br />
<br />
它也会存在数据冗余、更新异常、插入异常和删除异常的情况，读者可自行分析得知。<br />
<br />
把学生关系表分为如下两个
表：<br />
<br />
学生：(学号, 姓名, 年龄, 所在<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>)；<br />
<br />
<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>：(<a style="text-decoration: none; color: #336699;" href="http://edu.itbulo.com/"><span style="text-decoration: underline;"><span style="color: #004a9c;">学院</span></span></a>, 地点, 电话)。<br />
<br />
这样的数据库表是符合第三范式的，消除了数据冗余、更
新异常、插入异常和删除异常。<br />
<br />
鲍依斯-科得范式（BCNF）：在第三范式的基础上，数据库表中如果不存在任何字段对任一候选关键字段
的传递函数依赖则符合第三范式。
<p style="margin: 1em 0px 0.5em; padding: 0px;">　假设仓库管理关系表为
StorehouseManage(仓库ID, 存储物品ID, 管理员ID,
数量)，且有一个管理员只在一个仓库工作；一个仓库可以存储多种物品。这个数据库表中存在如下决定关系：<br />
<br />
(仓库ID,
存储物品ID) &#8594;(管理员ID, 数量)<br />
<br />
(管理员ID, 存储物品ID) &#8594; (仓库ID, 数量)<br />
<br />
所以，
(仓库ID, 存储物品ID)和(管理员ID,
存储物品ID)都是StorehouseManage的候选关键字，表中的唯一非关键字段为数量，它是符合第三范式的。但是，由于存在如下决定关系：<br />
<br />
(仓库ID) &#8594; (管理员ID)<br />
<br />
(管理员ID) &#8594; (仓库ID)<br />
<br />
即存在关键字段决定关键字段的情况，所以
其不符合BCNF范式。它会出现如下异常情况：<br />
<br />
(1) 删除异常：<br />
<br />
当仓库被清空后，所有"存储物品ID"和"数
量"信息被删除的同时，"仓库ID"和"管理员ID"信息也被删除了。<br />
<br />
(2) 插入异常：<br />
<br />
当仓库没有存储任何物
品时，无法给仓库分配管理员。<br />
<br />
(3) 更新异常：<br />
<br />
如果仓库换了管理员，则表中所有行的管理员ID都要修改。<br />
<br />
把仓库管理关系表分解为二个关系表：<br />
<br />
仓库管理：StorehouseManage(仓库ID, 管理员ID)；<br />
<br />
仓库：Storehouse(仓库ID, 存储物品ID, 数量)。<br />
<br />
这样的数据库表是符合BCNF范式的，消除了删除异常、插入异
常和更新异常。</p>
<p style="margin: 1em 0px 0.5em; padding: 0px;">范式应用<br />
<br />
我们来逐步搞定一个论
坛的数据库，有如下信息：<br />
<br />
（1） 用户：用户名，email，主页，电话，联系地址<br />
<br />
（2）
帖子：发帖标题，发帖内容，回复标题，回复内容&nbsp;<br />
<br />
第一次我们将数据库设计为仅仅存在表：</p>
<table align="center" border="1" cellpadding="2" cellspacing="0" width="90%">
    <tbody>
        <tr>
            <td>用户名</td>
            <td>email</td>
            <td>主页</td>
            <td>电话</td>
            <td>联系地址</td>
            <td>发帖标题</td>
            <td>发帖内容</td>
            <td>回复标题</td>
            <td>回复内容</td>
        </tr>
    </tbody>
</table>
<br />
这个数据库表符合第一范式，但是没有任何一组候选关键字能决定数据库表的整行，唯一的关键字段用户名也不能完全决定整个元组。我们需要增加"
发帖ID"、"回复ID"字段，即将表修改为：<br />
<br />
<table align="center" border="1" cellpadding="2" cellspacing="0" width="90%">
    <tbody>
        <tr>
            <td>用户名</td>
            <td>email</td>
            <td>主页</td>
            <td>电话</td>
            <td>联系地址</td>
            <td>发帖ID</td>
            <td>发帖标题</td>
            <td>发帖内容</td>
            <td>回复ID</td>
            <td>回复标题</td>
            <td>回复内容</td>
        </tr>
    </tbody>
</table>
<br />
这样数据表中的关键字(用户名，发帖ID，回复ID)能决定整行：<br />
<br />
(用户名,发帖ID,回复ID) &#8594;
(email,主页,电话,联系地址,发帖标题,发帖内容,回复标题,回复内容)<br />
<br />
但是，这样的设计不符合第二范式，因为存在如下决定
关系：<br />
<br />
(用户名) &#8594; (email,主页,电话,联系地址)<br />
<br />
(发帖ID) &#8594; (发帖标题,发帖内容)<br />
<br />
(回复ID) &#8594; (回复标题,回复内容)<br />
<br />
即非关键字段部分函数依赖于候选关键字段，很明显，这个设计会导致大量的数据冗余和操作
异常。&nbsp;
<table align="left" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td valign="top">&nbsp;</td>
        </tr>
        <tr>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
<br />
<br />
我们将数据库表分解为（带下划线的为关键字）：<br />
<br />
（1） 用户信息：用户名，email，主页，电话，联系地址<br />
<br />
（2） 帖子信息：发帖ID，标题，内容<br />
<br />
（3） 回复信息：回复ID，标题，内容<br />
<br />
（4）
发贴：用户名，发帖ID<br />
<br />
（5） 回复：发帖ID，回复ID<br />
<br />
这样的设计是满足第1、2、3范式和BCNF范式要求
的，但是这样的设计是不是最好的呢？<br />
<br />
不一定。<br />
<br />
观察可知，第4项"发帖"中的"用户名"和"发帖ID"之间是
1：N的关系，因此我们可以把"发帖"合并到第2项的"帖子信息"中；第5项"回复"中的"发帖ID"和"回复ID"之间也是1：N的关系，因此我们可以
把"回复"合并到第3项的"回复信息"中。这样可以一定量地减少数据冗余，新的设计为：<br />
<br />
（1）
用户信息：用户名，email，主页，电话，联系地址<br />
<br />
（2） 帖子信息：用户名，发帖ID，标题，内容<br />
<br />
（3）
回复信息：发帖ID，回复ID，标题，内容<br />
<br />
数据库表1显然满足所有范式的要求；<br />
<br />
数据库表2中存在非关键字段"标
题"、"内容"对关键字段"发帖ID"的部分函数依赖，即不满足第二范式的要求，但是这一设计并不会导致数据冗余和操作异常；<br />
<br />
数据库
表3中也存在非关键字段"标题"、"内容"对关键字段"回复ID"的部分函数依赖，也不满足第二范式的要求，但是与数据库表2相似，这一设计也不会导致数
据冗余和操作异常。<br />
<br />
由此可以看出，并不一定要强行满足范式的要求，对于1：N关系，当1的一边合并到N的那边后，N的那边就不再满足
第二范式了，但是这种设计反而比较好！<br />
<br />
对于M：N的关系，不能将M一边或N一边合并到另一边去，这样会导致不符合范式要求，同时导致
操作异常和数据冗余。&nbsp;<br />
对于1：1的关系，我们可以将左边的1或者右边的1合并到另一边去，设计导致不符合范式要求，但是并不会导致操作异常和数
据冗余。<br />
<br />
结论<br />
<br />
满足范式要求的数据库设计是结构清晰的，同时可避免数据冗余和操作异常。这并意味着不符合范式要求
的设计一定是错误的，在数据库表中存在1：1或1：N关系这种较特殊的情况下，合并导致的不符合范式要求反而是合理的。<br />
<br />
在我们设计数
据库的时候，一定要时刻考虑范式的要求。</span>
<img src ="http://www.blogjava.net/caizh2009/aggbug/325534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-07-08 11:13 <a href="http://www.blogjava.net/caizh2009/archive/2010/07/08/325534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面向海量服务的设计原则和策略总结</title><link>http://www.blogjava.net/caizh2009/archive/2010/05/28/322167.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 28 May 2010 10:20:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/05/28/322167.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/322167.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/05/28/322167.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/322167.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/322167.html</trackback:ping><description><![CDATA[互联网服务的特点就是面向海量级的用户，面向海量级的用户如何提供稳定的服务呢？这里，对这几年的一些经验积累和平时接触的一些理念做一个总结。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一、原则<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1．Web服务的CAP原理<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CAP指的是三个要素：一致性(Consistency)、可用性(Availability)、分区容忍性(Partition
tolerance)。CAP原理指的是这三个要素最多只能同时实现两点，不可能三者兼顾，对于海量级服务，一般这是一条常记心中的基准准则。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
如下是《<a href="http://newkadbbz.spaces.live.com/blog/cns%21B9B9D1C8892F9662%21524.entry" target="_blank">Web服务的CAP</a>
》关于CAP的定义：
<ul>
    <li>一致性：可以参考数据库的一致性。每次信息的读取都需要反映最新更新后的数据。 </li>
    <li>可用性：高可用性意味着每一次请求都可以成功完成并受到响应数据 </li>
    <li>分区宽容度：这个是容错机制的要求。一个服务需要在局部出错的情况下，没有出错的那部分被复制的数据分区仍然可以支持部分服务的操作，可以简单的
    理解为可以很容易的在线增减机器以达到更高的扩展性，即所谓的横向扩展能力。</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 面向海量级的分布式服务设计，基本上分区容忍性(Partition
tolerance)是第一要素，因此根据业务的情况，我们需要在一致性(Consistency)和可用性(Availability)之间做取舍。对
于一些业务，譬如支付宝或财付通，一致性会是第一考虑要素，即使是延迟的不一致也是不可接受的，这种时候只能牺牲可用性以保证一致性。对于一些应用，譬如
淘宝或拍拍交易中的评价信息，一般用户是可以接受延迟的一致性，这种时候可以优先考虑可用性，而用最终一致性来保证数据一致，譬如通过某种对帐机制。对于
一些应用，甚至一致性都并非要求，只需要保证差不多一致性即可，譬如Q-zone中的农场游戏中的偷菜。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据我们应用的业务需求，选择合适的一致性级别，以更好地保证系统的分区容忍性和可用性。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2．柔性可用<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
面向海量级的分布式服务设计，我们要意识到，一切都是不可靠的，在不可靠的环境的环境中构建可靠的应用，其中最重要的一点就是保持系统的柔性。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1）不可靠的环境<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
我们可能已经见惯一个远程服务提供不了服务了，运行一段时间后WebServer突然不响应了，数据库随着负载的不断增加再放上一条SQL语句就会垮掉。
但是，硬盘坏掉、电源断掉、光纤中断，听起来似乎多么不可思议，然而，当一个海量服务需要成千上万台服务器、需要部署全国各地的数十个数据中心、需要横跨
电信网通教育网三大网络的时候，一切听起来不可思议的事情会变成常态。一切都是不可靠的，唯一可靠的就是不可靠本身。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）划分服务级别<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
我们应该意识到，在这种不可靠的环境中提供完美的服务，本身就是一个神话，即使不是说完全不可能，但至少是代价高昂的，因此，当某些问题发生（环境变地不
可靠的时候），我们必须做出取舍，选择为用户提供用户最关心的服务，这种服务虽然听起来是有损的（至少是不完美的），但却能在一定程度上满足用户大部分的
需求。譬如，当网络带宽无法为用户提供最好的体验而扩容又不是短期可以达到的时候，选择降低一些非重要服务的体验是一个比较好的选择。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在面向海量互联网的设计当中，对服务进行分级，当系统变地不可靠的时候，优先提供重要优先级的服务。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）尽快响应<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
互联网用户的耐心是非常有限的，如果一个页面需要3秒以上才能看到，也许大部分用户的第一选择就是关掉浏览器。在构建柔性可用的互联网服务的时候，响应时
间大部分情况下都是需要最优先考虑。还是一句话，环境是不可靠的，当我们无法尽快从远程服务获得数据、当数据库已经慢如蜗牛，也许当后台还在吭哧吭哧干活
的时候，用户老早已经关闭了页面，处理返回的数据也只是在浪费表情，面向互联网用户，响应就是生命。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 二、策略<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何让我们的应用提供更高质量的服务呢，这里是一些在日常开发使用到或者观察到的一些策略的总结：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1．数据sharding<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
海量服务相应也意味着海量的用户和海量的用户数据，大家都知道，即使是再强大的数据库、再强大服务器，在单表上亿规模的数据足够让一条简单的SQL语句慢
如蜗牛（甚至于在百万、千万级别上，如果没有采取合适的策略，都无法满足服务要求），一般处理这种千万上亿级数据的大家基本上都会想到的就是数据
sharding，将数据切割成多个数据集，分散到多个数据库的多个表中（譬如将用户数据按用户ID切割成4个数据库每个数据库100个表共400个
表），由于每个表数据足够小可以让我们的SQL语句快速地执行。而至于如何切割，实际上跟具体的业务策略有关系。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
当然，我们要认识到，这种数据sharding并非全无代价的，这也意味着我们需要做出一些折中，譬如可能很难进行跨表数据集的查询、联表和排序也变地非
常困难、同时数据库client程序编写也会变地更加复杂、保证数据一致性在某些情况下会变地困难重重。sharding并非万能药，选择是否
sharding、如何sharding、为sharding如何换用一个近似的业务描述方式，这是业务设计需要仔细考虑的问题。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2．Cache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
经验会告诉我们，基本上大部分系统的瓶颈会集中在IO/数据库上，常识也告诉我们，网络和内存的速度比IO/数据库会提升甚至不止一个数量级。面向海量服
务，Cache基本上是一个必选项，分布式Cache更是一个不二选择，根据我们的需要，我们可以选择memcached（非持久化）、
memcachedb/Tokyo Tyrant（持久化），甚至构建自己的cache平台。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在使用Cache上，下面是需要仔细考虑的点：</p>
<ul>
    <li>选择合适的Cache分布算法，基本上我们会发现使用取模方式决定Cache位置是不可靠的，因为坏节点的摘除或者节点扩量会让我们的Cache
    命中率在短时间内下降到冰点，甚至会导致系统在短期内的负载迅速增长甚至于崩溃，选择一种合适的分布算法非常重要，譬如稳定的一致性哈希</li>
    <li>Cache管理：为每个应用配置独立的Cache通常不是一个好主意，我们可以选择在大量的机器上，只要有空闲内存，则运行Cache实例，将
    Cache实例分成多个组，每个组就是一个完整的Cache池，而多个应用共享一个Cache池</li>
    <li>合理的序列化格式：使用紧凑的序列化方案存储Cache数据，尽量少存储冗余数据，一方面可以最大能力地榨取Cache的存储利用率，另一方面，
    可以更方便地进行容量预估。此外，不可避免地，随着业务的升级，存储的数据的格式有可能会变更，序列化也需要注意向上兼容的问题，让新格式的客户端能够支
    持旧的数据格式。</li>
    <li>容量估算：在开始运行之前，先为自己的应用可能使用到的容量做一个容量预估，以合理地分配合适的Cache池，同时为可能的容量扩充提供参考。</li>
    <li>容量监控：Cache命中率怎么样，Cache的存储饱和度怎么样，Client的Socket连接数等等，对这些数据的采集和监控，将为业务的
    调整和容量的扩充提供了数据支持。</li>
    <li>选择在哪层上进行Cache，譬如数据层Cache、应用层Cache和Web层Cache，越靠近数据，Cache的通用性越高，越容易保持
    Cache数据的一致性，但相应的处理流程也越长，而越靠近用户，Cache的通用性越差，越难保证Cache数据的一致性，但是响应也越快，根据业务的
    特点，选择合适的Cache层是非常重要的。一般而言，我们会选择将粗粒度、极少变更、数据对用户不敏感（即可以一定程度上接受误差）、并且非针对用户级
    的数据，在最靠近用户的层面上Cache，譬如图片Cache、TOP
    X等数据；而将一些细粒度、变更相对频繁、用户相对敏感的数据或者是针对用户级的数据放在靠近数据的一段，譬如用户的Profile、关系链等。</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3．服务集群<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 面向海量服务，系统的横向扩展基本上是第一要素，在我的经验和经历中，服务集群需要考虑如下因素：</p>
<ul>
    <li>分层：合理地对系统进行分层，将系统资源要求不同的部分进行合理地逻辑/物理分层，一般对于简单业务，Client层、WebServer层和
    DB层已经足够，对于更复杂业务，可能要切分成Client层、WebServer层、业务层、数据访问层（业务层和数据访问层一般倾向于在物理上处于同
    一层）、数据存储层（DB），太多的分层会导致处理流程变长，但相应系统地灵活性和部署性会更强。</li>
    <li>功能细粒度化：将功能进行细粒度的划分，并使用独立的进程部署，一方面能更有利于错误的隔离，另一方面在功能变更的时候避免一个功能对其他功能产
    生影响</li>
    <li>按数据集部署：如果每一层都允许对下一层所有的服务接口进行访问，将存在几个严重的缺陷，一是随着部署服务的增长，会发现下一层必须允许数量非常
    庞大的Socket连接进来，二是我们可能必须把不同的服务部署在不同的数据中心(DC)的不同机房上，即便是上G的光纤专线，机房间的穿梭流量也会变地
    不可接受，三是每个服务节点都是全数据容量接入，并不利于做一些有效的内部优化机制，四是只能采用代码级控制的灰度发布和部署。当部署规模达到一定数量级
    的时候，按数据集横向切割成多组服务集合，每组服务集合只为特定的数据集服务，在部署上，每组服务集合可以部署在独立的相同的数据中心(DC)上。</li>
    <li>无状态：状态将为系统的横向扩容带来无穷尽的烦恼。对于状态信息比少的情况，可以选择将全部状态信息放在请求发器端，对于状态信息比较多的情况，
    可以考虑维持一个统一的Session中心。</li>
    <li>选择合适的负载均衡器和负载均衡策略：譬如在L4上负载均衡的LVS、L7上负载均衡的Nginx、甚至是专用的负载均衡硬件F5（L4），对于
    在L7上工作的负载均衡器，选择合适的负载均衡策略也非常重要，一般让用户总是负载均衡到同一台后端Server是一个很好的方式</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4．灰度发布<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
当系统的用户增长到一定的规模，一个小小功能的发布也会产生非常大的影响，这个时候，将功能先对一小部分用户开放，并慢慢扩展到全量用户是一个稳妥的做
法，使用灰度化的发布将避免功能的BUG产生大面积的错误。如下是一些常见的灰度控制策略：</p>
<ul>
    <li>白名单控制：只有白名单上的用户才允许访问，一般用于全新功能Alpha阶段，只向被邀请的用户开放功能</li>
    <li>准入门槛控制：常见的譬如gmail出来之初的邀请码、QQ农场开始阶段的X级的黄钻准入，同样一般用于新功能的Beta阶段，慢慢通过一步一步
    降低门槛，避免在开始之处由于系统可能潜在的问题或者容量无法支撑导致整个系统的崩溃。</li>
    <li>按数据集开放：一般常用于成熟的功能的新功能开发，避免新功能的错误产生大面积的影响</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5．设计自己的通信协议：二进制协议、向上/下兼容<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
随着系统的稳定运行访问量的上涨，慢慢会发现，一些看起来工作良好的协议性能变地不可接受，譬如基于xml的协议xml-rpc，将会发现xml解析和包
体的增大变地不可接受，即便是接近于二进制的hessian协议，多出来的字段描述信息(按我的理解，hessian协议是类似于map结构的，包含字段
的名称信息)和基于文本的http头将会使协议效率变地低下。也许，在开始合适的时候而不是到最后不得已的时候，去设计一个良好的基于二进制的高效的内部
通信协议是一个好的方式。按我的经验，设计自己的通信协议需要注意如下几点：</p>
<ul>
    <li>协议紧凑性，否则早晚你会为你浪费的空间痛心疾首</li>
    <li>协议扩展性，早晚会发现旧的协议格式不能适应新的业务需求，而在早期预留变地非常地重要，基本上，参见一些常用的规范，魔术数（对于无效果的请求
    可以迅速丢弃）、协议版本信息、协议头、协议Body、每个部分（包括结构体信息中的对象）的长度这些信息是不能省的</li>
    <li>向下兼容和向上兼容：但功能被大规模地调用的时候，发布一个新的版本，让所有的client同时升级基本上是不可接受的，因此在设计之处就需要考
    虑好兼容性的问题</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6．设计自己的Application Server<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 事情进行到需要自己设计通信协议，自己构建Application Server也变地顺理成章，下面是在自己开发Application
Server的时候需要处理的常见的问题：</p>
<ul>
    <li>过载保护：当系统的某个部件出现问题的时候，最常见的情况是整个系统的负载出现爆炸性的增长而导致雪崩效应，在设计application
    server的时候，必须注意进行系统的过载保护，当请求可以预期无法处理的时候(譬如排队满载或者排队时间过长)，丢弃是一个明智的选择，TCP的
    backlog参数是一个典型的范例。</li>
    <li>频率控制：即便是同一系统中的其他应用在调用，一个糟糕的程序可能会将服务的所有资源占完，因此，应用端必须对此做防范措施，频率控制是其中比较
    重要的一个</li>
    <li>异步化/无响应返回：对于一些业务，只需要保证请求会被处理即可，客户端并不关心什么时候处理完，只要最终保证处理就行，甚至最终没有处理也不是
    很严重的事情，譬如邮件，对于这种应用，应快速响应避免占着宝贵的连接资源，而将请求进入异步处理队列慢慢处理。</li>
    <li>自我监控：Application
    Server本身应该具备自我监控的功能，譬如性能数据采集、为外部提供内部状态的查询（譬如排队情况、处理线程、等待线程）等</li>
    <li>预警：譬如当处理变慢、排队太多、发生请求丢弃的情况、并发请求太多的时候，Application
    Server应该具备预警的能力以快速地对问题进行处理</li>
    <li>模块化、模块间松耦合、机制和策略分离：如果不想一下子面对所有的复杂性或不希望在修改小部分而不得不对所有的测试进行回归的话，模块化是一个很
    好的选择，将问题进行模块切割，每个模块保持合理的复杂度，譬如对于这里的Application
    Server，可以切分成请求接收/管理/响应、协议解析、业务处理、数据采集、监控和预警等等模块。这里同时要注意块间使用松耦合的方式交互，譬如，请
    求接收和业务处理之间则可以使用阻塞队列通信的方式降低耦合。另外还需要注意的是机制和策略的分离，譬如协议可能会变更、性能采集和告警的方式可能会变化
    等等，事先的机制和策略分离，策略变更的处理将变地更加简单。</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7．Client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 很多应用会作为服务的Client，去调用其他的服务，如下是在做为Client应该注意的一些问题：</p>
<ul>
    <li>服务不可靠：作为Client永远要记住的一点就是，远程服务永远是不可靠的，因此作为Client自己要注意做自我保护，当远程服务如果无法访
    问时，做折中处理</li>
    <li>超时保护：还是上面所说的，远程服务永远都是不可靠的，永远也无法预测到远程什么时候会响应，甚至可能不会响应（譬如远程主机宕机），请求方要做
    好超时保护，譬如对于主机不可达的情况，在linux环境下，有时会让客户端等上几分钟TCP层才会最终告诉你服务不可到达。</li>
    <li>并发/异步：为了提速响应，对于很多可以并行获取的数据，我们总是应该并行地去获取，对于一些我们无法控制的同步接口——譬如读数据库或同步读
    cache——虽然不是很完美，但多线程并行去获取是一个可用的选择，而对于服务端都是使用自构建的Application
    Server，使用异步Client接口至关重要，将请求全部发送出去，使用异步IO设置超时等待返回即可，甚至于更进一步异步anywhere，在将
    client与application
    server整合到一块的时候，请求发送出去之后立即返回，将线程/进程资源归还，而在请求响应回来符合条件的时候，触发回调做后续处理。</li>
</ul>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8．监控和预警<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
基本上我们会见惯了各种网络设备或服务器的监控，譬如网络流量、IO、CPU、内存等监控数据，然而除了这些总体的运行数据，应用的细粒度化的数据也需要
被监控，服务的访问压力怎么样、处理速度怎么样、性能瓶颈在哪里、带宽主要是被什么应用占、Java虚拟机的CPU占用情况怎么样、各内存区的内存占用情
况如何，这些数据将有利于我们更好的了解系统的运行情况，并对系统的优化和扩容提供数据指导。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
除了应用总体监控，特定业务的监控也是一个可选项，譬如定时检查每个业务的每个具体功能点(url)访问是否正常、访问速度如何、页面访问速度如何（用户
角度，包括服务响应时间、页面渲染时间等，即网页测速）、每个页面的PV、每个页面（特别是图片）每天占用的总带宽等等。这些数据将为系统预警和优化提供
数据上的支持，例如对于图片，如果我们知道哪些图片占用的带宽非常大（不一定是图片本身比较大，而可能是访问比较大），则一个小小的优化会节省大量的网络
带宽开销，当然，这些事情对于小规模的访问是没有意义的，网络带宽开销节省的成本可能都没有人力成本高。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
除了监控，有效的预警机制也是必不可少，应用是否在很好地提供服务、响应时间是否能够达到要求、系统容量是否达到一个阀值。有效的预警机制将让我们尽快地
对问题进行处理。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9．配置中心化<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
当系统错误的时候，我们如何尽快地恢复呢，当新增服务节点的时候，如何尽快地让真个系统感知到呢？当系统膨胀之后，如果每次摘除服务节点或者新增节点都需
要修改每台应用配置，那么配置和系统的维护将变地越来越困难。<br />
&nbsp;&nbsp;&nbsp;&nbsp;
配置中心化是一个很好的处理这个问题的方案，将所有配置进行统一地存储，而当发生变更的时候（摘除问题节点或者扩量增加服务节点或新增服务），使用一些通
知机制让各应用刷新配置。甚至于，我们可以自动地检测出问题节点并进行智能化的切换。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 三、最后<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
构建面向海量用户的服务，可以说是困难重重挑战重重，一些原则和前人的设计思路可以让我们获得一些帮助，但是更大的挑战会来源于细节部分，按我们技术老大
的说法，原则和思路只要看几本书是个技术人员都会，但决定一个系统架构师能力的，往往却是对细节的处理能力。因此，在掌握原则和前人的设计思路的基础上，
更深入地挖掘技术的细节，才是面向海量用户的服务的制胜之道。</p>
<img src ="http://www.blogjava.net/caizh2009/aggbug/322167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-05-28 18:20 <a href="http://www.blogjava.net/caizh2009/archive/2010/05/28/322167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 位运算</title><link>http://www.blogjava.net/caizh2009/archive/2010/05/18/321248.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 18 May 2010 04:02:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/05/18/321248.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/321248.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/05/18/321248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/321248.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/321248.html</trackback:ping><description><![CDATA[前不久做的一个笔记本BIOS相关的项目，操作对BOIS文件里面的内容时进行较多的位运算，于是顺手整理了一份位运算相关的内容。 <br />
&nbsp;&nbsp; Java 定义的位运算（bitwise operators
）直接对整数类型的位进行操作，这些整数类型包括long，int，short，char，and byte 。<br />
&nbsp;&nbsp; 所有的整数类型（除了char 类型之外）都是有符号的整数。这意味着他们既能表示正数，又能表示负数。Java 使用采用补码来表示负数。<br />
&nbsp;&nbsp; 为什么采用补码吗？这是考虑到零的交叉（zero crossing ）问题。<br />
&nbsp;&nbsp; 原码：<br />
&nbsp;&nbsp;
将最高位作为符号位（以0代表正，1代表负），其余各位代表数值本身的绝对值（以二进制表示）。这个时候有一个问题：表示0的时候正0和负0表示并不一
样，所以在计算机中没有采用原码的表示形式。<br />
&nbsp;&nbsp; 反码：<br />
&nbsp;&nbsp;
一个数如果为正，则它的反码与原码相同；一个数如果为负，则符号位为1，其余各位是对原码取反。问题和上面一样的。所以，计算机中也没有采用反码来表示数
字。<br />
&nbsp;&nbsp; 补码：<br />
&nbsp;&nbsp;
一个数如果为正，则它的原码、反码、补码相同；一个数如果为负，则符号位为1，其余各位是对原码取反，然后再加1。也就是通过将与其对应的正数的二进制代
码取反（即将1变成0，将0变成1），然后对其结果加1。例如，-42就是通过将42的二进制代码的各个位取反，即对00101010
取反得到11010101 ，然后再加1，得到11010110 ，即-42
。要对一个负数解码，首先对其所有的位取反，然后加1。例如-42，或11010110 取反后为00101001
，或41，然后加1，这样就得到了42。<br />
&nbsp;&nbsp; 在计算机中，如果我们用1个字节表示一个数，一个字节有8位，超过8位就进1，在内存中情况为：1
00000000。进位1被丢弃。这种情况，我们叫溢出。在计算机中，假定byte 类型的值零为0000 0000,反码为1111 1111
补码为1 0000 0000,在计算-0的补码的时候因为溢出，导致-0和+0是一样的表示，所以计算机中采用补码的形式表示数字。<br />
数的最大值和最小值:由于最高位为符号位,所以最大值和最小值时要去掉最高位。如一个byte为8位.最大值为0111 1111 ，即<span> (2的7次方)
</span>
-1 = 127.最小值为1000 0000，即-<span style="font-size: 12pt; font-family: 'Times New Roman';">( 2的7次方)
</span>
=-128。char为无符号数,没有符号位,所以最小值为0,最大值为1111 1111 1111 1111 ，即(<span style="font-family: Times New Roman;">2的16次方)</span>
-1。<br />
<br />
移位运算符<br />
包括：<br />
&#8220;&gt;&gt; 右移,高位补符号位&#8221;；<br />
&#8220;&gt;&gt;&gt; 无符号右移,高位补0&#8221;；<br />
&#8220;&lt;&lt; 左移&#8221;；<br />
<br />
例子：<br />
-5&gt;&gt;3=-1<br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
1111 1111 1111 1111 1111 1111 1111 1111<br />
其结果与 Math.floor((double)-5/(2*2*2)) 完全相同。<br />
<br />
-5&lt;&lt;3=-40<br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
1111 1111 1111 1111 1111 1111 1101 1000<br />
其结果与 -5*2*2*2 完全相同。<br />
<br />
5&gt;&gt;3=0<br />
0000 0000 0000 0000 0000 0000 0000 0101<br />
0000 0000 0000 0000 0000 0000 0000 0000<br />
其结果与 5/(2*2*2) 完全相同。<br />
<br />
5&lt;&lt;3=40<br />
0000 0000 0000 0000 0000 0000 0000 0101<br />
0000 0000 0000 0000 0000 0000 0010 1000<br />
其结果与 5*2*2*2 完全相同。<br />
<br />
-5&gt;&gt;&gt;3=536870911 <br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
0001 1111 1111 1111 1111 1111 1111 1111<br />
<br />
无论正数、负数，它们的右移、左移、无符号右移 32 位都是其本身，比如
-5&lt;&lt;32=-5、-5&gt;&gt;32=-5、-5&gt;&gt;&gt;32=-5。<br />
一个有趣的现象是，把 1 左移 31 位再右移 31 位，其结果为 -1。<br />
0000 0000 0000 0000 0000 0000 0000 0001<br />
1000 0000 0000 0000 0000 0000 0000 0000<br />
1111 1111 1111 1111 1111 1111 1111 1111<br />
<br />
位逻辑运算符<br />
包括：<br />
&amp; 与；<br />
| 或；<br />
~ 非（也叫做求反）；<br />
^ 异或<br />
<br />
&#8220;&amp; 与&#8221;、&#8220;| 或&#8221;、&#8220;~ 非&#8221;是基本逻辑运算，由此可以演变出&#8220;与非&#8221;、&#8220;或非&#8221;、&#8220;与或非&#8221;复合逻辑运算。&#8220;^
异或&#8221;是一种特殊的逻辑运算，对它求反可以得到&#8220;同或&#8221;，所以&#8220;同或&#8221;逻辑也叫&#8220;异或非&#8221;逻辑。<br />
<br />
例子：<br />
5&amp;3=1<br />
0000 0000 0000 0000 0000 0000 0000 0101<br />
0000 0000 0000 0000 0000 0000 0000 0011<br />
0000 0000 0000 0000 0000 0000 0000 0001<br />
<br />
-5&amp;3=1<br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
0000 0000 0000 0000 0000 0000 0000 0011<br />
0000 0000 0000 0000 0000 0000 0000 0011<br />
<br />
5|3=7<br />
0000 0000 0000 0000 0000 0000 0000 0101<br />
0000 0000 0000 0000 0000 0000 0000 0011<br />
0000 0000 0000 0000 0000 0000 0000 0111<br />
<br />
-5|3=-5<br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
0000 0000 0000 0000 0000 0000 0000 0011<br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
<br />
~5=-6<br />
0000 0000 0000 0000 0000 0000 0000 0101<br />
1111 1111 1111 1111 1111 1111 1111 1010<br />
<br />
~-5=4<br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
0000 0000 0000 0000 0000 0000 0000 0100<br />
<br />
5^3=6<br />
0000 0000 0000 0000 0000 0000 0000 0101<br />
0000 0000 0000 0000 0000 0000 0000 0011<br />
0000 0000 0000 0000 0000 0000 0000 0110<br />
<br />
-5^3=-8<br />
1111 1111 1111 1111 1111 1111 1111 1011<br />
0000 0000 0000 0000 0000 0000 0000 0011<br />
1111 1111 1111 1111 1111 1111 1111 1000<br />
<br />
参考:<br />
http://blog.csdn.net/zdmilan/archive/2005/10/30/519634.aspx
<img src ="http://www.blogjava.net/caizh2009/aggbug/321248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-05-18 12:02 <a href="http://www.blogjava.net/caizh2009/archive/2010/05/18/321248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Web服务器和应用服务器的区别</title><link>http://www.blogjava.net/caizh2009/archive/2010/05/14/320952.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 14 May 2010 02:19:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/05/14/320952.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/320952.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/05/14/320952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/320952.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/320952.html</trackback:ping><description><![CDATA[应用程序服务器通过各种协议，可以包括HTTP，把商业逻辑暴露给客户端应用程序。Web服务器主要是处理向浏览器发送HTML以供浏览，而应用程序服务
器提供访问商业逻辑的途径以供客户端应用程序使用。应用程序使用此商业逻辑就象你调用对象的一个方法一样。<br />
通俗的讲，Web服务器传送(serves)页面使浏览器可以浏览，然而应用程序服务器提供的是客户端应用程序可以调用(call)的方法
(methods)。确切一点，你可以说：Web服务器专门处理HTTP请求(request)，但是应用程序服务器是通过很多协议来为应用程序提供
(serves)商业逻辑(business logic)。 <br />
<br />
下面让我们来细细道来： <br />
<br />
<strong>Web服务器
(Web Server) </strong>
<p>Web服务器可以解析(handles)HTTP协议。当Web服务器接收到一个HTTP请求(request)，会返回一个HTTP响应
(response)，例如送回一个HTML页面。为了处理一个请求(request)，Web服务器可以响应(response)一个静态页面或图片，
进行页面跳转(redirect)，或者把动态响应(dynamic
response)的产生委托(delegate)给一些其它的程序例如CGI脚本，JSP(JavaServer
Pages)脚本，servlets，ASP(Active Server
Pages)脚本，服务器端(server-side)JavaScript，或者一些其它的服务器端(server-side)技术。无论它们(译者
注：脚本)的目的如何，这些服务器端(server-side)的程序通常产生一个HTML的响应(response)来让浏览器可以浏览。 <br />
<br />
要知道，Web服务器的代理模型(delegation
model)非常简单。当一个请求(request)被送到Web服务器里来时，它只单纯的把请求(request)传递给可以很好的处理请求
(request)的程序(译者注：服务器端脚本)。Web服务器仅仅提供一个可以执行服务器端(server-side)程序和返回(程序所产生的)响
应(response)的环境，而不会超出职能范围。服务器端(server-side)程序通常具有事务处理(transaction
processing)，数据库连接(database connectivity)和消息(messaging)等功能。 <br />
<br />
虽然
Web服务器不支持事务处理或数据库连接池，但它可以配置(employ)各种策略(strategies)来实现容错性(fault
tolerance)和可扩展性(scalability)，例如负载平衡(load
balancing)，缓冲(caching)。集群特征(clustering—features)经常被误认为仅仅是应用程序服务器专有的特征。 <br />
<br />
<strong>应用程序服务器(The Application Server) </strong><br />
根据我们的定义，作为应用程序服务器，
它通过各种协议，可以包括HTTP，把商业逻辑暴露给(expose)客户端应用程序。Web服务器主要是处理向浏览器发送HTML以供浏览，而应用程序
服务器提供访问商业逻辑的途径以供客户端应用程序使用。应用程序使用此商业逻辑就象你调用对象的一个方法(或过程语言中的一个函数)一样。 <br />
<br />
应用程序服务器的客户端(包含有图形用户界面(GUI)的)可能会运行在一台PC、一个Web服务器或者甚至是其它的应用程序服务器上。在应用程序服务
器与其客户端之间来回穿梭(traveling)的信息不仅仅局限于简单的显示标记。相反，这种信息就是程序逻辑(program logic)。
正是由于这种逻辑取得了(takes)数据和方法调用(calls)的形式而不是静态HTML，所以客户端才可以随心所欲的使用这种被暴露的商业逻辑。 <br />
<br />
在大多数情形下，应用程序服务器是通过组件(component)的应用程序接口(API)把商业逻辑暴露(expose)(给客户端应用程序)的，例
如基于J2EE(Java 2 Platform, Enterprise Edition)应用程序服务器的EJB(Enterprise
JavaBean)组件模型。此外，应用程序服务器可以管理自己的资源，例如看大门的工作(gate-keeping
duties)包括安全(security)，事务处理(transaction processing)，资源池(resource
pooling)，
和消息(messaging)。就象Web服务器一样，应用程序服务器配置了多种可扩展(scalability)和容错(fault
tolerance)技术。 <br />
<br />
一个例子 <br />
例如，设想一个在线商店(网站)提供实时定价(real-time
pricing)和有效性(availability)信息。这个站点(site)很可能会提供一个表单(form)让你来选择产品。当你提交查询
(query)后，网站会进行查找(lookup)并把结果内嵌在HTML页面中返回。网站可以有很多种方式来实现这种功能。我要介绍一个不使用应用程序
服务器的情景和一个使用应用程序服务器的情景。观察一下这两中情景的不同会有助于你了解应用程序服务器的功能。 <br />
<br />
<strong>情景
1：不带应用程序服务器的Web服务器 </strong><br />
<br />
在此种情景下，一个Web服务器独立提供在线商店的功能。Web服务器获
得你的请求(request)，然后发送给服务器端(server-side)可以处理请求(request)的程序。此程序从数据库或文本文件
(flat file，译者注：flat
file是指没有特殊格式的非二进制的文件，如properties和XML文件等)中查找定价信息。一旦找到，服务器端(server-side)程序
把结果信息表示成(formulate)HTML形式，最后Web服务器把会它发送到你的Web浏览器。 <br />
<br />
简而言之，Web服务器只是简
单的通过响应(response)HTML页面来处理HTTP请求(request)。 <br />
<br />
<strong>情景2：带应用程序服务器的
Web服务器 </strong><br />
<br />
情景2和情景1相同的是Web服务器还是把响应(response)的产生委托
(delegates)给脚本(译者注：服务器端(server-side)程序)。然而，你可以把查找定价的商业逻辑(business
logic)放到应用程序服务器上。由于这种变化，此脚本只是简单的调用应用程序服务器的查找服务(lookup
service)，而不是已经知道如何查找数据然后表示为(formulate)一个响应(response)。
这时当该脚本程序产生HTML响应(response)时就可以使用该服务的返回结果了。 <br />
<br />
在此情景中，应用程序服务器提供
(serves)了用于查询产品的定价信息的商业逻辑。(服务器的)这种功能(functionality)没有指出有关显示和客户端如何使用此信息的细
节，相反客户端和应用程序服务器只是来回传送数据。当有客户端调用应用程序服务器的查找服务(lookup
service)时，此服务只是简单的查找并返回结果给客户端。 <br />
<br />
通过从响应产生(response-generating)HTML的
代码中分离出来，在应用程序之中该定价(查找)逻辑的可重用性更强了。其他的客户端，例如收款机，也可以调用同样的服务(service)来作为一个店员
给客户结帐。相反，在情景1中的定价查找服务是不可重用的因为信息内嵌在HTML页中了。 <br />
<br />
总而言之，在情景2的模型中，在Web服务器
通过回应HTML页面来处理HTTP请求(request)，而应用程序服务器则是通过处理定价和有效性(availability)请求
(request)来提供应用程序逻辑的。 <br />
<br />
警告(Caveats) <br />
现在，XML Web
Services已经使应用程序服务器和Web服务器的界线混淆了。通过传送一个XML有效载荷(payload)给服务器，Web服务器现在可以处理数
据和响应(response)的能力与以前的应用程序服务器同样多了。 <br />
<br />
另外，现在大多数应用程序服务器也包含了Web服务器，这就意味
着可以把Web服务器当作是应用程序服务器的一个子集(subset)。虽然应用程序服务器包含了Web服务器的功能，但是开发者很少把应用程序服务器部
署(deploy)成这种功能(capacity)(译者注：这种功能是指既有应用程序服务器的功能又有Web服务器的功能)。相反，如果需要，他们通常
会把Web服务器独立配置，和应用程序服务器一前一后。这种功能的分离有助于提高性能(简单的Web请求(request)就不会影响应用程序服务器
了)，分开配置(专门的Web服务器，集群(clustering)等等)，而且给最佳产品的选取留有余地。</p>
<br />
<img src ="http://www.blogjava.net/caizh2009/aggbug/320952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-05-14 10:19 <a href="http://www.blogjava.net/caizh2009/archive/2010/05/14/320952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTPS和HTTP的区别</title><link>http://www.blogjava.net/caizh2009/archive/2010/05/13/320770.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 13 May 2010 01:37:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/05/13/320770.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/320770.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/05/13/320770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/320770.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/320770.html</trackback:ping><description><![CDATA[HTTPS（Secure Hypertext Transfer Protocol）安全超文本传输协议 <br />
它是一个安全通信通道，它基于HTTP开发，用于在客户计算机和服务器之间交换信息。它使用安全套接字层(SSL)进行信息交换，简单来说它是HTTP的
安全版。 <br />
它是由Netscape开发并内置于其浏览器中，用于对数据进行压缩和解压操作，并返回网络上传送回的结果。HTTPS实际上应用了Netscape的安
全全套接字层（SSL）作为HTTP应用层的子层。（HTTPS使用端口443，而不是象HTTP那样使用端口80来和TCP/IP进行通信。）SSL使
用40
位关键字作为RC4流加密算法，这对于商业信息的加密是合适的。HTTPS和SSL支持使用X.509数字认证，如果需要的话用户可以确认发送者是谁。 <br />
HTTPS和HTTP的区别： <br />
https协议需要到ca申请证书，一般免费证书很少，需要交费。 <br />
http是超文本传输协议，信息是明文传输，https 则是具有安全性的ssl加密传输协议 <br />
http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。 <br />
http的连接很简单,是无状态的 <br />
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全 <br />
HTTPS解决的问题： <br />
1 . 信任主机的问题. 采用https 的server 必须从CA 申请一个用于证明服务器用途类型的证书. 改证书只有用于对应的server
的时候,客户度才信任次主机. 所以目前所有的银行系统网站,关键部分应用都是https 的. 客户通过信任该证书,从而信任了该主机.
其实这样做效率很低,但是银行更侧重安全. 这一点对我们没有任何意义,我们的server ,采用的证书不管自己issue
还是从公众的地方issue, 客户端都是自己人,所以我们也就肯定信任该server. <br />
2 . 通讯过程中的数据的泄密和被窜改 <br />
1. 一般意义上的https, 就是 server 有一个证书. <br />
a) 主要目的是保证server 就是他声称的server. 这个跟第一点一样. <br />
b) 服务端和客户端之间的所有通讯,都是加密的. <br />
i. 具体讲,是客户端产生一个对称的密钥,通过server 的证书来交换密钥. 一般意义上的握手过程. <br />
ii. 加下来所有的信息往来就都是加密的. 第三方即使截获,也没有任何意义.因为他没有密钥. 当然窜改也就没有什么意义了. <br />
2. 少许对客户端有要求的情况下,会要求客户端也必须有一个证书. <br />
a) 这里客户端证书,其实就类似表示个人信息的时候,除了用户名/密码, 还有一个CA 认证过的身份.
应为个人证书一般来说上别人无法模拟的,所有这样能够更深的确认自己的身份. <br />
b) 目前少数个人银行的专业版是这种做法,具体证书可能是拿U盘作为一个备份的载体. <br />
HTTPS 一定是繁琐的. <br />
a) 本来简单的http协议,一个get一个response. 由于https 要还密钥和确认加密算法的需要.单握手就需要6/7 个往返. <br />
i. 任何应用中,过多的round trip 肯定影响性能. <br />
b) 接下来才是具体的http协议,每一次响应或者请求, 都要求客户端和服务端对会话的内容做加密/解密. <br />
i. 尽管对称加密/解密效率比较高,可是仍然要消耗过多的CPU,为此有专门的SSL 芯片. 如果CPU
信能比较低的话,肯定会降低性能,从而不能serve 更多的请求. <br />
ii. 加密后数据量的影响. 所以，才会出现那么多的安全认证提示
<img src ="http://www.blogjava.net/caizh2009/aggbug/320770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-05-13 09:37 <a href="http://www.blogjava.net/caizh2009/archive/2010/05/13/320770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ava线程安全同步解决方案（淘宝面试题）</title><link>http://www.blogjava.net/caizh2009/archive/2010/05/11/320556.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Tue, 11 May 2010 01:49:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/05/11/320556.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/320556.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/05/11/320556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/320556.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/320556.html</trackback:ping><description><![CDATA[<p>早早就听说过开发方向的笔试面试都是以算法和数据结构这些基础为主，我自恃着那么一丁点项目经验，一直没放在心上。</p>
<p>连日下来的笔试彻底印证了师兄们的话，笔试基本不过。最可惜的是淘宝，笔试中发挥不错终于能进一面，一开始聊家常聊框架聊开源技术还聊得不错，突然
间，连续问了三个问题：</p>
<p>1.多线程访问hashtable和hashmap有什么不一样？我只答出线程安全不一样，具体怎么不一样就有一句每一句了（回来google一
下，这种java基础还真TM简单，枉称精通java了）</p>
<p>2.平衡二叉树查找算法的复杂度？再次雷响，随便蒙了个归并排序的复杂度给他。</p>
<p>3.对于100W条数据的排序和查找有什么效率高的方式？完了，结结巴巴的说一通，最后自认不会&#8230;&#8230;</p>
<p>原本以为技术面会比笔试好过的，回学校的路上我泪流满面啊我。这些都不是RP问题了，铁了心恶补数据结构&#8230;&#8230;</p>
<p><strong><span style="font-size: small;">Java线
程安全同步解决方案</span></strong>&nbsp;</p>
<p><span style="font-family: Arial;">1、&nbsp;问题描述：</span></p>
<p><span style="font-family: Arial;">　　如果一个资源或对象可能被多个线程同时访问，它就是一个共享资源；例如
类的成员变量，包括类变量和实例变量，再比如对一个文件进行写操作等。一般情况下，对共享资源的访问需要考虑线程安全的问题。</span></p>
<p><span style="font-family: Arial;">　　如果一个对象的完整生命周期只在一个线程内，则不需要考虑线程安全，例
如一个局部变量。下面为一个示例代码：</span></p>
<div>
<ol>
    <li>public class C1 { </li>
    <li>public static <span>java.text.SimpleDateFormat
    sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
    </span></li>
    <li>//其他代码 </li>
    <li>
    } </li>
</ol>
</div>
<p><span style="font-family: Arial;">　　假如在一个JSP中这样的去调用：</span></p>
<div>
<ol>
    <li>&lt;a.jsp&gt;: </li>
    <li>&lt;% </li>
    <li><span>Java.util.Date date =
    C1.sdf.parse(&#8220;2003-4-15&#8221;); </span></li>
    <li>
    %&gt; </li>
</ol>
</div>
<p>　　则这样的代码不是线程安全的。因为java.text.SimpleDateFormat
不是线程安全的，a.jsp中的代码将会有若干个线程同时执行，而都访问的是同一个线程不安全的对象，这样就不是一个线程安全的代码。正确的写法应该如
下：</p>
<div>
<ol>
    <li>&lt;a.jsp&gt;: </li>
    <li>&lt;% </li>
    <li><span>java.text.SimpleDateFormat sdf =
    new java.text.SimpleDateFormat("yyyy-MM-dd");
    </span></li>
    <li><span>Java.util.Date date =
    sdf.parse(&#8220;2003-4-15&#8221;); </span></li>
    <li>
    %&gt; </li>
</ol>
</div>
<p>2、&nbsp;原因分析：</p>
<p>　　此时，sdf对象从创建到销毁都位于一个方法中，相当于一个局部变量，不是一个共享资源，因此则没有线程不安全的问题。</p>
<p>3、&nbsp;解决方法或过程：</p>
<p>1）&nbsp;如果对象是immutable，则是线程安全的，例如:String，可以放心使用。<br />
2）&nbsp;如果对象是线程安全的，则放心使用<br />
3）&nbsp;有
条件线程安全，对于Vector和Hashtable一般情况下是线程安全的，但是对于某些特殊情况，需要通过额外的synchronized保证线程安
全。<br />
4）&nbsp;使用synchronized关键字；</p>
<p>　　对于上例中可以改写jsp代码，在sdf上进行同步，而不需要每次创建一个新的对象来保证线程安全，代码如下：</p>
<div>
<ol>
    <li>&lt;% </li>
    <li>synchronized(C1.sdf){ </li>
    <li><span>Java.util.Date date =
    C1.sdf.parse(&#8220;2003-4-15&#8221;); </span></li>
    <li>} </li>
    <li>
    %&gt; </li>
</ol>
</div>
<p>　　这种写法是在一个对象级别上进行同步，也就是说任何时候，对于这个对象，最多只能有一个线程在执行同步方法。</p>
<p>　　另外一种写法是在Class级别上进行同步，写法如下：</p>
<div>
<ol>
    <li>public class C1 { </li>
    <li>public static <span>java.text.SimpleDateFormat
    sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
    </span></li>
    <li>public void method(){ </li>
    <li>synchronized(C1.class){ </li>
    <li>//synchronized code </li>
    <li>} </li>
    <li>} </li>
    <li>
    } </li>
</ol>
</div>
<p>　　这种写法表示无论C1有多少个实例，在任何一个时间点，最多只能有一个线程和一个实例进入同步块中。这种同步会比较大的影响性能。</p>
<p>　　5）&nbsp;有些对象不能在多线程间共享，则只能在方法内部使用，或者只在一个线程内部使用。</p>
<p><strong><span style="font-size: small;">synchronized详解</span></strong></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">Java</span>对多线程的支持与同步机制深受大家的喜爱，似乎看起来使用了<span style="font-family: Times New Roman;">synchronized</span>关键字就可以轻松地解决多线程共享数据同步问题。到底如何？――还得对<span style="font-family: Times New Roman;">synchronized</span>关键字的作用进行深入了解才可定论。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">总的说来，<span style="font-family: Times New Roman;">synchronized</span>关键字可以作为函数的修饰符，也可作为函数内的语句，也就是平时说的同步方法和同步语句块。如果再细的分类，<span style="font-family: Times New Roman;">synchronized</span>可作用于<span style="font-family: Times New Roman;">instance</span>变量、<span><span style="font-family: Times New Roman;">object
reference</span></span>（对象引用）、<span style="font-family: Times New Roman;">static</span>函数和<span style="font-family: Times New Roman;">class literals(</span>类名称字面常量<span style="font-family: Times New Roman;">)</span>身上。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">在进一步阐述之前，我们需要明确几点：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">A</span>．无论<span style="font-family: Times New Roman;">synchronized</span>关键字加在方法上还是对象上，它取得的锁都是对象，而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">B</span>．每个对象只有一个锁（<span style="font-family: Times New Roman;">lock</span>）与之相关联。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">C</span><span>．实现同步是要很大的系统开销作为代价的，甚至可能
造成死锁，所以尽量避免无谓的同步控制。</span></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><strong>接着来讨论<span style="font-family: Times New Roman;">synchronized</span></strong>
<p style="margin: 0cm 0cm 0pt;"><strong>用到不同地方对代码产生的影响：</strong></p>
</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">假设<span style="font-family: Times New Roman;">P1</span>、<span style="font-family: Times New Roman;">P2</span>是同一个类的不同对象，这个类中定义了以下几种情况的同步块或同步方法，<span style="font-family: Times New Roman;">P1</span>、<span style="font-family: Times New Roman;">P2</span>就都可以调用它们。
</span></p>
<p><span style="font-family: Times New Roman;"><span style="font-size: small;">1．&nbsp;</span></span><span style="font-size: small;">把<span style="font-family: Times New Roman;">synchronized</span>当作函数修饰符时，示例代码如下：</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">Public synchronized void methodAAA()</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt 63pt;"><span style="font-size: small; font-family: Times New Roman;">//&#8230;.</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">这也就是同步方法，那这时<span style="font-family: Times New Roman;">synchronized</span>锁定的是哪个对象呢？它锁定的是调用这个同步方法对象。也就是说，当一个对象<span style="font-family: Times New Roman;">P1</span><span>在不
同的线程中执行这个同步方法时，它们之间会形成互斥，达到同步的效果。但是这个对象所属的</span><span style="font-family: Times New Roman;">Class</span><span>所
产生的另一对象</span><span style="font-family: Times New Roman;">P2</span>却可以任意调用这个被加了<span style="font-family: Times New Roman;">synchronized</span>关键字的方法。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">上边的示例代码等同于如下代码：</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">public void methodAAA()</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt 63pt;"><span style="font-size: small; font-family: Times New Roman;">synchronized (this)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;(1)</span></p>
<p style="margin: 0cm 0cm 0pt 63pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt 63pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&#8230;..</span></span></p>
<p style="margin: 0cm 0cm 0pt 63pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;(1)</span><span>处
的</span><span style="font-family: Times New Roman;">this</span>指的是什么呢？它指的就是调用这个方法的对象，如<span style="font-family: Times New Roman;">P1</span><span>。可见
同步方法实质是将</span><span style="font-family: Times New Roman;">synchronized</span>作用于<span><span style="font-family: Times New Roman;">object
reference</span></span>。――那个拿到了<span style="font-family: Times New Roman;">P1</span><span>对象
锁的线程，才可以调用</span><span style="font-family: Times New Roman;">P1</span>的同步方法，而对<span style="font-family: Times New Roman;">P2</span><span>而
言，</span><span style="font-family: Times New Roman;">P1</span>这个锁与它毫不相干，程序也可能在这种情形下摆脱同步机制的控制，造成数据混乱：（</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">2</span>．同步块，示例代码如下：</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void method3(SomeObject so)</span></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(so)</span></span></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&#8230;..</span></span></p>
<p style="margin: 0cm 0cm 0pt 42pt; text-indent: 21pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;"><span style="font-size: small;">这时，锁就是<span style="font-family: Times New Roman;">so</span><span>这个对象，谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时，就可以这样写程序，但当没有明确的对象作为
锁，只是想让一段代码同步时，可以创建一个特殊的</span><span style="font-family: Times New Roman;">instance</span>变量（它得是一个对象）来充当锁：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;"><span style="font-size: small; font-family: Times New Roman;">class Foo implements Runnable</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private byte[] lock = new
byte[0];&nbsp;// </span></span>特殊的<span style="font-family: Times New Roman;">instance</span>变量</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp; Public void methodA()</span></span></p>
<p style="margin: 0cm 0cm 0pt 20.25pt; text-indent: 21.75pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(lock) { //&#8230; }</span></span></p>
<p style="margin: 0cm 0cm 0pt 20.25pt; text-indent: 21.75pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt 20.25pt; text-indent: 21.75pt;"><span style="font-size: small; font-family: Times New Roman;">//&#8230;..</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21.75pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;">注：零长度的<span style="font-family: Times New Roman;">byte</span><span>数
组对象创建起来将比任何对象都经济――查看编译后的字节码：生成零长度的</span><span style="font-family: Times New Roman;">byte[]</span><span>对
象只需</span><span style="font-family: Times New Roman;">3</span>条操作码，而<span style="font-family: Times New Roman;">Object lock = new Object()</span><span>则
需要</span><span style="font-family: Times New Roman;">7</span>行操作码。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">3</span>．将<span style="font-family: Times New Roman;">synchronized</span>作用于<span style="font-family: Times New Roman;">static </span>函数，示例代码如下：</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class Foo </span></span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">public synchronized static void methodAAA()&nbsp;&nbsp; // </span>同步的<span style="font-family: Times New Roman;">static </span>函数</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt 63pt;"><span style="font-size: small; font-family: Times New Roman;">//&#8230;.</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">public void methodBBB()</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">{</span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(Foo.class)&nbsp;&nbsp; //&nbsp;class literal(</span>类名称字面常量<span style="font-family: Times New Roman;">)</span></span></p>
<p style="margin: 0cm 0cm 0pt 42pt;"><span style="font-size: small; font-family: Times New Roman;">}</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="font-family: Times New Roman;">&nbsp;&nbsp; </span>代码中的<span style="font-family: Times New Roman;">methodBBB()</span>方法是把<span style="font-family: Times New Roman;">class literal</span>作为锁的情况，它和同步的<span style="font-family: Times New Roman;">static</span><span>函
数产生的效果是一样的，取得的锁很特别，是当前调用这个方法的对象所属的类（</span><span style="font-family: Times New Roman;">Class</span><span>，
而不再是由这个</span><span style="font-family: Times New Roman;">Class</span>产生的某个具体对象了）。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">记得在《<span style="font-family: Times New Roman;">Effective Java</span>》一书中看到过将<span style="font-family: Times New Roman;"> Foo.class</span>和<span style="font-family: Times New Roman;"> P1.getClass()</span>用于作同步锁还不一样，不能用<span style="font-family: Times New Roman;">P1.getClass()</span>来达到锁这个<span style="font-family: Times New Roman;">Class</span>的目的。<span style="font-family: Times New Roman;">P1</span>指的是由<span style="font-family: Times New Roman;">Foo</span>类产生的对象。</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">可以推断：如果一个类中定义了一个<span style="font-family: Times New Roman;">synchronized</span>的<span style="font-family: Times New Roman;">static</span>函数<span style="font-family: Times New Roman;">A</span><span>，也定
义了一个</span><span style="font-family: Times New Roman;">synchronized </span>的<span style="font-family: Times New Roman;">instance</span>函数<span style="font-family: Times New Roman;">B</span>，那么这个类的同一对象<span style="font-family: Times New Roman;">Obj</span>在多线程中分别访问<span style="font-family: Times New Roman;">A</span>和<span style="font-family: Times New Roman;">B</span>两个方法时，不会构成同步，因为它们的锁都不一样。<span style="font-family: Times New Roman;">A</span><span>方法的锁
是</span><span style="font-family: Times New Roman;">Obj</span>这个对象，而<span style="font-family: Times New Roman;">B</span>的锁是<span style="font-family: Times New Roman;">Obj</span>所属的那个<span style="font-family: Times New Roman;">Class</span>。
</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">小结如下：</span></p>
<p style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;">搞清楚<span style="font-family: Times New Roman;">synchronized</span>锁定的是哪个对象，就能帮助我们设计更安全的多线程程序。</span></p>
<p style="margin: 0cm 0cm 0pt;"><span style="font-size: small;">还有一些技巧可以让我们对共享资源的同步访问更加安全：</span></p>
<p><span style="font-family: Times New Roman;"><span style="font-size: small;">1．&nbsp;</span></span><span style="font-size: small;">定义<span style="font-family: Times New Roman;">private </span>的<span style="font-family: Times New Roman;">instance</span>变量<span style="font-family: Times New Roman;">+</span>它的<span style="font-family: Times New Roman;"> get</span>方法，而不要定义<span style="font-family: Times New Roman;">public/protected</span>的<span style="font-family: Times New Roman;">instance</span>变量。如果将变量定义为<span style="font-family: Times New Roman;">public</span><span>，对象在外界可以绕过同步方法的控制而
直接取得它，并改动它。这也是</span><span style="font-family: Times New Roman;">JavaBean</span>的标准实现方式之一。</span></p>
<p><span style="font-family: Times New Roman;"><span style="font-size: small;">2．&nbsp;</span></span><span style="font-size: small;">如果<span style="font-family: Times New Roman;">instance</span>变量是一个对象，如数组或<span style="font-family: Times New Roman;">ArrayList</span><span>什么的，那上述方法仍然不安全，
因为当外界对象通过</span><span style="font-family: Times New Roman;">get</span>方法拿到这个<span style="font-family: Times New Roman;">instance</span>对象的引用后，又将其指向另一个对象，那么这个<span style="font-family: Times New Roman;">private</span>变量也就变了，岂不是很危险。这个时候就需要将<span style="font-family: Times New Roman;">get</span><span>方法
也加上</span><span style="font-family: Times New Roman;">synchronized</span>同步，并且，只返回这个<span style="font-family: Times New Roman;">private</span>对象的<span style="font-family: Times New Roman;">clone()</span>――这样，调用端得到的就是对象副本的引用了。</span></p>
<p><br />
</p>
<p><span style="font-size: small;"><br />
</span></p>
<img src ="http://www.blogjava.net/caizh2009/aggbug/320556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-05-11 09:49 <a href="http://www.blogjava.net/caizh2009/archive/2010/05/11/320556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>电话面试（淘宝）</title><link>http://www.blogjava.net/caizh2009/archive/2010/04/08/317691.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 08 Apr 2010 01:37:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/04/08/317691.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/317691.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/04/08/317691.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/317691.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/317691.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; * struts1.2和webwork的区别
<br />
&nbsp;&nbsp;&nbsp; * hibernate和ibatis的区别
<br />
&nbsp;&nbsp;&nbsp; * spring工作机制，IOC容器
<br />
&nbsp;&nbsp;&nbsp; * servlet的一些相关问题
<br />
&nbsp;&nbsp;&nbsp; * webservice相关
<br />
&nbsp;&nbsp;&nbsp; * java基础：jvm，HashSet等等
<br />
&nbsp;&nbsp;&nbsp; * 考察学习新技术的能力
<img src ="http://www.blogjava.net/caizh2009/aggbug/317691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-04-08 09:37 <a href="http://www.blogjava.net/caizh2009/archive/2010/04/08/317691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>笔试（创立）</title><link>http://www.blogjava.net/caizh2009/archive/2010/04/08/317689.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 08 Apr 2010 01:35:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/04/08/317689.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/317689.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/04/08/317689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/317689.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/317689.html</trackback:ping><description><![CDATA[1.hibernate中配置int和integer的区别<br />
2.手写，spring+hibernate配置<br />
3.JavaScript时间和如何实现继承<br />
其他略忘了<br />
<br />
<img src ="http://www.blogjava.net/caizh2009/aggbug/317689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-04-08 09:35 <a href="http://www.blogjava.net/caizh2009/archive/2010/04/08/317689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java对象池技术的原理及其实现</title><link>http://www.blogjava.net/caizh2009/archive/2010/03/05/314615.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 05 Mar 2010 07:24:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/03/05/314615.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/314615.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/03/05/314615.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/314615.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/314615.html</trackback:ping><description><![CDATA[　<strong>摘 要</strong> 本文在分析对象池技术基本原理的基础上，给出了对象池技术的两种实现方式。还指出了使用对象池技术时所应注意的问题。<br />
<br />
　　<strong>关键词</strong> 对象池；对象池技术；Java 对象；性能 <br />
<br />
　<strong>　Java对象的生命周期分析</strong><br />
<br />
　　Java对象的生命周期大致包括三个阶段：对象的创建，对象的使用，对象的清除。因此，对象的生命周期长度可用如下的表达式表示：T = T1 + T2 +T3。其中T1表示对象的创建时间，T2表示对象的使用时间，而T3则表示其清除时间。由此，我们可以看出，只有T2是真正有效的时间，而T1、T3则是对象本身的开销。下面再看看T1、T3在对象的整个生命周期中所占的比例。<br />
<br />
　　我们知道，Java对象是通过构造函数来创建的，在这一过程中，该构造函数链中的所有构造函数也都会被自动调用。另外，默认情况下，调用类的构造函数时，Java会把变量初始化成确定的值：所有的对象被设置成null，整数变量（byte、short、int、long）设置成0，float和double变量设置成0.0，逻辑值设置成false。所以用new关键字来新建一个对象的时间开销是很大的，如表1所示。<br />
<br />
　　表1 一些操作所耗费时间的对照表<br />
<br />
<table cellspacing="0" cellpadding="2" width="90%" align="center" border="1">
    <tbody>
        <tr>
            <td>运算操作</td>
            <td>示例</td>
            <td>标准化时间 </td>
        </tr>
        <tr>
            <td>本地赋值</td>
            <td>i = n</td>
            <td>1.0 </td>
        </tr>
        <tr>
            <td>实例赋值</td>
            <td>this.i = n</td>
            <td>1.2 </td>
        </tr>
        <tr>
            <td>方法调用</td>
            <td>Funct()</td>
            <td>5.9 </td>
        </tr>
        <tr>
            <td>新建对象</td>
            <td>New Object() </td>
            <td>980 </td>
        </tr>
        <tr>
            <td>新建数组</td>
            <td>New int[10] </td>
            <td>3100 </td>
        </tr>
    </tbody>
</table>
<br />
　　从表1可以看出，新建一个对象需要980个单位的时间，是本地赋值时间的980倍，是方法调用时间的166倍，而若新建一个数组所花费的时间就更多了。<br />
<br />
　　再看清除对象的过程。我们知道，Java语言的一个优势，就是Java程序员勿需再像C/C++程序员那样，显式地释放对象，而由称为垃圾收集器（Garbage Collector）的自动内存管理系统，定时或在内存凸现出不足时，自动回收垃圾对象所占的内存。凡事有利总也有弊，这虽然为Java程序设计者提供了极大的方便，但同时它也带来了较大的性能开销。这种开销包括两方面，首先是对象管理开销，GC为了能够正确释放对象，它必须监控每一个对象的运行状态，包括对象的申请、引用、被引用、赋值等。其次，在GC开始回收&#8220;垃圾&#8221;对象时，系统会暂停应用程序的执行，而独自占用CPU。<br />
<br />
　　因此，如果要改善应用程序的性能，一方面应尽量减少创建新对象的次数；同时，还应尽量减少T1、T3的时间，而这些均可以通过对象池技术来实现。<br />
<br />
　　<strong>对象池技术的基本原理</strong><br />
<br />
　　对象池技术基本原理的核心有两点：缓存和共享，即对于那些被频繁使用的对象，在使用完后，不立即将它们释放，而是将它们缓存起来，以供后续的应用程序重复使用，从而减少创建对象和释放对象的次数，进而改善应用程序的性能。事实上，由于对象池技术将对象限制在一定的数量，也有效地减少了应用程序内存上的开销。<br />
<br />
　　实现一个对象池，一般会涉及到如下的类：<br />
<br />
　　1）对象池工厂（ObjectPoolFactory）类<br />
<br />
　　该类主要用于管理相同类型和设置的对象池（ObjectPool），它一般包含如下两个方法：<br />
<br />
　　&#183;createPool：用于创建特定类型和设置的对象池；<br />
<br />
　　&#183;destroyPool：用于释放指定的对象池；<br />
<br />
　　同时为保证ObjectPoolFactory的单一实例，可以采用Singleton设计模式，见下述getInstance方法的实现：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>public static ObjectPoolFactory getInstance() {<br />
            　if (poolFactory == null) {<br />
            　　poolFactory = new ObjectPoolFactory();<br />
            　}<br />
            　return poolFactory;<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　2）参数对象（ParameterObject）类<br />
<br />
　　该类主要用于封装所创建对象池的一些属性参数，如池中可存放对象的数目的最大值（maxCount）、最小值（minCount）等。<br />
<br />
　　3）对象池（ObjectPool）类<br />
<br />
　　用于管理要被池化对象的借出和归还，并通知PoolableObjectFactory完成相应的工作。它一般包含如下两个方法：<br />
<br />
　　　&#183;getObject：用于从池中借出对象；<br />
　　　&#183;returnObject：将池化对象返回到池中，并通知所有处于等待状态的线程；<br />
<br />
　　4）池化对象工厂（PoolableObjectFactory）类<br />
<br />
　　该类主要负责管理池化对象的生命周期，就简单来说，一般包括对象的创建及销毁。该类同ObjectPoolFactory一样，也可将其实现为单实例。<br />
<strong>通用对象池的实现</strong><br />
<br />
　　对象池的构造和管理可以按照多种方式实现。最灵活的方式是将池化对象的Class类型在对象池之外指定，即在ObjectPoolFactory类创建对象池时，动态指定该对象池所池化对象的Class类型，其实现代码如下：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>. . .<br />
            public ObjectPool createPool(ParameterObject paraObj,Class clsType) {<br />
            　return new ObjectPool(paraObj, clsType);<br />
            }<br />
            . . .</td>
        </tr>
    </tbody>
</table>
<br />
　　其中，paraObj参数用于指定对象池的特征属性，clsType参数则指定了该对象池所存放对象的类型。对象池（ObjectPool）创建以后，下面就是利用它来管理对象了，具体实现如下：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>public class ObjectPool {<br />
            　private ParameterObject paraObj;//该对象池的属性参数对象<br />
            　private Class clsType;//该对象池中所存放对象的类型<br />
            　private int currentNum = 0; //该对象池当前已创建的对象数目<br />
            　private Object currentObj;//该对象池当前可以借出的对象<br />
            　private Vector pool;//用于存放对象的池<br />
            　public ObjectPool(ParameterObject paraObj, Class clsType) {<br />
            　　this.paraObj = paraObj;<br />
            　　this.clsType = clsType;<br />
            　　pool = new Vector();<br />
            　}<br />
            　public Object getObject() {<br />
            　　if (pool.size() &lt;= paraObj.getMinCount()) {<br />
            　　　if (currentNum &lt;= paraObj.getMaxCount()) {<br />
            　　　　//如果当前池中无对象可用，而且已创建的对象数目小于所限制的最大值，就利用<br />
            　　　　//PoolObjectFactory创建一个新的对象<br />
            　　　　PoolableObjectFactory objFactory =PoolableObjectFactory.getInstance();<br />
            　　　　currentObj = objFactory.create Object (clsType);<br />
            　　　　currentNum++;<br />
            　　　} else {<br />
            　　　　//如果当前池中无对象可用，而且所创建的对象数目已达到所限制的最大值，<br />
            　　　　//就只能等待其它线程返回对象到池中<br />
            　　　　synchronized (this) {<br />
            　　　　　try {<br />
            　　　　　　wait();<br />
            　　　　　} catch (InterruptedException e) {<br />
            　　　　　　System.out.println(e.getMessage());<br />
            　　　　　　e.printStackTrace();<br />
            　　　　　}<br />
            　　　　　currentObj = pool.firstElement();<br />
            　　　　}<br />
            　　　}<br />
            　　} else {<br />
            　　　//如果当前池中有可用的对象，就直接从池中取出对象<br />
            　　　currentObj = pool.firstElement();<br />
            　　}<br />
            　　return currentObj;<br />
            }<br />
            　　public void returnObject(Object obj) {<br />
            　　　// 确保对象具有正确的类型<br />
            　　　if (obj.isInstance(clsType)) {<br />
            　　　　pool.addElement(obj);<br />
            　　　　synchronized (this) {<br />
            　　　　　notifyAll();<br />
            　　　　}<br />
            　　　} else {<br />
            　　　　throw new IllegalArgumentException("该对象池不能存放指定的对象类型");<br />
            　　　}<br />
            　　}<br />
            }</td>
        </tr>
    </tbody>
</table>
<br />
　　从上述代码可以看出，ObjectPool利用一个java.util.Vector作为可扩展的对象池，并通过它的构造函数来指定池化对象的Class类型及对象池的一些属性。在有对象返回到对象池时，它将检查对象的类型是否正确。当对象池里不再有可用对象时，它或者等待已被使用的池化对象返回池中，或者创建一个新的对象实例。不过，新对象实例的创建并不在ObjectPool类中，而是由PoolableObjectFactory类的createObject方法来完成的，具体实现如下：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>. . .<br />
            public Object createObject(Class clsType) {<br />
            　Object obj = null;<br />
            　try {<br />
            　　obj = clsType.newInstance();<br />
            　} catch (Exception e) {<br />
            　　e.printStackTrace();<br />
            　} <br />
            　return obj;<br />
            }<br />
            . . .</td>
        </tr>
    </tbody>
</table>
<br />
　　这样，通用对象池的实现就算完成了，下面再看看客户端（Client）如何来使用它，假定池化对象的Class类型为StringBuffer：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>. . .<br />
            //创建对象池工厂<br />
            ObjectPoolFactory poolFactory = ObjectPoolFactory. getInstance ();<br />
            //定义所创建对象池的属性<br />
            ParameterObject paraObj = new ParameterObject(2,1);<br />
            //利用对象池工厂,创建一个存放StringBuffer类型对象的对象池<br />
            ObjectPool pool = poolFactory.createPool(paraObj,String Buffer.class);<br />
            //从池中取出一个StringBuffer对象<br />
            StringBuffer buffer = (StringBuffer)pool.getObject();<br />
            //使用从池中取出的StringBuffer对象<br />
            buffer.append("hello");<br />
            System.out.println(buffer.toString()); <br />
            . . .</td>
        </tr>
    </tbody>
</table>
<br />
　　可以看出，通用对象池使用起来还是很方便的，不仅可以方便地避免频繁创建对象的开销，而且通用程度高。但遗憾的是，由于需要使用大量的类型定型（cast）操作，再加上一些对Vector类的同步操作，使得它在某些情况下对性能的改进非常有限，尤其对那些创建周期比较短的对象<br />
<strong>专用对象池的实现</strong>　　　　　<br />
<br />
　　由于通用对象池的管理开销比较大，某种程度上抵消了重用对象所带来的大部分优势。为解决该问题，可以采用专用对象池的方法。即对象池所池化对象的Class类型不是动态指定的，而是预先就已指定。这样，它在实现上也会较通用对象池简单些，可以不要ObjectPoolFactory和PoolableObjectFactory类，而将它们的功能直接融合到ObjectPool类，具体如下（假定被池化对象的Class类型仍为StringBuffer，而用省略号表示的地方，表示代码同通用对象池的实现）：<br />
<br />
<table bordercolor="#cccccc" width="90%" align="center" bgcolor="#e7e9e9" border="1">
    <tbody>
        <tr>
            <td>public class ObjectPool {<br />
            　private ParameterObject paraObj;//该对象池的属性参数对象<br />
            　private int currentNum = 0; //该对象池当前已创建的对象数目<br />
            　private StringBuffer currentObj;//该对象池当前可以借出的对象<br />
            　private Vector pool;//用于存放对象的池<br />
            　public ObjectPool(ParameterObject paraObj) {<br />
            　　this.paraObj = paraObj;<br />
            　　pool = new Vector();<br />
            　}<br />
            　public StringBuffer getObject() {<br />
            　　if (pool.size() &lt;= paraObj.getMinCount()) {<br />
            　　　if (currentNum &lt;= paraObj.getMaxCount()) {<br />
            　　　　currentObj = new StringBuffer();<br />
            　　　　currentNum++;<br />
            　　　} <br />
            　　　. . . <br />
            　　}<br />
            　　return currentObj;<br />
            　}<br />
            　public void returnObject(Object obj) {<br />
            　　// 确保对象具有正确的类型<br />
            　　if (StringBuffer.isInstance(obj)) {<br />
            　　　. . . <br />
            　　}<br />
            　}</td>
        </tr>
    </tbody>
</table>
<br />
　　<strong>结束语</strong><br />
<br />
　　恰当地使用对象池技术，能有效地改善应用程序的性能。目前，对象池技术已得到广泛的应用，如对于网络和数据库连接这类重量级的对象，一般都会采用对象池技术。但在使用对象池技术时也要注意如下问题： <br />
<br />
　　&#183;并非任何情况下都适合采用对象池技术。基本上，只在重复生成某种对象的操作成为影响性能的关键因素的时候，才适合采用对象池技术。而如果进行池化所能带来的性能提高并不重要的话，还是不采用对象池化技术为佳，以保持代码的简明。<br />
<br />
　　&#183;要根据具体情况正确选择对象池的实现方式。如果是创建一个公用的对象池技术实现包，或需要在程序中动态指定所池化对象的Class类型时，才选择通用对象池。而大部分情况下，采用专用对象池就可以了。<br />
 <img src ="http://www.blogjava.net/caizh2009/aggbug/314615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-03-05 15:24 <a href="http://www.blogjava.net/caizh2009/archive/2010/03/05/314615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用filter过滤请求</title><link>http://www.blogjava.net/caizh2009/archive/2010/03/05/314596.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 05 Mar 2010 04:33:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/03/05/314596.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/314596.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/03/05/314596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/314596.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/314596.html</trackback:ping><description><![CDATA[<div style="border-right: black 1px solid; border-top: black 1px solid; border-left: black 1px solid; border-bottom: black 1px solid; height: 73px; background-color: white" xmlns="http://www.w3.org/TR/xhtml1/transitional"><a title="Family168" style="border-right: medium none; border-top: medium none; border-left: medium none; border-bottom: medium none" href="http://www.family168.com/"><img src="http://www.family168.com/tutorial/jsp/shared/images/family168.png" border="0"  alt="" /></a></div>
<div class="navheader">
<table width="100%" summary="Navigation header">
    <tbody>
        <tr>
            <th align="center" colspan="3">第&nbsp;7&nbsp;章&nbsp;使用filter过滤请求</th>
        </tr>
        <tr>
            <td align="left" width="20%"><a accesskey="p" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-06.html">上一页</a>&nbsp;</td>
            <th align="center" width="60%">&nbsp;</th>
            <td align="right" width="20%">&nbsp;<a accesskey="n" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-08.html">下一页</a></td>
        </tr>
    </tbody>
</table>
<hr />
</div>
<div class="chapter" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a name="jsp-ch-07"></a>第&nbsp;7&nbsp;章&nbsp;使用filter过滤请求</h2>
</div>
</div>
</div>
<div class="simplesect" lang="zh-cn">
<div class="titlepage"></div>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in">
<h3 class="title">注意</h3>
<p>Filter虽然很常用，但是覆盖的范围太广，这里我们只介绍设置编码和控制权限的过滤器，其他的使用方式还需要大家自行积累。</p>
</div>
<p>如果你不满足以下任一条件，请继续阅读，否则请跳过此后的部分，进入下一章：<a class="xref" title="第&nbsp;8&nbsp;章&nbsp;配置listener监听器" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-08.html">第&nbsp;8&nbsp;章 <em>配置listener监听器</em></a>。</p>
<div class="orderedlist">
<ol type="1">
    <li>
    <p>了解Filter的使用。</p>
    </li>
</ol>
</div>
</div>
<div class="sect1" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="jsp-ch-07-01"></a>7.1.&nbsp;批量设置请求编码</h2>
</div>
</div>
</div>
<p>编码问题会不会成为中国人学java的标志呢？</p>
<p>通过之前的讨论<a class="xref" title="2.2.2.&nbsp;POST乱码" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-02.html#jsp-ch-02-02-02">第&nbsp;2.2.2&nbsp;节 &#8220;POST乱码&#8221;</a>，我们知道为了避免提交数据的乱码问题，需要在每次使用请求之前设置编码格式。在你复制粘贴了无数次request.setCharacterEncoding("gb2312");后，有没有想要一劳永逸的方法呢？能不能一次性修改所有请求的编码呢？</p>
<p>用Filter吧，它的名字是过滤器，可以批量拦截修改servlet的请求和响应。</p>
<p>我们编写一个EncodingFilter.java，来批量设置请求编码。</p>
<pre class="programlisting"><span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">package</span> anni;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">import</span> java.io.IOException;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">import</span> javax.servlet.Filter;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">import</span> javax.servlet.FilterChain;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">import</span> javax.servlet.FilterConfig;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">import</span> javax.servlet.ServletException;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">import</span> javax.servlet.ServletRequest;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">import</span> javax.servlet.ServletResponse;
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">public</span> <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">class</span> EncodingFilter <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">implements</span> Filter {
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">public</span> <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">void</span> init(FilterConfig config) <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">throws</span> ServletException {}
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">public</span> <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">void</span> destroy() {}
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">public</span> <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">void</span> doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">throws</span> IOException, ServletException {
request.setCharacterEncoding(<span class="hl-string" xmlns="http://www.w3.org/TR/xhtml1/transitional">"gb2312"</span>);
chain.doFilter(request, response);
}
}
</pre>
<p>在此EncodingFilter实现了Filter接口，Filter接口中定义的三个方法都要在EncodingFilter中实现，其中doFilter()的代码实现主要的功能：为请求设置gb2312编码并执行chain.doFilter()继续下面的操作。</p>
<p>与servlet相似，为了让filter发挥作用还需要在web.xml进行配置。</p>
<pre class="programlisting">&lt;<strong class="hl-tag" style="color: blue">filter</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-name</strong>&gt;EncodingFilter&lt;<strong class="hl-tag" style="color: blue">/filter-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-class</strong>&gt;anni.EncodingFilter&lt;<strong class="hl-tag" style="color: blue">/filter-class</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/filter</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-name</strong>&gt;EncodingFilter&lt;<strong class="hl-tag" style="color: blue">/filter-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/*&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/filter-mapping</strong>&gt;
</pre>
<p>filter标签部分定义使用的过滤器，filter-mapping标签告诉服务器把哪些请求交给过滤器处理。这里的/*表示所有请求，/表示根路径，*（星号）代表所有请求，加在一起就变成了根路径下的所有请求。</p>
<p>这样，所有的请求都会先被EncodingFilter拦截，并在请求里设置上指定的gb2312编码。</p>
<p>例子在lingo-sample/07-01目录下，这次我们不需要在test.jsp中为请求设置编码也可以得到正常的中文参数了，EncodingFilter圆满的完成了它的工作。</p>
</div>
<div class="sect1" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="jsp-ch-07-02"></a>7.2.&nbsp;用filter控制用户访问权限</h2>
</div>
</div>
</div>
<p>出于信息安全和其他一些原因的考虑，项目中的一些页面要求用户满足了一定条件之后才能访问。比如，让用户输入帐号和密码，如果输入的信息正确就在session里做一个成功登录的标记，其后在请求保密信息的时候判断session中是否有已经登录成功的标记，存在则可以访问，不存在则禁止访问。</p>
<p>如07-02例子中所示，进入首页看到的就是登录页面。</p>
<div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-02-security-01.png" align="center"  alt="" /></div>
<p>现在用户还没有登录，如果直接访问保密信息，就会显示无法访问保密信息的页面，并提醒用户进行注册。</p>
<div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-02-security-02.png" align="center"  alt="" /></div>
<p>返回登录页面后，输入正确的用户名和密码，点击登录。</p>
<div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-02-security-03.png" align="center"  alt="" /></div>
<p>后台程序判断用户名和密码正确无误后，在session中设置已登录的标记，然后跳转到保密信息页面。</p>
<div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-02-security-04.png" align="center"  alt="" /></div>
<p>我们要保护的页面是admin/index.jsp，为此我们在web.xml进行如下配置。</p>
<pre class="programlisting">&lt;<strong class="hl-tag" style="color: blue">filter</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-name</strong>&gt;SecurityFilter&lt;<strong class="hl-tag" style="color: blue">/filter-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-class</strong>&gt;anni.SecurityFilter&lt;<strong class="hl-tag" style="color: blue">/filter-class</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/filter</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-name</strong>&gt;SecurityFilter&lt;<strong class="hl-tag" style="color: blue">/filter-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/admin/*&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/filter-mapping</strong>&gt;
</pre>
<p>定义SecurityFilter过滤器，让它过滤匹配/admin/*的所有请求，这就是说，对/admin/路径下的所有请求都会接受SecurityFilter的检查，那么SecurityFilter里到底做了些什么呢？</p>
<pre class="programlisting"><span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">public</span> <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">void</span> doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">throws</span> IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession();
<span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">if</span> (session.getAttribute(<span class="hl-string" xmlns="http://www.w3.org/TR/xhtml1/transitional">"username"</span>) != null) {
chain.doFilter(request, response);
} <span class="hl-keyword" xmlns="http://www.w3.org/TR/xhtml1/transitional">else</span> {
res.sendRedirect(<span class="hl-string" xmlns="http://www.w3.org/TR/xhtml1/transitional">"../failure.jsp"</span>);
}
}
</pre>
<p>首先要将ServletRequest和ServletResponse转换成HttpServletRequest和HttpServletResponse，因为Filter本来设计成为多种协议服务，http协议仅仅是其中一部分。不过我们接触到的也只有http，而且也只有转换成对应HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。</p>
<p>得到了http请求之后，可以获得请求对应的session，判断session中的username变量是否为null，如果不为null，说明用户已经登录，就可以调用doFilter继续请求访问的资源。如果为null，说明用户还没有登录，禁止用户访问，并使用页面重定向跳转到failure.jsp页面显示提示信息。</p>
<p>session中的username实在登录的时候设置进去的，值就是登录用户使用的用户名，详细代码可以参考07-02/WEB-INF/src/LoginServlet.java，登录和注销都写成了servlet并映射到/login.do和/logout.do这两个请求路径上。源代码和web.xml配置请自行参考07-02中的例子，这里就不复述了。</p>
<p>我们再来看看页面重定向的写法，res.sendRedirect()中使用的是"../failure.jsp"，两个点（..）代表当前路径的上一级路径，这是因为SecurityFilter负责处理的是/admin/下的请求，而/failure.jsp的位置在/admin/目录的上一级，所以加上两个点才能正确跳转到failure.jsp。当然这里使用forward()也可以，但是要注意在不同路径下做请求转发会影响页面中相对路径的指向。相关讨论在：<a class="xref" title="3.4.2.&nbsp;forward导致找不到图片" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-03.html#jsp-ch-03-04-02">第&nbsp;3.4.2&nbsp;节 &#8220;forward导致找不到图片&#8221;</a>。</p>
</div>
<div class="sect1" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="jsp-ch-07-03"></a>7.3.&nbsp;filter所谓的特性</h2>
</div>
</div>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="jsp-ch-07-03-01"></a>7.3.1.&nbsp;请求映射</h3>
</div>
</div>
</div>
<p>filter-mapping和servlet-mapping都是将对应的filter或servlet映射到某个url-pattern上，当客户发起某一请求时，服务器先将此请求与web.xml中定义的所有url-pattern进行匹配，然后执行匹配通过的filter和servlet。</p>
<p>你可以使用三种方式定义url-pattern。</p>
<div class="orderedlist">
<ol type="1">
    <li>
    <p>直接映射一个请求。</p>
    <pre class="programlisting">&lt;<strong class="hl-tag" style="color: blue">servlet-mapping</strong>&gt;
    &lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;ContactServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
    &lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/contact.do&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
    &lt;<strong class="hl-tag" style="color: blue">/servlet-mapping</strong>&gt;
    </pre>
    <p>像<a class="xref" title="6.3.&nbsp;使用servlet改写联系簿" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-06.html#jsp-ch-06-03">第&nbsp;6.3&nbsp;节 &#8220;使用servlet改写联系簿&#8221;</a>中对servlet的映射，只有当请求是/contact.do的时候才会执行ContactServlet。/contact.do?id=1或/contact.do?method=list&amp;id=1的请求也可以匹配到ContactServlet，这是因为根据http规范，请求的路径不包含问号以后的部分。</p>
    <li>
    <p>映射一个路径下的所有请求。</p>
    <pre class="programlisting">&lt;<strong class="hl-tag" style="color: blue">servlet-mapping</strong>&gt;
    &lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;EncodingFilter&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
    &lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/*&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
    &lt;<strong class="hl-tag" style="color: blue">/servlet-mapping</strong>&gt;
    </pre>
    <p>像<a class="xref" title="7.1.&nbsp;批量设置请求编码" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-07.html#jsp-ch-07-01">第&nbsp;7.1&nbsp;节 &#8220;批量设置请求编码&#8221;</a>中这样使用星号（*）的形式，可以将某个路径下的所有请求都映射到EncodingFilter过滤器下，如果这个路径下还有子路径，那么子路径下的请求也会被EncodingFilter过滤。所以 /*这种写法就会过滤应用下所有的请求。</p>
    <p>如果像<a class="xref" title="7.2.&nbsp;用filter控制用户访问权限" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-07.html#jsp-ch-07-02">第&nbsp;7.2&nbsp;节 &#8220;用filter控制用户访问权限&#8221;</a>中那样把映射配置成/admin/*，就会只处理/admin/路径下的请求，不会处理根路径下的/index.jsp和/failure.jsp。</p>
    <p>需要注意的是，这种写法必须以/开头，写成与绝对路径的形式，即便是映射所有请求也要写成/*，不能简化成*。</p>
    <li>
    <p>映射结尾相同的一类请求。</p>
    <pre class="programlisting">&lt;servlet-mapping&gt;
    &lt;servlet-name&gt;ControllerServlet&lt;/servlet-name&gt;
    &lt;url-pattern&gt;*.do&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
    </pre>
    <p>具体效果请参考07-03的例子，index.jsp中有四个链接，分别指向/a1.do, /a2.do, /xx/b1.do, /xx/yy/c1.do。</p>
    <div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-03-01-mapping-01.png" align="center"  alt="" /></div>
    <p>web.xml中的ControllerServlet会接收以.do结尾的请求，并使用forward将请求转发到/test.jsp。</p>
    <p>点击/a1.do的情况。</p>
    <div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-03-01-mapping-02.png" align="center"  alt="" /></div>
    <p>点击/xx/yy/c1.do的情况。</p>
    <div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-03-01-mapping-03.png" align="center"  alt="" /></div>
    <p>这样做的一个好处是语义更清楚，只要看到以.do结尾的请求就知道肯定是交给ControllerServlet处理了，不管这个请求是在根路径还是子路径下，都会准确无误的找到对应的servlet。</p>
    <p>缺点就是不同路径之间进行forward，jsp里就不能再使用相对路径了，所以我们在test.jsp中使用request.getContextPath()获得当前应用在服务器中的位置（例子中是/07-03）将相对路径都组装成绝对路径，这种用法在以后也会经常用到。</p>
    <pre class="programlisting">&lt;%
    pageContext.setAttribute(<span class="hl-string" xmlns="http://www.w3.org/TR/xhtml1/transitional">"ctx"</span>, request.getContextPath());
    %&gt;
    &lt;p&gt;&lt;a href=<span class="hl-string" xmlns="http://www.w3.org/TR/xhtml1/transitional">"${ctx}/index.jsp"</span>&gt;返回&lt;/a&gt;&lt;/p&gt;
    </pre>
    <p>最后需要注意的是，这种请求映射就不能指定某一路径了，它必须是以星号（*）开始字母结尾，不能写成/*.do的形式。</p>
    </li>
</ol>
</div>
<p>现在咱们也发现java的请求映射有多傻了，灵活配置根本是不可能的任务。</p>
<p>想要获得所有以user开头.do结尾的请求吗？user*.do在url-pattern是无法识别的，只能配置成*.do，再去servlet中对请求进行筛选。</p>
<p>想要让一个servlet负责多个请求吗？/user/*,/admin/*,*.do写在一起url-pattern也不认识，只能配成多个servlet-mapping。</p>
<pre class="programlisting">&lt;<strong class="hl-tag" style="color: blue">servlet-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;ControllerServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/user/*&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/servlet-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;ControllerServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/admin/*&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/servlet-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;ControllerServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;*.do&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/servlet-mapping</strong>&gt;
</pre>
<p>java的复杂性在此处显露无疑。实际使用时，最好不要依赖web.xml中的配置，在自己的类中实现灵活配置才是正途。</p>
</div>
<div class="sect2" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a name="jsp-ch-07-03-02"></a>7.3.2.&nbsp;过滤链</h3>
</div>
</div>
</div>
<p>其实在07-02这个例子里，我们使用了两个过滤器，EncodingFilter负责设置编码，SecurityFilter负责控制权限，那这两个过滤器是怎么起作用的呢？它们两个同时过滤一个请求时谁先谁后呢？</p>
<p>下面这个图会告诉我们答案。</p>
<div class="mediaobject" align="center"><img src="http://www.family168.com/tutorial/jsp/shared/images/jsp-ch-07-03-02-chain-01.png" align="center"  alt="" /></div>
<p>所有的奥秘就在Filter中的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链，然后一次执行其中的doFilter()方法。执行的顺序就如上图所示，执行第一个过滤器的chain.doFilter()之前的代码，第二个过滤器的chain.doFilter()之前的代码，请求的资源，第二个过滤器的chain.doFilter()之后的代码，第一个过滤器的chain.doFilter()之后的代码，最后返回响应。</p>
<p>因此在07-02中执行的代码顺序是：</p>
<div class="orderedlist">
<ol type="1">
    <li>
    <p>执行EncodingFilter.doFilter()中chain.doFilter()之前的部分：request.setCharacterEncoding("gb2312");</p>
    <li>
    <p>执行SecurityFilter.doFilter()中chain.doFilter()之前的部分：判断用户是否已登录。</p>
    <p>如果用户已登录，则访问请求的资源：/admin/index.jsp。</p>
    <p>如果用户未登录，则页面重定向到：/failure.jsp。</p>
    <li>
    <p>执行SecurityFilter.doFilter()中chain.doFilter()之后的部分：这里没有代码。</p>
    <li>
    <p>执行EncodingFilter.doFilter()中chain.doFilter()之后的部分：这里也没有代码。</p>
    </li>
</ol>
</div>
<p>过滤链的好处是，执行过程中任何时候都可以打断，只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。而在实际使用时，就要特别注意过滤链的执行顺序问题，像EncodingFilter就一定要放在所有Filter之前，这样才能确保在使用请求中的数据前设置正确的编码。</p>
</div>
</div>
<div class="sect1" lang="zh-cn">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a name="jsp-ch-07-04"></a>7.4.&nbsp;filter的详细配置</h2>
</div>
</div>
</div>
<p>我们已经了解了filter的基本用法，还有一些细节配置在特殊情况下起作用。</p>
<p>在servlet-2.3中，Filter会过滤一切请求，包括服务器内部使用forward转发请求和&lt;%@ include file="/index.jsp"%&gt;的情况。</p>
<p>到了servlet-2.4中Filter默认下只拦截外部提交的请求，forward和include这些内部转发都不会被过滤，但是有时候我们需要forward的时候也用到Filter，这样就需要如下配置。</p>
<pre class="programlisting">&lt;<strong class="hl-tag" style="color: blue">filter</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-name</strong>&gt;TestFilter&lt;<strong class="hl-tag" style="color: blue">/filtername</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-class</strong>&gt;anni.TestFilter&lt;<strong class="hl-tag" style="color: blue">/filter-class</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/filter</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-name</strong>&gt;TestFilter&lt;<strong class="hl-tag" style="color: blue">/filtername</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/*&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">dispatcher</strong>&gt;REQUEST&lt;<strong class="hl-tag" style="color: blue">/dispatcher</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">dispatcher</strong>&gt;FORWARD&lt;<strong class="hl-tag" style="color: blue">/dispatcher</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">dispatcher</strong>&gt;INCLUDE&lt;<strong class="hl-tag" style="color: blue">/dispatcher</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">dispatcher</strong>&gt;EXCEPTION&lt;<strong class="hl-tag" style="color: blue">/dispatcher</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/filter-mapping</strong>&gt;
</pre>
<p>这样TestFilter就会过滤所有状态下的请求。如果我们没有进行设置，默认使用的就是REQUEST。而EXCEPTION是在isErrorPage="true"的情况下出现的，这个用处不多，看一下即可。</p>
<p>这里FORWARD是解决request.getDispatcher("index.jsp").forward(request, response);无法触发Filter的关键，配置上这个以后再进行forward的时候就可以触发过滤器了。</p>
<p>Filter还有一个有趣的用法，在filter-mapping中我们可以直接指定servlet-mapping，让过滤器只处理一个定义在web.xml中的servlet。</p>
<pre class="programlisting">&lt;<strong class="hl-tag" style="color: blue">filter-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">filter-name</strong>&gt;TestFilter&lt;<strong class="hl-tag" style="color: blue">/filter-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;TestServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/filter-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;TestServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-class</strong>&gt;anni.TestServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-class</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/servlet</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-mapping</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">servlet-name</strong>&gt;TestServlet&lt;<strong class="hl-tag" style="color: blue">/servlet-name</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">url-pattern</strong>&gt;/TestServlet&lt;<strong class="hl-tag" style="color: blue">/url-pattern</strong>&gt;
&lt;<strong class="hl-tag" style="color: blue">/servlet-mapping</strong>&gt;
</pre>
<p>直接指定servlet-name，TestFilter便会引用TestServlet配置的url-pattern，在某些filter与servlet绑定的情况下不失为一个好办法。</p>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
    <tbody>
        <tr>
            <td align="left" width="40%"><a accesskey="p" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-06.html">上一页</a>&nbsp;</td>
            <td align="center" width="20%">&nbsp;</td>
            <td align="right" width="40%">&nbsp;<a accesskey="n" href="http://www.family168.com/tutorial/jsp/html/jsp-ch-08.html">下一页</a></td>
        </tr>
        <tr>
            <td valign="top" align="left" width="40%">第&nbsp;6&nbsp;章&nbsp;贴近servlet&nbsp;</td>
            <td align="center" width="20%"><a accesskey="h" href="http://www.family168.com/tutorial/jsp/html/index.html">起始页</a></td>
            <td valign="top" align="right" width="40%">&nbsp;第&nbsp;8&nbsp;章&nbsp;配置listener监听器</td>
        </tr>
    </tbody>
</table>
</div>
<script type="text/javascript">var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));</script><script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script><script type="text/javascript">var pageTracker = _gat._getTracker("UA-2857097-3");pageTracker._initData();pageTracker._trackPageview();</script>
<img src ="http://www.blogjava.net/caizh2009/aggbug/314596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-03-05 12:33 <a href="http://www.blogjava.net/caizh2009/archive/2010/03/05/314596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中"equals"和"=="的区别</title><link>http://www.blogjava.net/caizh2009/archive/2010/03/05/314571.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 05 Mar 2010 02:36:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/03/05/314571.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/314571.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/03/05/314571.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/314571.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/314571.html</trackback:ping><description><![CDATA[<p>一句话概括：==比较的是两个对象的引用（即内存地址）是否相等，而equals()比较的是两个对象的值（即内存地址里存放的值）是否相等。当然equals()在个别类中被重写了那就例外了。</p>
<p>详细论述：eqauls 与 = =之异同</p>
<p>1）比较方式角度：</p>
<p>= =是面向过程的操作符；equals是面向对象的操作符</p>
<p>= =不属于任何类，equals则是任何类（在Java中）的一个方法；</p>
<p>我们可以1）Primitive1 (基本类型)= = Primitive2(基本类型)；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）Object Reference1(对象引用)= = Object Reference2(对象引用)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）Object Reference1 (对象引用) .equals(Object Reference2 (对象引用))</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这三种比较</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但却不能Primitive1 (基本类型).equals( Primitive2(基本类型))；</p>
<p>&nbsp;对于基本类型，没有面向对象中发送消息一说，自然也不会有</p>
<p>方法成员。</p>
<p>&nbsp;</p>
<p>2）比较目的角度:</p>
<p>1）&nbsp;&nbsp;&nbsp; 如果要比较两个基本类型是否相等，请用= =；</p>
<p>2）&nbsp;&nbsp;&nbsp; 如果要比较两个对象引用是否相等，请用= =；</p>
<p>3）&nbsp;&nbsp;&nbsp; 如果要比较两个对象（逻辑上）是否一致，请用equals；</p>
<p>&nbsp;</p>
<p>对两个对象（逻辑上）是否一致的阐释：</p>
<p>&nbsp;&nbsp; 有人会问:在C++中, 比较两个对象相等不是也可以用==吗？我知道您是指运算符重载，但是很遗憾，Java中不支持运算符重载（java中亦有重载过运算符，他们是&#8220;+&#8221;，&#8220;+=&#8221;，不过也仅此两个，而且是内置实现的）；所以，对象的是否相等的比较这份责任就交由&nbsp; equals()来实现 。&nbsp;&nbsp;&nbsp; </p>
<p>这个&#8220;逻辑上&#8221;其实就取决于人类的看法，实际开发中，就取决于用户的需求；</p>
<p><br />
第三节：equals()缘起：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; equals()是每个对象与生俱来的方法，因为所有类的最终基类就是Object(除去Object本身)；而equals()是Object的方法之一。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们不妨观察一下Object中equals()的source code:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public boolean equals(Object obj) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (this == obj);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意 &#8220;return (this == obj)&#8221;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this与obj都是对象引用，而不是对象本身。所以equals()的缺省实现就是比较</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对象引用是否一致；为何要如此实现呢？ 前面我们说过：对象是否相等，是由我们的需求决定的，世界上的类千奇百怪（当然，这些类都是我们根据模拟现实世界而创造的），虽然Object是他们共同的祖先，可他又怎能知道他的子孙类比较相等的标准呢？但是他明白，任何一个对象，自己总是等于自己的，何谓&#8220;自己总是等于自己&#8221;呢，又如何判断&#8220;自己总是等于自己&#8221;呢？一个对象在内存中只有一份，但他的引用却可以有无穷多个，&#8220;对象自己的引用1=对象自己的引用2&#8221;，不就能判断&#8220;自己总是等于自己&#8221;吗？所以缺省实现实现自然也就是</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;return (this == obj)&#8221;；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而到了我们自己编写的类，对象相等的标准由我们确立，于是就不可避免的要覆写</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 继承而来的public boolean equals(Object obj)；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果您有过编覆写过equals（）的经验（没有过也不要紧），请您思考一个问题：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;两个对象（逻辑上）是否一致&#8221;实际上是比较什么？没错，或许您已脱口而出：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就是对象的属性（即field，或称数据成员）的比较。方法是不可比较的哦。（这个问题是不是有些弱智呢？哈哈）</p>
<p>&nbsp;第四节：对一个推论的思考</p>
<p>推论如下：一言以蔽之：欲比较栈中数据是否相等，请用= =；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 欲比较堆中数据是否相等，请用equals； </p>
<p>因为（根）基本类型，（根）对象引用都在栈中； 而对象本身在堆中；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这句话又对又不对，问题出在哪，就是&#8220;数据&#8221;二字，先看栈中，数据或为基本类型，或为对象引用，用==比较当然没错；但是堆中呢？对象不是堆中吗？不是应该用equals比较吗？可是，我们比较的是堆中&#8220;数据&#8221;，堆中有对象，对象由什么构成呢？可能是对象引用，可能是基本类型，或两者兼而有之。如果我们要比较他们，该用什么呢，用&#8221;equals()&#8221;?不对吧，只能是&#8221;= =&#8221;!所以正确的结论是：欲比较栈中数据是否相等，请用= =； 欲比较堆中数据是否相等，请用equals；</p>
<p>因为（根）基本类型，（根）对象引用都在栈中（所谓&#8220;根&#8221;，指未被任何其他对象所包含）； 而对象本身在堆中。 </p>
<p>文章出处：DIY部落(http://www.diybl.com/course/3_program/java/javajs/2007917/71587.html#)</p>
<img src ="http://www.blogjava.net/caizh2009/aggbug/314571.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-03-05 10:36 <a href="http://www.blogjava.net/caizh2009/archive/2010/03/05/314571.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 关于Java栈与堆的思考</title><link>http://www.blogjava.net/caizh2009/archive/2010/03/05/314570.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Fri, 05 Mar 2010 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/03/05/314570.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/314570.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/03/05/314570.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/314570.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/314570.html</trackback:ping><description><![CDATA[　1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同，Java自动管理栈和堆，程序员不能直接地设置栈或堆。 <br />
<br />
　　2. 栈的优势是，存取速度比堆要快，仅次于直接位于CPU中的寄存器。但缺点是，存在栈中的数据大小与生存期必须是确定的，缺乏灵活性。另外，栈数据可以共享，详见第3点。堆的优势是可以动态地分配内存大小，生存期也不必事先告诉编译器，Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是，由于要在运行时动态分配内存，存取速度较慢。<br />
<br />
　　3. Java中的数据类型有两种。<br />
<br />
　　一种是基本类型(primitive types), 共有8种，即int, short, long, byte, float, double, boolean, char(注意，并没有string的基本类型)。这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的，称为自动变量。值得注意的是，自动变量存的是字面值，不是类的实例，即不是类的引用，这里并没有类的存在。如int a = 3; 这里的a是一个指向int类型的引用，指向3这个字面值。这些字面值的数据，由于大小可知，生存期可知(这些字面值固定定义在某个程序块里面，程序块退出后，字段值就消失了)，出于追求速度的原因，就存在于栈中。<br />
<br />
　　另外，栈有一个很重要的特殊性，就是存在栈中的数据可以共享。假设我们同时定义：<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>int a = 3; <br />
            int b = 3；</td>
        </tr>
    </tbody>
</table>
<br />
　　编译器先处理int a = 3；首先它会在栈中创建一个变量为a的引用，然后查找有没有字面值为3的地址，没找到，就开辟一个存放3这个字面值的地址，然后将a指向3的地址。接着处理int b = 3；在创建完b的引用变量后，由于在栈中已经有3这个字面值，便将b直接指向3的地址。这样，就出现了a与b同时均指向3的情况。<br />
<br />
　　特别注意的是，这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象，如果一个对象引用变量修改了这个对象的内部状态，那么另一个对象引用变量也即刻反映出这个变化。相反，通过字面值的引用来修改其值，不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例，我们定义完a与b的值后，再令a=4；那么，b不会等于4，还是等于3。在编译器内部，遇到a=4；时，它就会重新搜索栈中是否有4的字面值，如果没有，重新开辟地址存放4的值；如果已经有了，则直接将a指向这个地址。因此a值的改变不会影响到b的值。<br />
<br />
　　另一种是包装类数据，如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中，Java用new()语句来显示地告诉编译器，在运行时才根据需要动态创建，因此比较灵活，但缺点是要占用更多的时间。 4. String是一个特殊的包装类数据。即可以用String str = new String("abc");的形式来创建，也可以用String str = "abc"；的形式来创建(作为对比，在JDK 5.0之前，你从未见过Integer i = 3;的表达式，因为类与字面值是不能通用的，除了String。而在JDK 5.0中，这种表达式是可以的！因为编译器在后台进行Integer i = new Integer(3)的转换)。前者是规范的类的创建过程，即在Java中，一切都是对象，而对象是类的实例，全部通过new()的形式来创建。Java中的有些类，如DateFormat类，可以通过该类的getInstance()方法来返回一个新创建的类，似乎违反了此原则。其实不然。该类运用了单例模式来返回类的实例，只不过这个实例是在该类内部通过new()来创建的，而getInstance()向外部隐藏了此细节。那为什么在String str = "abc"；中，并没有通过new()来创建实例，是不是违反了上述原则？其实没有。<br />
<br />
　　5. 关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤：<br />
<br />
　　(1)先定义一个名为str的对String类的对象引用变量：String str；<br />
<br />
　　(2)在栈中查找有没有存放值为"abc"的地址，如果没有，则开辟一个存放字面值为"abc"的地址，接着创建一个新的String类的对象o，并将o的字符串值指向这个地址，而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址，则查找对象o，并返回o的地址。<br />
<br />
　　(3)将str指向对象o的地址。<br />
<br />
　　值得注意的是，一般String类中字符串值都是直接存值的。但像String str = "abc"；这种场合下，其字符串值却是保存了一个指向存在栈中数据的引用！<br />
<br />
　　为了更好地说明这个问题，我们可以通过以下的几个代码进行验证。<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>String str1 = "abc";<br />
            String str2 = "abc";<br />
            System.out.println(str1==str2); //true</td>
        </tr>
    </tbody>
</table>
<br />
　　注意，我们这里并不用str1.equals(str2)；的方式，因为这将比较两个字符串的值是否相等。==号，根据JDK的说明，只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是，str1与str2是否都指向了同一个对象。<br />
结果说明，JVM创建了两个引用str1和str2，但只创建了一个对象，而且两个引用都指向了这个对象。<br />
<br />
　　我们再来更进一步，将以上代码改成：<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>String str1 = "abc";<br />
            String str2 = "abc";<br />
            str1 = "bcd";<br />
            System.out.println(str1 + "," + str2); //bcd, abc<br />
            System.out.println(str1==str2); //false</td>
        </tr>
    </tbody>
</table>
<br />
　　这就是说，赋值的变化导致了类对象引用的变化，str1指向了另外一个新对象！而str2仍旧指向原来的对象。上例中，当我们将str1的值改为"bcd"时，JVM发现在栈中没有存放该值的地址，便开辟了这个地址，并创建了一个新的对象，其字符串的值指向这个地址。<br />
<br />
　　事实上，String类被设计成为不可改变(immutable)的类。如果你要改变其值，可以，但JVM在运行时根据新值悄悄创建了一个新对象，然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的，但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中，会带有一定的不良影响。<br />
<br />
　　再修改原来代码：<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>String str1 = "abc";<br />
            String str2 = "abc";<br />
            <br />
            str1 = "bcd";<br />
            <br />
            String str3 = str1;<br />
            System.out.println(str3); //bcd<br />
            <br />
            String str4 = "bcd";<br />
            System.out.println(str1 == str4); //true</td>
        </tr>
    </tbody>
</table>
<br />
　　str3这个对象的引用直接指向str1所指向的对象(注意，str3并没有创建新对象)。当str1改完其值后，再创建一个String的引用str4，并指向因str1修改值而创建的新的对象。可以发现，这回str4也没有创建新的对象，从而再次实现栈中数据的共享。<br />
<br />
　　我们再接着看以下的代码。<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>String str1 = new String("abc");<br />
            String str2 = "abc";<br />
            System.out.println(str1==str2); //false</td>
        </tr>
    </tbody>
</table>
<br />
　　创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。<br />
<br />
<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#dadacf" border="1">
    <tbody>
        <tr>
            <td>String str1 = "abc";<br />
            String str2 = new String("abc");<br />
            System.out.println(str1==str2); //false</td>
        </tr>
    </tbody>
</table>
<br />
　　创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。<br />
<br />
　　以上两段代码说明，只要是用new()来新建对象的，都会在堆中创建，而且其字符串是单独存值的，即使与栈中的数据相同，也不会与栈中的数据共享。<br />
<br />
　　6. 数据类型包装类的值不可修改。不仅仅是String类的值不可修改，所有的数据类型包装类都不能更改其内部的值。 7. 结论与建议：<br />
<br />
　　(1)我们在使用诸如String str = "abc"；的格式定义类时，总是想当然地认为，我们创建了String类的对象str。担心陷阱！对象可能并没有被创建！唯一可以肯定的是，指向String类的引用被创建了。至于这个引用到底是否指向了一个新的对象，必须根据上下文来考虑，除非你通过new()方法来显要地创建一个新的对象。因此，更为准确的说法是，我们创建了一个指向String类的对象的引用变量str，这个对象引用变量指向了某个值为"abc"的String类。清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。<br />
<br />
　　(2)使用String str = "abc"；的方式，可以在一定程度上提高程序的运行速度，因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc")；的代码，则一概在堆中创建新对象，而不管其字符串值是否相等，是否有必要创建新对象，从而加重了程序的负担。这个思想应该是享元模式的思想，但JDK的内部在这里实现是否应用了这个模式，不得而知。<br />
<br />
　　(3)当比较包装类里面的数值是否相等时，用equals()方法；当测试两个包装类的引用是否指向同一个对象时，用==。<br />
<br />
　　(4)由于String类的immutable性质，当String变量需要经常变换其值时，应该考虑使用StringBuffer类，以提高程序效率。<br />
<br />
<img src ="http://www.blogjava.net/caizh2009/aggbug/314570.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-03-05 10:35 <a href="http://www.blogjava.net/caizh2009/archive/2010/03/05/314570.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java  反射</title><link>http://www.blogjava.net/caizh2009/archive/2010/03/04/314532.html</link><dc:creator>小菜毛毛</dc:creator><author>小菜毛毛</author><pubDate>Thu, 04 Mar 2010 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/caizh2009/archive/2010/03/04/314532.html</guid><wfw:comment>http://www.blogjava.net/caizh2009/comments/314532.html</wfw:comment><comments>http://www.blogjava.net/caizh2009/archive/2010/03/04/314532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caizh2009/comments/commentRss/314532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caizh2009/services/trackbacks/314532.html</trackback:ping><description><![CDATA[<font size="+0">&nbsp;
<p><font size="+0">JAVA语言中的反射机制：<br />
&nbsp;&nbsp;&nbsp; 在Java 运行时 环境中，对于任意一个类，能否知道这个类有哪些属性和方法？<br />
&nbsp;&nbsp;&nbsp; 对于任意一个对象，能否调用他的方法？这些答案是肯定的，这种动态获取类的信息，以及动态调用类的方法的功能来源于JAVA的反射。从而使java具有动态语言的特性。</font></p>
<p><font size="+0">&nbsp; <strong>JAVA反射机制主要提供了以下功能：<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.在运行时判断任意一个对象所属的类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.在运行时构造任意一个类的对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3.在运行时判断任意一个类所具有的成员变量和方法（通过反射甚至可以调用private方法）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.在运行时调用任意一个对象的方法（*****注意：前提都是在运行时，而不是在编译时）</font></p>
<p><font size="+0">&nbsp; <strong>Java 反射相关的API简介：</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 位于java。lang。reflect包中<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --Class类：代表一个类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --Filed类：代表类的成员变量<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;--Method类：代表类的方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;--Constructor类：代表类的构造方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;--Array类：提供了动态创建数组，以及访问数组的元素的静态方法。该类中的所有方法都是静态方法</font></p>
<p><font size="+0"><br />
<strong>----Class类<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp; 在 java 的Object类中的申明了数个应该在所有的java类中被改写的methods：<br />
hashCode(), equals(),clone(),toString(),getClass()等，其中的getClass()返回yige<br />
Class 类型的对象。<br />
&nbsp;&nbsp;&nbsp;&nbsp; Class类十分的特殊，它和一般的类一样继承自Object，其实体用以表达java程序运行<br />
时的 class和 interface，也用来表达 enum，array，primitive，Java Types 以及关键字void<br />
，当加载一个类，或者当加载器（class loader）的defineClass（）被JVM调用，便产生一个Class<br />
对象，<br />
&nbsp;&nbsp;&nbsp;&nbsp; Class是Reflection起源，针对任何你想探勘的class（类），唯有现为他产生一个Class<br />
的对象，接下来才能经由后者唤起为数十多个的反射API。</font></p>
<p><font size="+0"><br />
&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color="#ff0000"> Java允许我们从多种途径为一个类class生成对应的Class对象。<br />
</font></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --运用 getClass（）：Object类中的方法，每个类都拥有此方法 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; String str="abc";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;Class cl=str.getClass();</font></p>
<p><font size="+0"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --运用 Class。getSuperclass（）：Class类中的方法，返回该Class的父类的Class<br />
&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; --运用 Class。forName（）静态方法：<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;--运用 ,Class：类名.class<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;--运用primitive wrapper classes的TYPE语法： 基本类型包装类的TYPE，如：Integer.TYPE<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;注意：TYPE的使用，只适合原生（基本）数据类型</font></p>
<p><font size="+0"><strong>----运行时生成instance</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp; 想生成对象的实体，在反射动态机制中有两种方法，一个针对无变量的构造方法，一个针对带参数的<br />
构造方法，，如果想调用带参数的构造方法，就比较的麻烦，不能直接调用Class类中的newInstance（）<br />
，而是调用Constructor类中newInstance（）方法，首先准备一个Class[]作为Constructor的参数类型。<br />
然后调用该Class对象的getConstructor（）方法获得一个专属的Constructor的对象，最后再准备一个<br />
Object[]作为Constructor对象昂的newInstance（）方法的实参。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">在这里需要说明的是 只有两个类拥有newInstance（）方法，分别是Class类和Constructor类<br />
Class类中的newInstance（）方法是不带参数的，而Constructro类中的newInstance（）方法是带参数的<br />
需要提供必要的参数。</font><br />
&nbsp;&nbsp;&nbsp; 例:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class c=Class.forName("DynTest");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class[] ptype=new Class[]{double.class,int.class}；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Constructor ctor=c.getConstructor(ptypr);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object[] obj=new Object[]{new Double(3.1415),new Integer(123)};<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object object=ctor.newInstance(obj);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(object);</font></p>
<p><font size="+0"><strong>----运行时调用Method</strong><br />
&nbsp;&nbsp;&nbsp; 这个动作首先准备一个Class[]{}作为getMethod（String name，Class[]）方法的参数类型，接下来准备一个<br />
Obeject[]放置自变量，然后调用Method对象的invoke（Object obj，Object[]）方法。<br />
&nbsp;&nbsp;&nbsp;&nbsp; 注意，在这里调用</font></p>
<p><font size="+0"><strong>----运行时调用Field内容</strong><br />
&nbsp;&nbsp;&nbsp; 变更Field不需要参数和自变量，首先调用Class的getField（）并指定field名称，获得特定的Field对象后<br />
便可以直接调用Field的 get（Object obj）和set(Object obj,Object value)方法</font></p>
<font size="+0">
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">package</span><span>&nbsp;cn.<span class="hilite3">com</span>.reflection; &nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;java.lang.reflect.Field; &nbsp;&nbsp;</span>
    <li class=""><span><span class="keyword">import</span><span>&nbsp;java.lang.reflect.InvocationTargetException; &nbsp;&nbsp;</span>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;java.lang.reflect.Method; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;ReflectTester&nbsp;{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;在这个类里面存在有copy（）方法，根据指定的方法的参数去&nbsp;构造一个新的对象的拷贝 </span>&nbsp;</span>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;并将他返回 </span>&nbsp;</span>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;NoSuchMethodException&nbsp; </span>&nbsp;</span>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;InvocationTargetException&nbsp; </span>&nbsp;</span>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;IllegalAccessException&nbsp; </span>&nbsp;</span>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;InstantiationException&nbsp; </span>&nbsp;</span>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;SecurityException&nbsp; </span>&nbsp;</span>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@throws&nbsp;IllegalArgumentException&nbsp; </span>&nbsp;</span>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Object&nbsp;copy(Object&nbsp;obj)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;IllegalArgumentException,&nbsp;SecurityException,&nbsp;InstantiationException,&nbsp;IllegalAccessException,&nbsp;InvocationTargetException,&nbsp;NoSuchMethodException{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//获得对象的类型 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;classType=obj.getClass(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"该对象的类型是："</span><span>+classType.toString()); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//通过默认构造方法去创建一个新的对象，getConstructor的视其参数决定调用哪个构造方法 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;objectCopy=classType.getConstructor(</span><span class="keyword">new</span><span>&nbsp;Class[]{}).newInstance(</span><span class="keyword">new</span><span>&nbsp;Object[]{}); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//获得对象的所有属性 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field[]&nbsp;fields=classType.getDeclaredFields(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">for</span><span>(</span><span class="keyword">int</span><span>&nbsp;i=</span><span class="number">0</span><span>;i </span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//获取数组中对应的属性 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;field=fields[i]; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;fieldName=field.getName(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;stringLetter=fieldName.substring(</span><span class="number">0</span><span>,&nbsp;</span><span class="number">1</span><span>).toUpperCase(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//获得相应属性的getXXX和setXXX方法名称 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;getName=</span><span class="string">"get"</span><span>+stringLetter+fieldName.substring(</span><span class="number">1</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;setName=</span><span class="string">"set"</span><span>+stringLetter+fieldName.substring(</span><span class="number">1</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//获取相应的方法 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;getMethod=classType.getMethod(getName,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Class[]{}); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;setMethod=classType.getMethod(setName,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Class[]{field.getType()}); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//调用源对象的getXXX（）方法 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;value=getMethod.invoke(obj,&nbsp;</span><span class="keyword">new</span><span>&nbsp;Object[]{}); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(fieldName+</span><span class="string">"&nbsp;:"</span><span>+value); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//调用拷贝对象的setXXX（）方法 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setMethod.invoke(objectCopy,</span><span class="keyword">new</span><span>&nbsp;Object[]{value}); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;objectCopy; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;IllegalArgumentException,&nbsp;SecurityException,&nbsp;InstantiationException,&nbsp;IllegalAccessException,&nbsp;InvocationTargetException,&nbsp;NoSuchMethodException&nbsp;{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Customer&nbsp;customer=</span><span class="keyword">new</span><span>&nbsp;Customer(); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;customer.setName(</span><span class="string">"hejianjie"</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;customer.setId(</span><span class="keyword">new</span><span>&nbsp;Long(</span><span class="number">1234</span><span>)); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;customer.setAge(</span><span class="number">19</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Customer&nbsp;customer2=</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;customer2=(Customer)</span><span class="keyword">new</span><span>&nbsp;ReflectTester().copy(customer); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(customer.getName()+</span><span class="string">"&nbsp;"</span><span>+customer2.getAge()+</span><span class="string">"&nbsp;"</span><span>+customer2.getId()); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(customer); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(customer2); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li class=""><span><span class="keyword">class</span><span>&nbsp;Customer{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;Long&nbsp;id; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;String&nbsp;name; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;age; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Customer(){ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;getAge()&nbsp;{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;age; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setAge(</span><span class="keyword">int</span><span>&nbsp;age)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.age&nbsp;=&nbsp;age; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Long&nbsp;getId()&nbsp;{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;id; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setId(Long&nbsp;id)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.id&nbsp;=&nbsp;id; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;String&nbsp;getName()&nbsp;{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;name; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setName(String&nbsp;name)&nbsp;{ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.name&nbsp;=&nbsp;name; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p><br />
</p>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar">
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">package</span><span>&nbsp;cn.com.reflection; &nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;java.lang.reflect.Array; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;ArrayTester1&nbsp;{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp;
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;此类根据反射来创建 </span>&nbsp;</span>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;一个动态的数组&nbsp; </span>&nbsp;</span>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;ClassNotFoundException&nbsp;{ &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;classType=Class.forName(</span><span class="string">"java.lang.String"</span><span>); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;array=&nbsp;Array.newInstance(classType,</span><span class="number">10</span><span>);&nbsp;&nbsp;</span><span class="comment">//指定数组的类型和大小 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//对索引为5的位置进行赋值 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Array.set(array,&nbsp;</span><span class="number">5</span><span>,&nbsp;</span><span class="string">"hello"</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s=(String)Array.get(array,&nbsp;</span><span class="number">5</span><span>); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(s); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//循环遍历这个动态数组 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">for</span><span>(</span><span class="keyword">int</span><span>&nbsp;i=</span><span class="number">0</span><span>;i&lt;((String[])array).length;i++){ &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str=(String)Array.get(array,&nbsp;i); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(str); &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>} &nbsp;&nbsp;</span> </li>
</ol>
</div>
</font></font></div>
<div id="topic_copyright">声明：JavaEye文章版权属于作者，受法律保护。没有作者书面许可不得转载。 </div>
<div id="forum_recommended_f5"><span>推荐链接</span>
<ul></ul>
    </div>
    </span></span></span></span></span></span></span></div>
 <img src ="http://www.blogjava.net/caizh2009/aggbug/314532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caizh2009/" target="_blank">小菜毛毛</a> 2010-03-04 16:43 <a href="http://www.blogjava.net/caizh2009/archive/2010/03/04/314532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>