﻿<?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-Junky's IT Notebook-随笔分类-java</title><link>http://www.blogjava.net/junky/category/11397.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 07 Mar 2008 03:07:21 GMT</lastBuildDate><pubDate>Fri, 07 Mar 2008 03:07:21 GMT</pubDate><ttl>60</ttl><item><title>Java正则表达式详解</title><link>http://www.blogjava.net/junky/archive/2008/03/05/184018.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 05 Mar 2008 07:52:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2008/03/05/184018.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/184018.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2008/03/05/184018.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/184018.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/184018.html</trackback:ping><description><![CDATA[如果你曾经用过Perl或任何其他内建正则表达式支持的语言，你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语，那么&#8220;正则表达式&#8221;（Regular Expression）就是一个字符构成的串，它定义了一个用来搜索匹配字符串的模式。
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">许多语言，包括Perl、PHP、Python、JavaScript和JScript，都支持用正则表达式处理文本，一些文本编辑器用正则表达式实现高 级&#8220;搜索-替换&#8221;功能。那么Java又怎样呢？本文写作时，一个包含了用正则表达式进行文本处理的Java规范需求（Specification Request）已经得到认可，你可以期待在JDK的下一版本中看到它。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">然而，如果现在就需要使用正则表达式，又该怎么办呢？你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识，然后以Jakarta-ORO API为例介绍如何使用正则表达式。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong><font size="4">一、正则表达式基础知识</font></strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">我们先从简单的开始。假设你要搜索一个包含字符&#8220;cat&#8221;的字符串，搜索用的正则表达式就是&#8220;cat&#8221;。如果搜索对大小写不敏感，单词&#8220;catalog&#8221;、&#8220;Catherine&#8221;、&#8220;sophisticated&#8221;都可以匹配。也就是说：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_a.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>1.1 句点符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">假设你在玩英文拼字游戏，想要找出三个字母的单词，而且这些单词必须以&#8220;t&#8221;字母开头，以&#8220;n&#8221;字母结束。另外，假设有一本英文字典，你可以用正则表达式 搜索它的全部内容。要构造出这个正则表达式，你可以使用一个通配符——句点符号&#8220;.&#8221;。这样，完整的表达式就是&#8220;t.n&#8221;，它匹配&#8220;tan&#8221;、 &#8220;ten&#8221;、&#8220;tin&#8221;和&#8220;ton&#8221;，还匹配&#8220;t#n&#8221;、&#8220;tpn&#8221;甚至&#8220;t n&#8221;，还有其他许多无意义的组合。这是因为句点符号匹配所有字符，包括空格、Tab字符甚至换行符：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_b.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>1.2 方括号符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">为了解决句点符号匹配范围过于广泛这一问题，你可以在方括号（&#8220;[]&#8221;）里面指定看来有意义的字符。此时，只有方括号里面指定的字符才参与匹配。也就是 说，正则表达式&#8220;t[aeio]n&#8221;只匹配&#8220;tan&#8221;、&#8220;Ten&#8221;、&#8220;tin&#8221;和&#8220;ton&#8221;。但&#8220;Toon&#8221;不匹配，因为在方括号之内你只能匹配单个字 符：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_c.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>1.3 &#8220;或&#8221;符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">如果除了上面匹配的所有单词之外，你还想要匹配&#8220;toon&#8221;，那么，你可以使用&#8220;|&#8221;操作符。&#8220;|&#8221;操作符的基本意义就是&#8220;或&#8221;运算。要匹配 &#8220;toon&#8221;，使用&#8220;t(a|e|i|o|oo)n&#8221;正则表达式。这里不能使用方扩号，因为方括号只允许匹配单个字符；这里必须使用圆括号&#8220;()&#8221;。圆括 号还可以用来分组，具体请参见后面介绍。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_d.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>1.4 表示匹配次数的符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">表一显示了表示匹配次数的符号，这些符号用来确定紧靠该符号左边的符号出现的次数：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4n.jpg" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中，连字符 （&#8220;-&#8221;）有着特殊的意义，它表示一个范围，比如从0到9。因此，匹配社会安全号码中的连字符号时，它的前面要加上一个转义字符&#8220;\&#8221;。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4a.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图一：匹配所有123-12-1234形式的社会安全号码</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">假设进行搜索的时候，你希望连字符号可以出现，也可以不出现——即，999-99-9999和999999999都属于正确的格式。这时，你可以在连字符号后面加上&#8220;？&#8221;数量限定符号，如图二所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4b.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图二：匹配所有123-12-1234和123121234形式的社会安全号码</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分&#8220;[0-9]{4}&#8221;，再加上字母部分&#8220;[A-Z]{2}&#8221;。图三显示了完整的正则表达式。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4c.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图三：匹配典型的美国汽车牌照号码，如8836KV</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">1.5 &#8220;否&#8221;符号</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">&#8220;^&#8221;符号称为&#8220;否&#8221;符号。如果用在方括号内，&#8220;^&#8221;表示不想要匹配的字符。例如，图四的正则表达式匹配所有单词，但以&#8220;X&#8221;字母开头的单词除外。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4d.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图四：匹配所有单词，但&#8220;X&#8221;开头的除外</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">1.6 圆括号和空白符号</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">假设要从格式为&#8220;June 26, 1951&#8221;的生日日期中提取出月份部分，用来匹配该日期的正则表达式可以如图五所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4e.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图五：匹配所有Moth DD,YYYY格式的日期</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">新出现的&#8220;\s&#8221;符号是空白符号，匹配所有的空白字符，包括Tab字符。如果字符串正确匹配，接下来如何提取出月份部分呢？只需在月份周围加上一个圆括号创建一个组，然后用ORO API（本文后面详细讨论）提取出它的值。修改后的正则表达式如图六所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4f.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图六：匹配所有Month DD,YYYY格式的日期，定义月份值为第一个组</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>1.7 其它符号</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">为简便起见，你可以使用一些为常见正则表达式创建的快捷符号。如表二所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">表二：常用符号</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4o.jpg" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">例如，在前面社会安全号码的例子中，所有出现&#8220;[0-9]&#8221;的地方我们都可以使用&#8220;\d&#8221;。修改后的正则表达式如图七所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4g.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图七：匹配所有123-12-1234格式的社会安全号码</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong><font size="4">二、Jakarta-ORO库</font></strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">有许多源代码开放的正则表达式库可供Java程序员使用，而且它们中的许多支持Perl 5兼容的正则表达式语法。我在这里选用的是Jakarta-ORO正则表达式库，它是最全面的正则表达式API之一，而且它与Perl 5正则表达式完全兼容。另外，它也是优化得最好的API之一。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">Jakarta-ORO库以前叫做OROMatcher，Daniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下载它。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">我首先将简要介绍使用Jakarta-ORO库时你必须创建和访问的对象，然后介绍如何使用Jakarta-ORO API。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>▲ PatternCompiler对象</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">首先，创建一个Perl5Compiler类的实例，并把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实现，允许你把正则表达式编译成用来匹配的Pattern对象。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_e.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>▲ Pattern对象</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">要把正则表达式编译成Pattern对象，调用compiler对象的compile()方法，并在调用参数中指定正则表达式。例如，你可以按照下面这种方式编译正则表达式&#8220;t[aeio]n&#8221;：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_f.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">默认情况下，编译器创建一个大小写敏感的模式（pattern）。因此，上面代码编译得到的模式只匹配&#8220;tin&#8221;、&#8220;tan&#8221;、 &#8220;ten&#8221;和&#8220;ton&#8221;，但不匹配&#8220;Tin&#8221;和&#8220;taN&#8221;。要创建一个大小写不敏感的模式，你应该在调用编译器的时候指定一个额外的参数：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_g.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">创建好Pattern对象之后，你就可以通过PatternMatcher类用该Pattern对象进行模式匹配。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>▲ PatternMatcher对象</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">PatternMatcher对象根据Pattern对象和字符串进行匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给 PatternMatcher接口。Perl5Matcher类是PatternMatcher接口的一个实现，它根据Perl 5正则表达式语法进行模式匹配：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_h.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">使用PatternMatcher对象，你可以用多个方法进行匹配操作，这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">&#183; boolean matches(String input, Pattern pattern)：当输入字符串和正则表达式要精确匹配时使用。换句话说，正则表达式必须完整地描述输入字符串。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">&#183; boolean matchesPrefix(String input, Pattern pattern)：当正则表达式匹配输入字符串起始部分时使用。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">&#183; boolean contains(String input, Pattern pattern)：当正则表达式要匹配输入字符串的一部分时使用（即，它必须是一个子串）。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">另外，在上面三个方法调用中，你还可以用PatternMatcherInput对象作为参数替代String对象；这时，你可以从字符串中最后一次匹配 的位置开始继续进行匹配。当字符串可能有多个子串匹配给定的正则表达式时，用PatternMatcherInput对象作为参数就很有用了。用 PatternMatcherInput对象作为参数替代String时，上述三个方法的语法如下：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">&#183; boolean matches(PatternMatcherInput input, Pattern pattern)</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">&#183; boolean matchesPrefix(PatternMatcherInput input, Pattern pattern)</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">&#183; boolean contains(PatternMatcherInput input, Pattern pattern)</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong><font size="4">三、应用实例</font></strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">下面我们来看看Jakarta-ORO库的一些应用实例。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>3.1 日志文件处理</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">任务：分析一个Web服务器日志文件，确定每一个用户花在网站上的时间。在典型的BEA WebLogic日志文件中，日志记录的格式如下：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_i.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">分析这个日志记录，可以发现，要从这个日志文件提取的内容有两项：IP地址和页面访问时间。你可以用分组符号（圆括号）从日志记录提取出IP地址和时间标记。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">首先我们来看看IP地址。IP地址有4个字节构成，每一个字节的值在0到255之间，各个字节通过一个句点分隔。因此，IP地址中的每一个字节有至少一个、最多三个数字。图八显示了为IP地址编写的正则表达式：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4h.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图八：匹配IP地址</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">IP地址中的句点字符必须进行转义处理（前面加上&#8220;\&#8221;），因为IP地址中的句点具有它本来的含义，而不是采用正则表达式语法中的特殊含义。句点在正则表达式中的特殊含义本文前面已经介绍。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">日志记录的时间部分由一对方括号包围。你可以按照如下思路提取出方括号里面的所有内容：首先搜索起始方括号字符（&#8220;[&#8221;），提取出所有不超过结束方括号字符（&#8220;]&#8221;）的内容，向前寻找直至找到结束方括号字符。图九显示了这部分的正则表达式。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4i.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图九：匹配至少一个字符，直至找到&#8220;]&#8221;</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">现在，把上述两个正则表达式加上分组符号（圆括号）后合并成单个表达式，这样就可以从日志记录提取出IP地址和时间。注意，为了匹配&#8220;- -&#8221;（但不提取它），正则表达式中间加入了&#8220;\s-\s-\s&#8221;。完整的正则表达式如图十所示。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4j.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图十：匹配IP地址和时间标记</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">现在正则表达式已经编写完毕，接下来可以编写使用正则表达式库的Java代码了。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">为使用Jakarta-ORO库，首先创建正则表达式字符串和待分析的日志记录字符串：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_j.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">这里使用的正则表达式与图十的正则表达式差不多完全相同，但有一点例外：在Java中，你必须对每一个向前的斜杠（&#8220;\&#8221;）进行转义处理。图十不是 Java的表示形式，所以我们要在每个&#8220;\&#8221;前面加上一个&#8220;\&#8221;以免出现编译错误。遗憾的是，转义处理过程很容易出现错误，所以应该小心谨慎。你可以首先 输入未经转义处理的正则表达式，然后从左到右依次把每一个&#8220;\&#8221;替换成&#8220;\\&#8221;。如果要复检，你可以试着把它输出到屏幕上。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">初始化字符串之后，实例化PatternCompiler对象，用PatternCompiler编译正则表达式创建一个Pattern对象：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_k.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">现在，创建PatternMatcher对象，调用PatternMatcher接口的contain()方法检查匹配情况：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_l.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">接下来，利用PatternMatcher接口返回的MatchResult对象，输出匹配的组。由于logEntry字符串包含匹配的内容，你可以看到类如下面的输出：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_m.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>3.2 HTML处理实例一</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">下面一个任务是分析HTML页面内FONT标记的所有属性。HTML页面内典型的FONT标记如下所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><font face="Arial, Serif" color="red" size="+2"></font><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_n.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">程序将按照如下形式，输出每一个FONT标记的属性：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_o.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">在这种情况下，我建议你使用两个正则表达式。第一个如图十一所示，它从字体标记提取出&#8220;"face="Arial, Serif" size="+2" color="red"&#8221;。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4k.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图十一：匹配FONT标记的所有属性</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">第二个正则表达式如图十二所示，它把各个属性分割成名字-值对。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4l.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图十二：匹配单个属性，并把它分割成名字-值对</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">分割结果为：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_p.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">现在我们来看看完成这个任务的Java代码。首先创建两个正则表达式字符串，用Perl5Compiler把它们编译成Pattern对象。编译正则表达 式的时候，指定Perl5Compiler.CASE_INSENSITIVE_MASK选项，使得匹配操作不区分大小写。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">接下来，创建一个执行匹配操作的Perl5Matcher对象。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_q.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">假设有一个String类型的变量html，它代表了HTML文件中的一行内容。如果html字符串包含FONT标记，匹配器将返回true。此时，你可以用匹配器对象返回的MatchResult对象获得第一个组，它包含了FONT的所有属性：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_r.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">接下来创建一个PatternMatcherInput对象。这个对象允许你从最后一次匹配的位置开始继续进行匹配操作，因此，它很适合于提取FONT标 记内属性的名字-值对。创建PatternMatcherInput对象，以参数形式传入待匹配的字符串。然后，用匹配器实例提取出每一个FONT的属 性。这通过指定PatternMatcherInput对象（而不是字符串对象）为参数，反复地调用PatternMatcher对象的contains ()方法完成。PatternMatcherInput对象之中的每一次迭代将把它内部的指针向前移动，下一次检测将从前一次匹配位置的后面开始。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">本例的输出结果如下：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_s.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><strong>3.3 HTML处理实例二</strong></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">下面我们来看看另一个处理HTML的例子。这一次，我们假定Web服务器从widgets.acme.com移到了newserver.acme.com。现在你要修改一些页面中的链接：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_t.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">执行这个搜索的正则表达式如图十三所示：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4m.gif" border="0"  alt="" /></p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">
            <p align="center">图十三：匹配修改前的链接</p>
            </td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">如果能够匹配这个正则表达式，你可以用下面的内容替换图十三的链接：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_u.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">注意#字符的后面加上了$1。Perl正则表达式语法用$1、$2等表示已经匹配且提取出来的组。图十三的表达式把所有作为一个组匹配和提取出来的内容附加到链接的后面。</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">现在，返回Java。就象前面我们所做的那样，你必须创建测试字符串，创建把正则表达式编译到Pattern对象所必需的对象，以及创建一个PatternMatcher对象：<img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_v.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">接下来，用com.oroinc.text.regex包Util类的substitute()静态方法进行替换，输出结果字符串：</td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_w.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">Util.substitute()方法的语法如下：</td>
        </tr>
    </tbody>
</table>
<table height="17" width="620" align="center">
    <tbody>
        <tr>
            <td class="a14" height="13"><img src="http://www.ccw.com.cn/htm/app/aprog/01_7_31_4_x.jpg" border="0"  alt="" /></td>
        </tr>
    </tbody>
</table>
<table width="620" align="center">
    <tbody>
        <tr>
            <td class="a14">这个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象，它决定了替换操作如 何进行。本例使用的是Perl5Substitution对象，它能够进行Perl5风格的替换。第四个参数是想要进行替换操作的字符串，最后一个参数允 许指定是否替换模式的所有匹配子串（Util.SUBSTITUTE_ALL），或只替换指定的次数。</td>
        </tr>
    </tbody>
</table>
<strong>【结束语】</strong>在 这篇文章中，我为你介绍了正则表达式的强大功能。只要正确运用，正则表达式能够在字符串提取和文本修改中起到很大的作用。另外，我还介绍了如何在Java 程序中通过Jakarta-ORO库利用正则表达式。至于最终采用老式的字符串处理方式（使用StringTokenizer，charAt，和 substring），还是采用正则表达式，这就有待你自己决定了。
<img src ="http://www.blogjava.net/junky/aggbug/184018.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2008-03-05 15:52 <a href="http://www.blogjava.net/junky/archive/2008/03/05/184018.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaFX应用问题解答</title><link>http://www.blogjava.net/junky/archive/2007/09/29/149502.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sat, 29 Sep 2007 02:57:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/09/29/149502.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/149502.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/09/29/149502.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/149502.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/149502.html</trackback:ping><description><![CDATA[<strong><span style="font-size: 14px"><span style="color: blue"><a href="http://www.matrix.org.cn/resource/article/2007-09-24/user.shtml?userid=66080">cleverpig</a> 发表于 2007-09-24 12:30:35<br />
作者:cleverpig&nbsp;&nbsp;&nbsp;&nbsp; 来源:OpenJFX&amp;Matrix<br />
评论数:0 点击数:261&nbsp;&nbsp;&nbsp;&nbsp; 投票总得分:5 投票总人次:1<br />
关键字:JavaFX FAQ 解答 <!-- end of div title --><br />
<br />
<br />
常见问题</span></span></strong><br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX是什么？</span></span></strong><br />
<br />
&#8220;JavaFX脚本是一种声明式、静态类型编程语言。它具有一等函数（first-class functions）、声明式的语法、列表推导（list-comprehensions）及基于依赖关系的增量式求值（incremental dependency-based evaluation）等特征。&#8221;JavaFX脚本为多种多样的操作提供了声明式、无中间程序逻辑的语法，这些操作包括创建2D动画、设置属性或者声明在模式和视图对象之间的绑定依赖关系。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">什么样的函数能够称为&#8220;first-class functions&#8221;?</span></span></strong><br />
<br />
在编程语言中，我们常常把那些将函数作为一等对象的函数称为一等函数（first-class functions）。具体地说，就是编程语言支持在程序执行过程中构造新的函数，并将它们存储在数据结构中作为其它函数的参数的传入参数，并在函数返回时将它们作为函数值返回。本概念并不涵盖任何语言和程序的外部函数或者程序，例如通过调用编译器或者一个eval函数来创建新函数。<br />
这里提供一等函数的一个简单示例：map或者mapcar函数，它使用一个函数和一个列表作为参数，然后将通过将函数应用到列表中的每个成员后形成的列表作为返回值。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">&#8220;declarative syntax&#8221;是什么意思? </span></span></strong><br />
<br />
与大多数依靠程序和显式代码来更新在变量或者属性之间关系的编程语言不同，声明式语言允许数值被声明为另一种方式。<br />
在JavaFX的一个示例：<br />
<pre class="overflow">var a : Number = bind model.attrib/2;</pre>
<br />
无论何时model.attrib的数值发生改变，a的数值都将自动、透明地更新，更新期间无需调用任何程序。这对于在模式和视图对象之间绑定依赖关系、控制GUI行为是特别有用的。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">&#8220;list-comprehensions&#8221;是什么意思? </span></span></strong><br />
<br />
我们常常把&#8220;list-comprehensions&#8221;翻译为&#8220;列表推导&#8221;。列表推导是在语言级别上支持以多种方式创建、维护列表的方法。<br />
在JavaFX中的一些示例：<br />
<pre class="overflow">var nums = [1,2,3,4]; <br />
var nums2 = [1..4]; //same as above <br />
var numsGreaterThanTwo = nums[. &gt; 2]; <br />
var numsLessThanFour = select n from n in nums where n &lt; 4; </pre>
<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">什么是"incremental dependency-based evaluation"? </span></span></strong><br />
<br />
&#8220;incremental dependency-based evaluation&#8221;译为&#8220;基于依赖关系的增量式求值&#8221;。在JavaFX中，属性值能够被声明为依赖于（绑定到）包含其它属性的表达式。这样，当某个被引用的属性数值发生变化时，所有依赖此属性的属性都将直接或者间接地改变它们的数值，此过程无需调用任何的中间程序逻辑。这和在Excel之类的电子表格中使用方程式很类似。<br />
这对于那些需要动态维护模式和视图属性，而又时常需要复杂的程序逻辑的GUI开发来说非常有用。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">&#8220;操作（operation）&#8221; vs &#8220;函数（function）&#8221;</span></span></strong><br />
<br />
函数与操作之间的不同之处是函数可以递增地反复求值、可以绑定返回值、绑定参数、绑定变量/属性，隐性绑定本地变量。<br />
为了进一步说明，请看下面的JavaFX代码片段：<br />
<pre class="overflow">Class Foo (<br />
&nbsp;&nbsp; attribute zap;<br />
&nbsp;&nbsp; function bar(x) { x + zap }<br />
}<br />
var afoo = Foo { zap: 14 }<br />
var zing = 1;<br />
var snap = afoo.bar(zing);<br />
bind dyn = afoo.bar(zing);</pre>
<br />
我们非常清楚地看到：无论zing和zap如何变化，snap将不会发生变化。而dyn则会随着zing和zap的变化而改变。因为在zing和zap的数值发生变化时，发生了一个增量式的求值过程：程序将变化的数值传递给依赖其的所有函数，并重新计算数值。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX的授权模式是怎么的?</span></span></strong><br />
<br />
JavaFX的开发者很赞同让用户发布自己的应用，并坚信开源和社区的力量。但当前的JavaFX版本是在评估授权下发布的，因此并不能够被重新发布。你当然能够发布自己编写的基于JavaFX的应用，但不能够和JavaFX一起捆绑发布，并需要告之使用者：需要到openjfx项目站点下载JavaFX二进制代码库。并且，由于正处于早期的JavaFX代码还处在评估授权下，因此它不能用于商业用途。当Sun完成了JavaFX的商业化版本开发后，我相信这将会得到改变。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">Sun是否规定了发布JavaFX商业化产品的时间线?</span></span></strong><br />
<br />
很抱歉，目前没有准确的时间约定，不过马上就会制定出来。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX Runtime像JavaFX Script那样开源吗？</span></span></strong><br />
<br />
是的，JavaFX Runtime即将开放源代码。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">在JavaFX和&#8230;之间的不同</span></span></strong><br />
<br />
<strong>与F3比较：</strong>F3是Form Follows Function的缩写，这是JavaFX平台从前的名字。<br />
<br />
<strong>与Java比较：</strong>JavaFX 是一种兼容JSR-223的脚本语言。它能够使用Java类，并从Java类中被调用。<br />
<br />
<strong>与Java 6.0提供的Scriting Engine比较：</strong>Java 6.0提供的Scriting Engine为兼容JSR-223的脚本语言提供了运行平台，JavaFX可以在Java 6.0提供的Scriting Engine上执行。而JavaFX并不依赖于Java 6.0，它可以在任何兼容JSR-223的脚本引擎（比如javax.script.ScriptEngine）下执行。<br />
<br />
<strong>与SVG比较：</strong>SVG并不是一种程序语言；它是一种数据描述语言。其XML语法对于编程语言来讲是非常可怕的。但SVG的交互性、兼容性是令人满意的。目前JavaFX开发团队并没有计划直接使用SVG。由于SVG和JavaFX都源自旧的PostScript和Java2D向量图形模式，因此在某种程度上，我们已经在JavaFX中使用了SVG，但目前仍然存在某些值得注意的不兼容性。<br />
<a href="http://blogs.sun.com/chrisoliver/entry/javafx_svg_translator_preview" target="_new">Chris Oliver 已经编写了SVG-to-F3 转换程序</a>。<br />
<br />
<strong>与Swing比较：</strong>JavaFX是一种编写Swing应用的新方式，它无需了解swing框架和java语言。<br />
<br />
<strong>与JavaScript比较：</strong>在JavaFX和JavaScript之间唯一相同点就是它们都是兼容JSR-223的脚本语言。<br />
<br />
<strong>与Ajax比较：</strong>Ajax是使用了JavaScript和异步更新的web浏览器端技术。它与JavaFX的关系：两者都是UI相关的技术。但它们在语言和环境上完全不同。<br />
<br />
<strong>与Savaje OS的关系：</strong>Sun正在计划使用它们购买的Saveje手机系统和JVM来发布JavaFX Mobile，后者能在移动设备上运行JavaFX脚本，它将成为Windows Mobile、Flash Lite的有力竞争者。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">我能够使用JavaFX编写Java3D应用吗？它兼容VRML或者X3D标准、Xj3D之类的代码库吗？ </span></span></strong><br />
<br />
没有原因不能使用。JavaFX能够和任何第三方代码库互操作，并且不需要任何特殊语法。目前JavaFX开发团队正在进行开发支持Java3D的功能。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX是一种RCP(Rich Client Platform) 吗? </span></span></strong><br />
<br />
是的。JavaFX不仅能够用于RCP开发，也能够用于RIA（Rich internet Applications）开发。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">我能够在web应用中使用JavaFX吗? </span></span></strong><br />
<br />
JavaFX能够用于编写前端应用、web应用的视图或者用户接口，不过这都需要JVM的支持。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX将代替Java EE中的JSF和JSP吗? </span></span></strong><br />
<br />
不，JSF和JSP用于编写纯粹的web应用（对于支持HTML的HTTP客户端来讲是可用的），而JavaFX需要位于客户端的JVM。如果你希望编写富客户端的话，那么就需要在客户端安装JRE，JavaFX能够提供与基于Flash的Flex、基于.net的Silverlight相同的功能。常见的应用场景是开发运行在公司内网的应用。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX在运行时需要服务器吗? </span></span></strong><br />
<br />
JavaFX是一种关注GUI的脚本语言；它主要用于桌面应用，因此不需服务器。如果你计划部署JNLP（Java Web Start）的话，那么你需要一台web服务器。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">运行JavaFX需要什么条件? </span></span></strong><br />
<br />
两种条件任选其一：<br />
Java5以上、一个兼容JSR-223的实现、JavaFX代码库；<br />
Java6以上、JavaFX代码库。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">目前有JavaFX可用的编译器吗? </span></span></strong><br />
<br />
OpenFX Compiler是JavaFX编译器项目，目前已经开放源代码。<br />
详细情况请访问：<a href="https://openjfx-compiler.dev.java.net/" target="_new">https://openjfx-compiler.dev.java.net/</a><br />
<br />
<strong><span style="font-size: 14px"><span style="color: blue">开发中遇到的问题</span></span></strong><br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX中有哪些固有的数据类型? </span></span></strong><br />
<br />
JavaFX中的固有数据类型：String、Boolean、Number、Integer。<br />
<br />
JavaFX与Java类型之间的对应关系： <br />
<img style="display: inline" onclick="javascript:imgClick(this);" alt="image" src="http://static.zooomr.com/images/3349259_6456beb09f_o.jpg?r=360" onload="javascript:imgLoad(this);" border="0" resized="0" /><br />
更多信息请访问： <br />
<a href="https://openjfx.dev.java.net/JavaFX_Programming_Language.html#basic_types" target="_new">https://openjfx.dev.java.net/JavaFX_Programming_Language.html#basic_types </a><br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何连接两个字符串？&#8220;+&#8221;操作符已经不起作用了！？</span></span></strong><br />
<br />
与Java有所不同，JavaFX并没有重载&#8220;+&#8221;操作符来使其用于字符串连接：<br />
<pre class="overflow">import javafx.ui.*;<br />
import javafx.ui.canvas.*;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
Frame {<br />
&nbsp;&nbsp;&nbsp;&nbsp;content: Label {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text: "Hello " + "World"<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;visible: true<br />
}<br />
</pre>
<br />
如果尝试运行上面的代码，我们将看到以下的控制台输出：<br />
<pre class="overflow">compile thread: Thread[AWT-EventQueue-0,6,main]<br />
compile 2.031<br />
file:/C:/workspace/F3/HelloWorld.fx:6: incompatible types: expected Number, found String in "Hello "<br />
file:/C:/workspace/F3/HelloWorld.fx:6: incompatible types: expected Number, found String in "World"<br />
file:/C:/workspace/F3/HelloWorld.fx:6: incompatible types: expected String, found Number in text: "Hello " + "World"<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">实现方式之一：修改代码</span></span></strong><br />
<br />
Java实现方法：<br />
<pre class="overflow">String s = "Your score is " + n + " out of " + total + ".";</pre>
<br />
JavaFX的字符串表达式操作符{}实现连接字符串的功能： <br />
<pre class="overflow">var s:String = "Your score is {n} out of {total}.";</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">实现方式之二：调用concat()方法</span></span></strong><br />
<br />
JavaFX提供了concat()方法来连接两个字符串：<br />
<pre class="overflow">import javafx.ui.*;<br />
import javafx.ui.canvas.*;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
Frame {<br />
&nbsp;&nbsp;&nbsp;&nbsp;content: Label {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text: "Hello ".concat("World")<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;visible: true<br />
}<br />
</pre>
<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何将字符串转换为数字? </span></span></strong><br />
<br />
目前没有直接的方式，但可以使用下面的代码：<br />
<pre class="overflow">var value = new DecimalFormat("0").parse(someString);</pre>
<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何将TextField的数值绑定到一个数字类型属性? </span></span></strong><br />
<br />
使用绑定:：<br />
<pre class="overflow">var total = 10<br />
TextField {<br />
&nbsp;&nbsp; value: bind total<br />
&nbsp;&nbsp; ...<br />
}</pre>
<br />
也可以使用format进行格式化：<br />
<pre class="overflow">value: bind "{total format as &lt;&lt;#,##0&gt;&gt;}"</pre>
<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何设置用在Java Web Start上的JavaFX? </span></span></strong><br />
<br />
JNLP (Java Network Launch Protocol)是一种基于XML的协议，它能够在网络上部署Java和JavaFX应用。<br />
这里提供一个用于部署JavaFXPad的JNLP示例。<br />
详细示例请见：<a href="http://download.java.net/general/openjfx/demos/javafxpad.jnlp" target="_new">http://download.java.net/general/openjfx/demos/javafxpad.jnlp</a>) 。<br />
<pre class="overflow">&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;jnlp <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;spec="1.5+" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;codebase="http://download.java.net/general/openjfx/demos"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;href="javafxpad.jnlp"&gt;<br />
&nbsp;&nbsp;&lt;information&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;JavaFX Demos:JavaFX Pad&lt;/title&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;vendor&gt;Sun Microsystems&lt;/vendor&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;offline-allowed /&gt;<br />
&nbsp;&nbsp;&lt;/information&gt;<br />
&nbsp;&nbsp;&lt;security&gt; <br />
&nbsp;&nbsp;&lt;all-permissions/&gt;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&lt;/security&gt; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;resources&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;j2se version="1.5+" href="http://java.sun.com/products/autodl/j2se"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java-vm-args="-Xss1M -Xmx256M"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/j2se&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar href="javafxrt.jar" main="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar href="Filters.jar"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar href="swing-layout.jar"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar href="javafxpad.jar"/&gt;<br />
&nbsp;&nbsp;&lt;/resources&gt;<br />
&nbsp;&nbsp;&lt;application-desc main-class="net.java.javafx.FXShell"&gt;<br />
&nbsp;&nbsp;&lt;argument&gt;javafxpad.Main&lt;/argument&gt;<br />
&nbsp;&nbsp;&lt;/application-desc&gt;<br />
&lt;/jnlp&gt;</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">&#8220;Hello Web Start FX&#8221;示例 </span></span></strong><br />
<br />
环境需求<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226; Java 5 JDK <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226; 从openjfx项目下载后获得的JavaFX代码包中提取出来的/lib/javafxrt.jar and lib/swing-layout.jar<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">&#8220;Hello Web Start JFX&#8221;程序代码</span></span></strong><br />
<br />
文件名: HelloWebStart.fx <br />
<pre class="overflow">import javafx.ui.*;<br />
<br />
Frame {<br />
&nbsp;&nbsp;&nbsp;&nbsp;title&nbsp;&nbsp;: 'Hello Web Start JFX!'<br />
&nbsp;&nbsp;&nbsp;&nbsp;width&nbsp;&nbsp;: 600<br />
&nbsp;&nbsp;&nbsp;&nbsp;height : 400<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;content: Label {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text: 'Hello Web Start JFX!'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;font: Font{size: 32}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;visible: true<br />
}<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">创建 HelloWebStartJFX.jar </span></span></strong><br />
<br />
<pre class="overflow">jar cvf HelloWebStartJFX.jar HelloWebStart.fx</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">创建 HelloWebStartJFX.jnlp </span></span></strong><br />
<br />
文件名: HelloWebStartJFX.jnlp <br />
<pre class="overflow">&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;jnlp spec="1.5+"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;codebase="http://www.example.com/HelloWebStartJFX/"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;href="HelloWebStartJFX.jnlp"&gt;<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;information&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;Hello Web Start JFX&lt;/title&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;vendor&gt;John Doe&lt;/vendor&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;homepage href="http://www.example.com/HelloWebStartJFX/"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;description&gt;Web Start example for JavaFX Scripts&lt;/description&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;offline-allowed/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/information&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;security&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;all-permissions/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/security&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;resources&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;j2se version="1.5+" href="http://java.sun.com/products/autodl/j2se"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/j2se&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar href="javafxrt.jar" main="true"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar href="swing-layout.jar"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;jar href="HelloWebStartJFX.jar"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/resources&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;application-desc main-class="net.java.javafx.FXShell"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument&gt;HelloWebStart&lt;/argument&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/application-desc&gt;<br />
&lt;/jnlp&gt;<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">创建签名密钥 </span></span></strong><br />
<br />
<pre class="overflow">keytool -genkey -alias jfx -dname "CN=John Doe, O=JFX Inc." -validity 9999 -keystore jfx.keystore -keypass keyPassword -storepass storePassword</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">对jar文件进行签名</span></span></strong><br />
<br />
<pre class="overflow">jarsigner -keystore jfx.keystore -verbose -keypass keyPassword -storepass storePassword HelloWebStartJFX.jar jfx<br />
jarsigner -keystore jfx.keystore -verbose -keypass keyPassword -storepass storePassword javafxrt.jar jfx<br />
jarsigner -keystore jfx.keystore -verbose -keypass keyPassword -storepass storePassword swing-layout.jar jfx<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">连接到HelloWebStartJFX.jnlp </span></span></strong><br />
<br />
文件名: index.html <br />
<pre class="overflow">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"<br />
&nbsp;&nbsp;&nbsp;&nbsp; "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;<br />
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;<br />
&nbsp;&nbsp;&lt;head&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;Hello Web Start JFX!&lt;/title&gt;<br />
&nbsp;&nbsp;&lt;/head&gt;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;body&gt;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;h1&gt;Hello Web Start JFX!&lt;/h1&gt;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;&lt;a href="HelloWebStartJFX.jnlp"&gt;Java Web Start: Hello Web Start JFX!&lt;/a&gt;&lt;/p&gt;<br />
&nbsp;&nbsp;&lt;/body&gt;<br />
&lt;/html&gt;<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">Web服务器: 设置用于.jnlp 的MIME类型 </span></span></strong><br />
<br />
Apache服务器:在http.conf 或者 .htaccess文件中添加类型：<br />
<pre class="overflow">application/x-java-jnlp-file JNLP</pre>
<br />
<br />
将文件复制到Web服务器 <br />
<pre class="overflow">mkdir /www/www.example.com/docs/HelloWebStartJFX/<br />
cp index.html HelloWebStartJFX.jnlp HelloWebStartJFX.jar javafxrt.jar swing-layout.jar /www/www.example.com/docs/HelloWebStartJFX/<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">启动Web Start </span></span></strong><br />
<br />
通过www.example.com/HelloWebStartJFX/启动web Start。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何使用&#8220;全限定名&#8221;引用Java类? </span></span></strong><br />
<br />
全限定Java类名必须使用法语引号&lt;&lt; &gt;&gt;进行修饰。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何访问内部类和接口? </span></span></strong><br />
<br />
在访问内部类和接口时，你只能使用内部类的编译名。<br />
例如： <br />
在Java中的import java.util.Map.Entry，在JavaFX中将表示为import java.util.Map$Entry。<br />
<br />
在JavaFX中还需要注意的是在引用内部类时，你需要继续使用Outer$Inner 这种形式的语法。为了方便使用，你也可以相应地将导入语句修改为：<br />
<pre class="overflow">import java.util.Map$Entry as Entry</pre>
<br />
这样就不必重复地使用Outer$Inner形式了。<br />
我能够使用Java 5的枚举（enumerations）吗? <br />
当然可以。你可以采用下面的方式引用它们：<br />
<pre class="overflow">&nbsp;&nbsp; import java.util.management.MemoryType; // 导入枚举<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; var value = HEAP:MemoryType; // 使用枚举值 <br />
&nbsp;&nbsp; // HEAP是MemoryType中的枚举值<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; var allValues = MemoryType.values(); // 创建包含所有枚举值的JavaFX数组<br />
</pre>
<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何在JavaFX中轻松定制Swing组件?</span></span></strong><br />
<br />
这里提供了一些对Swing组件进行快速封装的代码，它能用于JavaFX组件层中：<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">SwingWidget类定义：</span></span></strong><br />
<br />
文件名：SwingWidget.fx<br />
<pre class="overflow">package a.b.c;<br />
<br />
import javafx.ui.*;<br />
import javax.swing.JComponent;<br />
<br />
class SwingWidget extends Widget {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; attribute swingComponent: JComponent;<br />
}<br />
<br />
operation SwingWidget.createComponent():&lt;&lt;javax.swing.JComponent&gt;&gt; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;return swingComponent;<br />
}<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">用法：</span></span></strong><br />
<br />
下面提供了一个使用SwingWidget的简单示例。请注意在树形列表中提供的数据来自于默认的树形模型，而不是JavaFX所特有的。<br />
文件名：WidgetTest.fx<br />
<pre class="overflow">package a.b.c;<br />
<br />
import javafx.ui.*;<br />
import javafx.ui.canvas.*;<br />
import java.lang.System;<br />
import javax.swing.JTree;<br />
import a.b.c.SwingWidget;<br />
<br />
Frame {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onClose: operation() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.exit(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; content: SwingWidget {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swingComponent: new JTree()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; visible: true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; title: "WTF, the Widget Test Framework"<br />
}<br />
</pre>
<br />
运行界面：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="display: inline" onclick="javascript:imgClick(this);" alt="image" src="http://images.wikia.com/jfx/images/c/c5/SwingWidgetExample.png" onload="javascript:imgLoad(this);" border="0" resized="0" /><br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">为什么我的某些.fx文件不能被JavaFX Pad重新装载?</span></span></strong><br />
<br />
非常抱歉地告诉你，JavaFXPad目前的功能非常有限。他并不能检测到外部文件的改变。为了让它能够&#8220;看到&#8221;你的修改，你需要以手工的方式在JavaFXPad中重新打开修改后的文件。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">如何引用其它JavaFX文件?</span></span></strong><br />
<br />
JavaFX能够从以下三种资源中引用静态值、变量和类：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.在同一文件内<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.在相同的目录/包路径下的文件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.在其它的包路径下的文件<br />
<br />
首先，第一种方式非常简单。如果你正在引用处于相同文件中的类，那么你只需要使用类名即可（类可以被定义在引用之前或者之后）。而变量则要在它们被声明之后才能被引用。<br />
<br />
对于第二种方式，显而易见，你无须对处于相同包路径下的每个.fx文件都使用import语句，而只要提供具有它们所在的同一包路径的import语句即可。<br />
<br />
如果你有其它的内部类或者你需要从不同的包路径下引入类，那么就需要使用import语句完成一点额外工作：使用import语句将.fx文件导入，而不是在此文件中的某个特定的类。例如，如果MediaTable.fx包含两个类：MediaTableColumn和MediaTableRow，那么你只需要importing MediaTable这一条语句就可以导入这两个类。<br />
<br />
你也可以像使用Java一样使用 import *语句。但由于这种方式降低了代码的可读性，所以并不推荐给大家。<br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX脚本提供类似 __LINE__这样的魔术常量（magic constants）吗? </span></span></strong><br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">魔术常量</span></span></strong><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226; __DIR__ -- 返回包含当前FX源文件的目录的URL。如果当前文件是从jar文件装载的，那么返回值可能是jar文件的URL。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226; __FILE__ -- 返回当前源文件的URL。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226; __LINE__ -- 返回当前源文件中的当前行。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226; __ARCHIVE__ -- 返回包含当前文件的jar文件的URL。<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">示例</span></span></strong><br />
<br />
<pre class="overflow">import javafx.ui.*;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
Frame {<br />
&nbsp;&nbsp;&nbsp;&nbsp;title&nbsp;&nbsp;: 'Magic Constants'<br />
&nbsp;&nbsp;&nbsp;&nbsp;width&nbsp;&nbsp;: 700<br />
&nbsp;&nbsp;&nbsp;&nbsp;height : 400<br />
&nbsp;&nbsp;&nbsp;&nbsp;content: Label {text: "&lt;html&gt;&lt;dl&gt;<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; &lt;dt&gt;__DOCBASE__&lt;/dt&gt;&lt;dd&gt;{__DOCBASE__}&lt;/dd&gt;<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; &lt;dt&gt;__DIR__&lt;/dt&gt;&nbsp;&nbsp;&nbsp;&nbsp;&lt;dd&gt;{__DIR__}&lt;/dd&gt;<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; &lt;dt&gt;__FILE__&lt;/dt&gt;&nbsp;&nbsp; &lt;dd&gt;{__FILE__}&lt;/dd&gt;<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; &lt;dt&gt;__LINE__&lt;/dt&gt;&nbsp;&nbsp; &lt;dd&gt;{__LINE__}&lt;/dd&gt;<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; &lt;dt&gt;__ARCHIVE__&lt;/dt&gt;&lt;dd&gt;{__ARCHIVE__}&lt;/dd&gt;<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; &lt;/dl&gt;&lt;/html&gt;"}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;visible: true<br />
}// Frame<br />
</pre>
<br />
<br />
<strong><span style="font-size: 10px"><span style="color: green">更多信息</span></span></strong><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8226; <a href="https://openjfx.dev.java.net/servlets/ReadMsg?list=users&amp;msgNo=649" target="_new">Christopher Oliver编写的"Magic Constants" </a><br />
<br />
<strong><span style="font-size: 12px"><span style="color: green">JavaFX中的保留字有哪些？</span></span></strong><br />
<br />
after<br />
and<br />
as<br />
assert<br />
attribute<br />
before<br />
bind<br />
break<br />
by<br />
catch<br />
class<br />
continue<br />
delete<br />
distinct<br />
do<br />
dur<br />
easeboth<br />
easein<br />
easeout<br />
else<br />
endif<br />
extends<br />
false<br />
finally<br />
first<br />
for<br />
foreach<br />
format<br />
fps<br />
from<br />
function<br />
if<br />
import<br />
in<br />
index<br />
indexof<br />
insert<br />
instanceof<br />
into<br />
inverse<br />
last<br />
later<br />
lazy<br />
linear<br />
motion<br />
nodebug<br />
new<br />
not<br />
null<br />
on<br />
operation<br />
or<br />
order<br />
package<br />
private<br />
protected<br />
public<br />
readonly<br />
return<br />
reverse<br />
select<br />
sizeof<br />
super<br />
then<br />
this<br />
throw (请注意不是throws)<br />
trigger<br />
true<br />
try<br />
typeof<br />
unitinterval<br />
valueof<br />
var<br />
where<br />
while<br />
xor
<img src ="http://www.blogjava.net/junky/aggbug/149502.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-09-29 10:57 <a href="http://www.blogjava.net/junky/archive/2007/09/29/149502.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>报表使用经验、技巧大总结（包括JFreechart、JS chart以及自己的使用经验） (转)</title><link>http://www.blogjava.net/junky/archive/2007/05/08/115930.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Tue, 08 May 2007 06:05:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/05/08/115930.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/115930.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/05/08/115930.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/115930.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/115930.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 前面我的工作中用到了报表，当时积累了一些试用心得。也触发了一些灵感。这里总结下来，希望对大家有一定帮助。&nbsp;一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 利用基本的TABLE元素——自己的创意之作可以参考我先前的一篇关于TABLE制作柱状图的blog：&nbsp;http://www.blogjava.net/JAVA-H...&nbsp;&nbsp;<a href='http://www.blogjava.net/junky/archive/2007/05/08/115930.html'>阅读全文</a><img src ="http://www.blogjava.net/junky/aggbug/115930.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-05-08 14:05 <a href="http://www.blogjava.net/junky/archive/2007/05/08/115930.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDK1.5新特性之Java Generics(转)</title><link>http://www.blogjava.net/junky/archive/2007/05/08/115929.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Tue, 08 May 2007 06:03:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/05/08/115929.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/115929.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/05/08/115929.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/115929.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/115929.html</trackback:ping><description><![CDATA[<div>
<h1><span><span><font face="Times New Roman"><font color=#000000><font size=5>1</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></font></span></span><span><font color=#000000 size=5>直观印象</font></span></h1>
<p><span>在</span><span>JDK1.5</span><span>之前的版本中，对于一个</span><span>Collection</span><span>类库中的容器类实例，可将任意类型</span></p>
<p><span>对象加入其中（都被当作</span><span>Object</span><span>实例看待）；从容器中取出的对象也只是一个</span><span>Object</span><span>实例，需要将其强制转型为期待的类型，这种强制转型的运行时正确性由程序员自行保证。</span></p>
<p><span>例如以下代码片断：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>List intList = new ArrayList(); </span><span>//</span><span>创建一个</span><span>List</span><span>，准备存放一些</span><span>Integer</span><span>实例</span></p>
            <p><span>intList.add(new Integer(0));</span></p>
            <p><span>intList.add(&#8220;1&#8221;); </span><span>//</span><span>不小心加入了一个字符串；但在编译和运行时都不报错，只有仔细的代码走<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//才能揪出</span></p>
            <p><span>Integer i0 = (Integer)intList.get(0); </span></p>
            <p><span>Integer i1 = (Integer)intList.get(1); </span><span>//</span><span>编译通过，直到运行时才抛</span><span>ClassCastException</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p><span>而在</span><span>JDK1.5</span><span>中，可以创建一个明确只能存放某种特定类型对象的容器类实例，例如如下代码：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>List&lt;Integer&gt; intList = new ArrayList&lt;Integer&gt;(); </span><span>//intList</span><span>为存放</span><span>Integer</span><span>实例的</span><span>List</span></p>
            <p><span>intList.add(new Integer(0)); </span></p>
            <p><span>Integer i0 = intList.get(0); </span><span>//</span><span>无需</span><span>(Integer)</span><span>强制转型；</span><span>List&lt;Integer&gt;</span><span>的</span><span>get()</span><span>返回的就是</span><span>Integer</span><span>类<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//型对象</span></p>
            <p><span>intList.add(&#8220;1&#8221;); </span><span>//</span><span>编译不通过，因为</span><span>List&lt;Integer&gt;</span><span>的</span><span>add()</span><span>方法只接受</span><span>Integer</span><span>类型的参数</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>&#8220;</span><span>List&lt;Integer&gt; intList = new ArrayList&lt;Integer&gt;();</span><span>&#8221;就是最简单且最常用的</span><span>Generic</span><span>应用；显然，运用</span><span>Generic</span><span>后的代码更具可读性和健壮性。</span></p>
<h1><font face="Times New Roman"><span><span><font color=#000000><font size=5>2</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span><font color=#000000 size=5>Generic</font></span></font><span><font color=#000000 size=5>类</font></span></h1>
<p><span>JDK1.5</span><span>中</span><span>Collection</span><span>类库的大部分类都被改进为</span><span>Generic</span><span>类。以下是从</span><span>JDK1.5</span><span>源码中</span></p>
<p><span>截取的关于</span><span>List</span><span>和</span><span>Iterator</span><span>接口定义的代码片断：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>public interface List&lt;E&gt; {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void add(E x);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Iterator&lt;E&gt; iterator;</span></p>
            <p><span>}</span></p>
            <p><span>public interface Iterator&lt;E&gt; {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>E next();</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>boolean hasNext();</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span>以</span><span>List</span><span>为例，&#8220;</span><span>public interface List&lt;E&gt;</span><span>&#8221;中的</span><span>E</span><span>是</span><span>List</span><span>的类型参数，用户在使用</span><span>List</span></p>
<p><span>时可为类型参数指定一个确定类型值（如</span><span>List&lt;Integer&gt;</span><span>）。类型值为</span><span>Java</span><span>编译器所用，确保用户代码类型安全。例如，编译器知道</span><span>List&lt;Integer&gt;</span><span>的</span><span>add()</span><span>方法只接受</span><span>Integer</span><span>类型的参数，因此如果你在代码中将一个字符串传入</span><span>add()</span><span>将导致编译错误；编译器知道</span><span>Iterator&lt;Integer&gt;</span><span>的</span><span>next()</span><span>方法返回一个</span><span>Integer</span><span>的实例，你在代码中也就无需对返回结果进行</span><span>(Integer)</span><span>强制转型。代码检验通过（语法正确且不会导致运行时类型安全问题）后，编译器对现有代码有一个转换工作。简单的说，就是去除代码中的类型值信息，在必要处添加转型代码。例如如下代码：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>public String demo() {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>List&lt;String&gt; strList = new ArrayList&lt;String&gt;();</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>strList.add(&#8220;Hello!&#8221;);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return strList.get(0);</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span>编译器在检验通过后，将其转换为：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>public String demo() {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>List strList = new ArrayList(); </span><span>//</span><span>去除类型值</span><span>&lt;String&gt;</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>strList.add(&#8220;Hello!&#8221;);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return (String)strList.get(0);</span><span> &nbsp;//</span><span>添加转型动作代码</span><span>(String)</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>可见，类型值信息只为</span><span>Java</span><span>编译器在编译时所用，确保代码无类型安全问题；验证通过之后，即被去除。对于</span><span>JVM</span><span>而言，只有如</span><span>JDK1.5</span><span>之前版本一样的</span><span>List</span><span>，并无</span><span>List&lt;Integer&gt;</span><span>和</span><span>List&lt;String&gt;</span><span>之分。这也就是</span><span>Java Generics</span><span>实现中关键技术</span><span>Erasure</span><span>的基本思想。以下代码在控制台输出的就是&#8220;</span><span>true</span><span>&#8221;。</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p align=left><span>List&lt;String&gt; strList = </span><strong><span>new</span></strong><span> ArrayList&lt;String&gt;();</span></p>
            <p align=left><span>List&lt;<span>Integer</span>&gt; intList = </span><strong><span>new</span></strong><span> ArrayList&lt;<span>Integer</span>&gt;();</span></p>
            <p><span>System.</span><em><span>out</span></em><span>.println(strList.getClass() == intList.getClass());</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>可以将</span><span>Generic</span><span>理解为：为提高</span><span>Java</span><span>代码类型安全性（在编译时确保，而非等到运行时才暴露），</span><span>Java</span><span>代码与</span><span>Java</span><span>编译器之间新增的一种约定规范。</span><span>Java</span><span>编译器在编译结果</span><span>*.class</span><span>文件中供</span><span>JVM</span><span>读取的部分里没有保留</span><span>Generic</span><span>的任何信息；</span><span>JVM</span><span>看不到</span><span>Generic</span><span>的存在。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>对于</span><span>Generic</span><span>类（设为</span><span>GenericClass</span><span>）的类型参数（设为</span><span>T</span><span>）：</span></p>
<p><span><span>1)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>由于对于</span><span>JVM</span><span>而言，只有一个</span><span>GenericClass</span><span>类，所以</span><span>GenericClass</span><span>类的静态字段和静态方法的定义中不能使用</span><span>T</span><span>。</span><span>T</span><span>只能出现在</span><span>GenericClass</span><span>的非静态字段或非静态方法中。也即</span><span>T</span><span>是与</span><span>GenericClass</span><span>的实例相关的信息；</span></p>
<p><span><span>2)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>T</span><span>只在编译时被编译器理解，因此也就不能与运行时被</span><span>JVM</span><span>理解并执行其代表的操作的操作符（如</span><span>instanceof </span><span>和</span><span>new</span><span>）联用。</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p align=left><strong><span>class</span></strong><span> GenericClass&lt;T&gt; {</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>T </span><span>t1</span><span>;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>public</span></strong><span> </span><strong><span>void</span></strong><span> method1(T t){</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>t1</span><span> = </span><strong><span>new</span></strong><span> T(); </span><span>//</span><span>编译错误，</span><span>T</span><span>不能与</span><span>new</span><span>联用</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><span>if</span></strong><span> (</span><span>t1</span><span> </span><strong><span>instanceof</span></strong><span> T) {}; </span><span>//</span><span>编译错误，</span><span>T</span><span>不能与</span><span>instanceof</span><span>联用</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>};</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>static</span></strong><span> T t2; </span><span>//</span><span>编译错误，静态字段不能使用</span><span>T</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>public</span></strong><span> </span><strong><span>static</span></strong><span> </span><strong><span>void</span></strong><span> method2(T t){};</span><span>//</span><span>编译错误，静态方法不能使用</span><span>T</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Generic</span><span>类可以有多个类型参数，且类型参数命名一般为大写单字符。例如</span><span>Collection</span><span>类库中的</span><span>Map</span><span>声明为：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>public interface Map&lt;K,V&gt; {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;&#8230;;</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<h1><font face="Times New Roman"><span><span><font color=#000000><font size=5>3</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span><font color=#000000 size=5>Generic</font></span></font><font size=5><font color=#000000><span>类和原（</span><span><font face="Times New Roman">Raw</font></span><span>）类</span></font></font></h1>
<p><span>对每一个</span><span>Generic</span><span>类，用户在使用时可以不指定类型参数。例如，对于</span><span>List&lt;E&gt;</span><span>，用户</span></p>
<p><span>可以以&#8220;</span><span>List&lt;String&gt; list;</span><span>&#8221;方式使用，也可以以&#8220;</span><span>List list;</span><span>&#8221;方式使用。&#8220;</span><span>List&lt;String&gt;</span><span>&#8221;被称为参数化的</span><span>Generic</span><span>类（类型参数被赋值），而&#8220;</span><span>List</span><span>&#8221;称为原类。原类</span><span>List</span><span>的使用方式和效果与</span><span>JDK1.5</span><span>之前版本</span><span>List</span><span>的一样；使用原类也就失去了</span><span>Generic</span><span>带来的可读性和健壮性的增强。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>允许原类使用方式的存在显然是为了代码的向前兼容：即</span><span>JDK1.5</span><span>之前的代码在</span><span>JDK1.5</span><span>下仍然编译通过且正常运行。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>当你在</span><span>JDK1.5</span><span>中使用原类并向原类实例中添加对象时，编译器会产生警告，因为它无法保证待添加对象类型的正确性。编译通过是为了保证代码向前兼容，产生警告是提醒潜在的风险。</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p align=left><strong><span>public</span></strong><span> </span><strong><span>void</span></strong><span> test () {</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>List <span>list</span> = </span><strong><span>new</span></strong><span> ArrayList();</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span><span>list</span>.add(</span><span>"tt"</span><span>);</span><span>//JDK1.5</span><span>编译器对此行产生警告</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<h1><font face="Times New Roman"><span><span><font color=#000000><font size=5>4</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span><font color=#000000 size=5>Generic</font></span></font><span><font color=#000000 size=5>类和子类</font></span></h1>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>List&lt;String&gt; ls = new ArrayList&lt;String&gt;();</span></p>
            <p><span>List&lt;Object&gt; lo = ls; </span><span>//</span><span>编译错误：</span><span>Type mismatch: cannot convert from List&lt;Dummy&gt; to&nbsp;<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;&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; <span>//</span>List&lt;Object&gt;</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span>以上第二行代码导致的编译错误&#8220;</span><span>Type mismatch: cannot convert from List&lt;Dummy&gt; to </span></p>
<p><span>List&lt;Object&gt;</span><span>&#8221;是不是有点出人意料？直观上看，就像</span><span>String</span><span>是</span><span>Object</span><span>的子类，因此&#8216;</span><span>Object o = &#8220;String&#8221;</span><span>&#8217;合法一样，存放</span><span>String</span><span>的</span><span>List</span><span>是存放</span><span>Object</span><span>的</span><span>List</span><span>的子类，因此第二行应该是合法的。反过来分析，如果第二行是合法的，那么如下会导致运行时异常的代码也是合法的：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>lo.add(new Object); </span><span>//</span><span>会导致在</span><span>ls</span><span>中添加了非</span><span>String</span><span>对象</span></p>
            <p><span>String s = ls.get(0); </span><span>//ls.get(0)</span><span>返回的实际上只是一个</span><span>Object</span><span>实例，会导致</span><span>ClassCastException</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>编译器显然不允许此种情形发生，因此不允许&#8220;</span><span>List&lt;Object&gt; lo = ls</span><span>&#8221;编译通过。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>因此，直观上的&#8220;存放</span><span>String</span><span>的</span><span>List</span><span>是存放</span><span>Object</span><span>的</span><span>List</span><span>的子类&#8221;是错误的。更一般的说，设</span><span>Foo</span><span>是</span><span>Bar</span><span>的子类，</span><span>G</span><span>是</span><span>Generic</span><span>类型声明，</span><span>G&lt;Foo&gt;</span><span>不是</span><span>G&lt;Bar&gt;</span><span>的子类。</span></p>
<h1><span><span><font face="Times New Roman"><font color=#000000><font size=5>5</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></font></span></span><font size=5><font color=#000000><span>参数化的</span><span><font face="Times New Roman">Generic</font></span><span>类和数组</span></font></font></h1>
<p><span>我们知道，如果</span><span>T</span><span>是</span><span>S</span><span>的子类，则</span><span>T[]</span><span>也是</span><span>S[]</span><span>的子类。因此，如下代码编译通过，只</span></p>
<p><span>在运行时于第三行代码处抛</span><span>ArrayStoreException</span><span>。</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>String[] words = new String[10];</span></p>
            <p><span>Object[] objects = words;</span></p>
            <p><span>Objects[0] = new Object(); </span><span>//</span><span>编译通过，但运行时会抛</span><span>ArrayStoreException</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span>再分析如下代码：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>List&lt;String&gt;[] wordLists = new ArrayList&lt;String&gt;[10]; </span></p>
            <p><span>ArrayList&lt;Integer&gt; integerList = new ArrayList&lt;Integer&gt;();</span></p>
            <p><span>integerList.add(123);</span></p>
            <p><span>Object[] objects = wordLists;</span></p>
            <p><span>objects[0] = integerList;</span><span>//</span><span>运行时不出错，因为运行时</span><span>ArrayList&lt;String&gt;</span><span>和</span><span>ArrayList&lt;Integer&gt;</span><span>都<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;&nbsp;&nbsp;<span>//</span>为</span><span>ArrayList</span></p>
            <p><span>String s = wordlists[0].get(0); </span><span>//</span><span>编译通过，运行时抛</span><span>ClassCastException</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>就出现了&#8220;正确使用了</span><span>Generic</span><span>，但在运行时仍然出现</span><span>ClassCastException</span><span>&#8221;的情形。显然</span><span>Java</span><span>编译器不允许此种情形的发生。事实上，以上代码的第一行&#8220;</span><span>List&lt;String&gt;[] wordLists = new ArrayList&lt;String&gt;[10];</span><span>&#8221;就是编译不通过的，也就不存在接下来的代码。</span></p>
<p><span>更一般地说，不能创建参数化的</span><span>Generic</span><span>类的数组。</span></p>
<h1><span><span><font face="Times New Roman"><font color=#000000><font size=5>6</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></font></span></span><font size=5><font color=#000000><span>类型参数通配符</span><span><font face="Times New Roman">?</font></span></font></font></h1>
<p><span>由&#8220;</span><span>Generic</span><span>类和子类&#8221;节知，</span><span>Collection&lt;Object&gt;</span><span>不是存放其它类型对象的</span><span>Collection</span><span>（例</span></p>
<p><span>如</span><span>Collection&lt;String&gt;</span><span>）的基类（抽象），那么如何表示任一种参数化的</span><span>Collection</span><span>的呢？使用</span><span>Collection&lt;?&gt;</span><span>。？即代表任一类型参数值。例如，我们可以很容易写出下面的通用函数</span><span>printCollection()</span><span>：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>public static void printCollection(Collection&lt;?&gt; c) {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span></span><span>//</span><span>如此遍历</span><span>Collection</span><span>的简洁方式也是</span><span>JDK1.5</span><span>新引入的</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for (Object o : c) {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.out.println(o);</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>这样，既可以将</span><span>Collection&lt;String&gt;</span><span>的实例，也可以将</span><span>Collection&lt;Integer&gt;</span><span>的实例作为参数调用</span><span>printCollection()</span><span>方法。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>然而，要注意一点，你不能往</span><span>Collection&lt;?&gt;</span><span>容器实例中加入任何非</span><span>null</span><span>元素，例如如下代码的第三行编译不通过：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>public static void testAdd(Collection&lt;?&gt; c) {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c.add(null);&nbsp;</span><span>//</span><span>编译通过</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c.add(&#8220;test&#8221;); </span><span>//</span><span>编译错误</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>很好理解：</span><span>c</span><span>中要存放的对象的具体类型不确定，编译器无法验证待添加对象类型的正确性，因此不能加入对象实例；而</span><span>null</span><span>可以看作是任一个类的实例，因而允许加入。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>另外，尽管</span><span>c</span><span>中要存放的对象的类型不确定，但我们知道任何类都是</span><span>Object</span><span>子类，因此从</span><span>c</span><span>中取出的对象都统一作为</span><span>Object</span><span>实例。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>更进一步，如果</span><span>BaseClass</span><span>代表某个可被继承的类的类名，那么</span><span>Collection&lt;? extends BaseClass&gt;</span><span>代表类型参数值为</span><span>BaseClass</span><span>或</span><span>BaseClass</span><span>某个子类的任一参数化</span><span>Collection</span><span>。对于</span><span>Collection&lt;? extends BaseClass&gt;</span><span>的实例</span><span>c</span><span>，因为</span><span>c</span><span>中要存放的对象具体类型不确定，不能往其加入非</span><span>null</span><span>对象，但从</span><span>c</span><span>中取出的对象都统一作为</span><span>BaseClass</span><span>实例。事实上，你可以把</span><span>Collection&lt;?&gt;</span><span>看作</span><span>Collection&lt;? extends Object&gt;</span><span>的简洁形式。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>另一种情形：如果</span><span>SubClass</span><span>代表任一个类的类名，那么</span><span>Collection&lt;? super SubClass&gt;</span><span>代表类型参数值为</span><span>SubClass</span><span>或</span><span>SubClass</span><span>某个祖先类的任一参数化</span><span>Collection</span><span>。对于</span><span>Collection&lt;? super SubClass&gt;</span><span>的实例</span><span>c</span><span>，你可以将</span><span>SubClass</span><span>实例加入其中，但从中取出的对象都是</span><span>Object</span><span>实例。</span></p>
<h1><font face="Times New Roman"><span><span><font color=#000000><font size=5>7</font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font></span></span><span><font color=#000000 size=5>Generic</font></span></font><span><font color=#000000 size=5>方法</font></span></h1>
<p><span>我们可以定义</span><span>Generic</span><span>类，同样可以定义</span><span>Generic</span><span>方法，即将方法的一个或多个参数的类型参数化，如代码：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>public static &lt;T&gt; void fromArrayToCollection(T[] a, Collection&lt;T&gt; c) {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>for (T o : a) {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c.add(o); </span><span>//</span><span>合法。注意与</span><span>Collection&lt;?&gt;</span><span>的区别</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>我们可以以如下方式调用</span><span>fromArrayToCollection()</span><span>：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>Object[] oa = new Object[100];</span></p>
            <p><span>Collection&lt;Object&gt; co = new ArrayList&lt;Object&gt;();</span></p>
            <p><span>fromArrayToCollection(oa, co); </span><span>//</span><span>此时，</span><span>T</span><span>即为</span><span>Object</span></p>
            <p>&nbsp;</p>
            <p><span>String[] sa = new String[100];</span></p>
            <p><span>Collection&lt;String&gt; cs = new ArrayList&lt;String&gt;();</span></p>
            <p><span>fromArrayToCollection(sa, cs); </span><span>//</span><span>此时，</span><span>T</span><span>即为</span><span>String</span></p>
            <p><span>fromArrayToCollection(sa, co); </span><span>//</span><span>此时，</span><span>T</span><span>即为</span><span>Object</span></p>
            <p>&nbsp;</p>
            <p><span>Integer[] ia = new Integer[100];</span></p>
            <p><span>Float[] fa = new Float[100];</span></p>
            <p><span>Number[] na = new Number[100];</span></p>
            <p><span>Collection&lt;Number&gt; cn = new ArrayList&lt;Number&gt;();</span></p>
            <p><span>fromArrayToCollection(ia, cn); </span><span>//</span><span>此时，</span><span>T</span><span>即为</span><span>Number</span></p>
            <p><span>fromArrayToCollection(fa, cn); </span><span>//</span><span>此时，</span><span>T</span><span>即为</span><span>Number</span></p>
            <p><span>fromArrayToCollection(na, cn); </span><span>//</span><span>此时，</span><span>T</span><span>即为</span><span>Number</span></p>
            <p><span>fromArrayToCollection(na, co); </span><span>//</span><span>此时，</span><span>T</span><span>即为</span><span>Object</span></p>
            <p><span>fromArrayToCollection(na, cs); </span><span>//</span><span>编译错误</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>通过以上代码可以看出，我们在调用</span><span>fromArrayToCollection()</span><span>时，无需明确指定</span><span>T</span><span>为何种类型（与</span><span>Generic</span><span>类的使用方式不同），而是像调用一般</span><span>method</span><span>一样，直接提供参数值，编译器会根据提供的参数值自动为</span><span>T</span><span>赋类型值或提示编译错误（参数值不当）。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>考虑如下函数</span><span>sum()</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p align=left><strong><span>public</span></strong><span> </span><strong><span>static</span></strong><span> </span><strong><span>long</span></strong><span> sum(Collection&lt;? </span><strong><span>extends</span></strong><span> Number&gt; numbers) {</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>long</span></strong><span> <span>sum</span> = 0;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>for</span></strong><span> (Number n : numbers) {</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>sum</span> += n.longValue();</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>return</span></strong><span> <span>sum</span>;</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>我们也可以将其以</span><span>Generic</span><span>方法实现：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p align=left><strong><span>public</span></strong><span> </span><strong><span>static</span></strong><span> &lt;T </span><strong><span>extends</span></strong><span> Number&gt; </span><strong><span>long</span></strong><span> sum(Collection&lt;T&gt; numbers) {</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>long</span></strong><span> sum = 0;</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>for</span></strong><span> (Number n : numbers) {</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>sum += n.longValue();</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p align=left><span><span>&nbsp;&nbsp;&nbsp; </span></span><strong><span>return</span></strong><span> sum;</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>那么对于一个方法，当要求参数类型可变时，是采用</span><span>Generic</span><span>方法，还是采用类型参数通配符方式呢？一般而言，如果参数类型间或参数类型与返回值类型间存在某种依赖关系，则采取</span><span>Generic</span><span>方法，否则采取类型参数通配符方式。</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>这一原则在</span><span>Collection</span><span>类库的源代码中得到了很好的体现，例如</span><span>Collection</span><span>接口的</span><span>containsAll()</span><span>、</span><span>addAll()</span><span>和</span><span>toArray()</span><span>方法：</span></p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>interface Collection&lt;E&gt; {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>public boolean containsAll(Collecion&lt;?&gt; c);</span><span> //</span><span>参数间类型以及参数与返回<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//值间类型无依赖</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&lt;T&gt; T[] toArray(T[] a); </span><span>//</span><span>参数</span><span>a</span><span>与返回值都是相同类的数组，有依赖</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>当然，根据需要，二者也可以结合使用，例如</span><span>Collections</span><span>中的</span><span>copy()</span><span>方法：</span></p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>class Collections {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>public static &lt;T&gt; void copy(List&lt;T&gt; dest, List&lt;? extends T&gt; src) {</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;&#8230;.</span></p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></p>
            <p><span>}</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p>
</div>
<img src ="http://www.blogjava.net/junky/aggbug/115929.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-05-08 14:03 <a href="http://www.blogjava.net/junky/archive/2007/05/08/115929.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Clone机制(转)</title><link>http://www.blogjava.net/junky/archive/2007/05/08/115928.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Tue, 08 May 2007 06:02:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/05/08/115928.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/115928.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/05/08/115928.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/115928.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/115928.html</trackback:ping><description><![CDATA[<div>
<h1><span><span><font size=5>1</font> <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><font size=5><span>什么是</span> <span>Clone</span> <span>，容易实现吗？</span> </font></h1>
<p><span>简单地说，</span> <span>Clone</span> <span>就是对于给定的一个对象实例</span> <span>o</span> <span>，得到另一个对象实例</span> <span>o&#8217;</span> <span>：</span> <span>o</span> <span>与</span> <span>o&#8217;</span> <span>类</span> </p>
<p><span>型相同（</span> <span>o.getClass() == o&#8217;.getClass()</span> <span>），内容相同（对于</span> <span>o/o&#8217;</span> <span>中的字段</span> <span>f</span> <span>，如果</span> <span>f</span> <span>是基本数据类型，则</span> <span>o.f == o&#8217;.f</span> <span>；如果</span> <span>f</span> <span>是对象引用，则</span> <span>o.f == o&#8217;.f</span> <span>或</span> <span>o.f</span> <span>指向的对象与</span> <span>o&#8217;.f</span> <span>指向的对象的内容相同）。通常称</span> <span>o&#8217;</span> <span>为</span> <span>o</span> <span>的克隆或副本。</span> </p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>直观上看，似乎很容易为一个类加上</span> <span>clone</span> <span>方法：</span> </p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>class A {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>private Type1 field1;</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>private Type2 field2;</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;..</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>public Object clone() {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>A a = new A();</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>a.field1 = a.getField1();</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>a.field2 = a.getField2();</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;&#8230;</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return a;</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>}</span> </p>
            <p><span>}</span> </p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span>然而，稍加推敲，就会发现这样的实现方法有两个问题：</span> </p>
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>要想某个类有</span> <span>clone</span> <span>功能，必须单独为其实现</span> <span>clone()</span> <span>函数，函数实现代码与该类定义密切相关。</span> </p>
<p><span><span>2.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>即使基类</span> <span>A</span> <span>已有</span> <span>clone()</span> <span>函数，其子类</span> <span>ExtendA</span> <span>若要具备</span> <span>clone</span> <span>功能，则必须</span> <span>override</span> <span>其基类</span> <span>A</span> <span>的</span> <span>clone()</span> <span>函数。否则，对类型为</span> <span>ExtendA</span> <span>的对象</span> <span>ea</span> <span>的</span> <span>clone()</span> <span>方法的调用，会执行于类</span> <span>A</span> <span>中定义的</span> <span>clone()</span> <span>方法而返回一个类型为</span> <span>A</span> <span>的对象，它显然不是</span> <span>ea</span> <span>的克隆。</span> </p>
<h1><span><span><font size=5>2</font> <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><font size=5><span>Java</span> <span>对</span> <span>clone</span> <span>的支持</span> </font></h1>
<p><span>万类之初的</span> <span>Object</span> <span>类有</span> <span>clone()</span> <span>方法：</span> </p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>protected native Object clone() throws CloneNotSupportedException;</span> </p>
            </td>
        </tr>
    </tbody>
</table>
<p><span>该方法是</span> <span>protected</span> <span>的，显然是留待被子类</span> <span>override</span> <span>的。该方法又是</span> <span>native</span> <span>的，必然做了</span> </p>
<p><span>与具体平台相关的底层工作。</span> </p>
<p><span>事实上，类</span> <span>Object</span> <span>的</span> <span>clone()</span> <span>方法首先会检查</span> <span>this.getClass()</span> <span>是否实现了</span> <span>Cloneable</span> <span>接口。</span> </p>
<p><span>Cloneable</span> <span>只是一个标志接口而已，用来标志该类是否有克隆功能。</span> </p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p align=left><strong><span>public</span> </strong><strong><span>interface</span> </strong><span><span>Cloneable</span> { </span></p>
            <p><span>}</span> </p>
            </td>
        </tr>
    </tbody>
</table>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>如果</span> <span>this.getClass()</span> <span>没有实现</span> <span>Cloneable</span> <span>接口，</span> <span>clone()</span> <span>就会抛</span> <span>CloneNotSupportedException</span> <span>返回。否则就会创建一个类型为</span> <span>this.getClass()</span> <span>的对象</span> <span>other</span> <span>，并将</span> <span>this</span> <span>各</span> <span>field</span> <span>的值赋值给</span> <span>other</span> <span>的对应</span> <span>field</span> <span>，然后返回</span> <span>other</span> <span>。</span> </p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>如此一来，我们要定义一个具有</span> <span>Clone</span> <span>功能的类就相当方便：</span> </p>
<p><span><span>1.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>在类的声明中加入&#8220;</span> <span>implements Cloneable</span> <span>&#8221;，标志该类有克隆功能；</span> </p>
<p><span><span>2.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>Override</span> <span>类</span> <span>Object</span> <span>的</span> <span>clone()</span> <span>方法，在该方法中调用</span> <span>super.clone()</span> <span>：</span> </p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>class CloneableClass implements Cloneable {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>&#8230;&#8230;</span> </p>
            <p><span>public Object clone() {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>try {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return super.clone();</span> <span>//</span> <span>直接让</span> <span>Object.clone()</span> <span>为我们代劳一切</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>} catch (CloneNotSupportedException e) {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new InternalError();</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span> </p>
            <p><span>}</span> </p>
            <p><span>}</span> </p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<h1><span><span><font size=5>3</font> <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><font size=5><span>Shallow Clone</span> <span>与</span> <span>Deep Clone</span> </font></h1>
<h2><span><span><font face=Arial>3.1</font> <span>&nbsp;&nbsp;&nbsp; </span></span></span><span><font face=Arial>Shallow</font> </span><span>与</span> <span><font face=Arial>Deep</font> </span><span>从何而来</span> </h2>
<p><span>一个具有克隆功能的类，如果有可变（</span> <span>Mutable</span> <span>）类类型的字段</span> <span>field</span> <span>，如何为其克隆（副</span> </p>
<p><span>本）对象</span> <span>o&#8217;</span> <span>中的</span> <span>field</span> <span>赋值？</span> </p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>方法一、如</span> <span>Object</span> <span>的</span> <span>clone()</span> <span>方法所实现：设原始对象为</span> <span>o</span> <span>，其克隆对象是</span> <span>o&#8217;</span> <span>，执行</span> <span>o&#8217;.field = o.field</span> <span>。这样，</span> <span>o&#8217;.field</span> <span>与</span> <span>o.field</span> <span>指向同一个可变对象</span> <span>m</span> <span>。</span> <span>o</span> <span>与</span> <span>o&#8217;</span> <span>可能会相互影响（一个对象的状态可能会随着另一个对象的状态的改变而改变）。这样的</span> <span>Clone</span> <span>称为</span> <span>Shallow Clone</span> <span>。这也是</span> <span>Object</span> <span>的</span> <span>clone()</span> <span>方法的实现方式。</span> </p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>方法二、将</span> <span>o.field</span> <span>指向的可变对象</span> <span>m</span> <span>克隆，得到</span> <span>m&#8217;</span> <span>，将</span> <span>m&#8217;</span> <span>的引用赋值给</span> <span>o&#8217;.field</span> <span>。这样</span> <span>o&#8217;</span> <span>与</span> <span>o</span> <span>内容相同，且相互之间无影响（一个对象状态的改变不会影响另一个对象的状态）。这样的</span> <span>Clone</span> <span>称为</span> <span>Deep Clone</span> <span>。</span> </p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Java Collection</span> <span>类库中具体数据结构类（</span> <span>ArrayList/LinkedList</span> <span>，</span> <span>HashSet/TreeSet</span> <span>，</span> <span>HashMap/TreeMap</span> <span>等）都具有克隆功能，且都是</span> <span>Shallow Clone</span> <span>，这样设计是合理的，因为它们不知道存放其中的每个数据对象是否也有克隆功能。</span> <span>System.arrayCopy()</span> <span>的实现采用的也是</span> <span>Shallow Clone</span> <span>。</span> </p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Deep Clone</span> <span>对于实现不可变（</span> <span>Immutable</span> <span>）类很有帮助。设一个类包含可变类</span> <span>M</span> <span>类型的</span> <span>field</span> <span>，如何将其设计为不可变类呢？先为</span> <span>M</span> <span>实现</span> <span>Deep Clone</span> <span>功能，然后这样设计类</span> <span>ImmutableClass</span> <span>：</span> </p>
<table cellSpacing=0 cellPadding=0 border=1>
    <tbody>
        <tr>
            <td vAlign=top width=568>
            <p><span>class ImmutableClass {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>MutableClass m;</span> </p>
            <p><span>ImmutableClass(MutableClass m) {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>this.m = m.clone(); </span><span>//</span> <span>将传入的</span> <span>m</span> <span>的</span> <span>clone</span> <span>赋值给内部</span> <span>m</span> </p>
            <p><span>}</span> </p>
            <p><span>public MutableClass getM() {</span> </p>
            <p><span><span>&nbsp;&nbsp;&nbsp; </span>return this.m.clone(); </span><span>//</span> <span>将内部</span> <span>m</span> <span>的</span> <span>clone</span> <span>返回给外部</span> </p>
            <p><span>}</span> </p>
            <p><span>}</span> </p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></p>
<h2><span><span><font face=Arial>3.2</font> <span>&nbsp;&nbsp;&nbsp; </span></span></span><span>如何实现</span> <span><font face=Arial>Deep Clone</font> </span></h2>
<p><span>检查类有无可变类类型的字段。如果无，返回</span> <span>super.clone()</span> <span>即可；</span> </p>
<p><span>如果有，确保包含的可变类本身都实现了</span> <span>Deep Clone</span> <span>；</span> </p>
<p><span>Object o = super.clone(); </span><span>//</span> <span>先执行浅克隆，确保类型正确和基本类型及非可变类类型字段内容正确</span> </p>
<p><span>对于每一个可变类类型的字段</span> <span>field</span> <span>：</span> </p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>o.field = this.getField().clone();</span> </p>
<p><span>返回</span> <span>o</span> <span>。</span> </p>
</div>
<img src ="http://www.blogjava.net/junky/aggbug/115928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-05-08 14:02 <a href="http://www.blogjava.net/junky/archive/2007/05/08/115928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA上加密算法的实现用例</title><link>http://www.blogjava.net/junky/archive/2007/05/08/115844.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Tue, 08 May 2007 01:28:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/05/08/115844.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/115844.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/05/08/115844.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/115844.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/115844.html</trackback:ping><description><![CDATA[来源：www.ibm.com<br>关于作者王辉 ddxxkk@21cn.com<br>王辉，具有八年的编程及系统管理经验，所使用的语言为C和Java 编程语言。目前在深圳一家公司做程序员，使用C和JAVA为DB2数据库编程.可通过 ddxxkk@21cn.com 联系。 <br><br>第1章 基础知识<br><br>1.1. 单钥密码体制 <br>单钥密码体制是一种传统的加密算法，是指信息的发送方和接收方共同使用同一把密钥进行加解密。<br><br>通常,使用的加密算法 比较简便高效,密钥简短，加解密速度快，破译极其困难。但是加密的安全性依靠密钥保管的安全性,在公开的计算机网络上安全地传送和保管密钥是一个严峻的问题，并且如果在多用户的情况下密钥的保管安全性也是一个问题。<br><br>单钥密码体制的代表是美国的DES<br><br>1.2. 消息摘要 <br>一个消息摘要就是一个数据块的数字指纹。即对一个任意长度的一个数据块进行计算，产生一个唯一指印（对于SHA1是产生一个20字节的二进制数组）。<br><br>消息摘要有两个基本属性： <br><br>两个不同的报文难以生成相同的摘要 <br>难以对指定的摘要生成一个报文，而由该报文反推算出该指定的摘要<br>代表：美国国家标准技术研究所的SHA1和麻省理工学院Ronald Rivest提出的MD5<br><br>1.3. Diffie-Hellman密钥一致协议 <br>密钥一致协议是由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。<br><br>先决条件,允许两名用户在公开媒体上交换信息以生成"一致"的,可以共享的密钥<br><br>代表：指数密钥一致协议(Exponential Key Agreement Protocol)<br><br>1.4. 非对称算法与公钥体系 <br>1976年，Dittie和Hellman为解决密钥管理问题，在他们的奠基性的工作"密码学的新方向"一文中，提出一种密钥交换协议，允许在不安全的媒体上通过通讯双方交换信息，安全地传送秘密密钥。在此新思想的基础上，很快出现了非对称密钥密码体制，即公钥密码体制。在公钥体制中，加密密钥不同于解密密钥，加密密钥公之于众，谁都可以使用；解密密钥只有解密人自己知道。它们分别称为公开密钥（Public key）和秘密密钥（Private key）。 <br><br>迄今为止的所有公钥密码体系中，RSA系统是最著名、最多使用的一种。RSA公开密钥密码系统是由R.Rivest、A.Shamir和L.Adleman俊教授于1977年提出的。RSA的取名就是来自于这三位发明者的姓的第一个字母<br><br>1.5. 数字签名 <br>所谓数字签名就是信息发送者用其私钥对从所传报文中提取出的特征数据（或称数字指纹）进行RSA算法操作，以保证发信人无法抵赖曾发过该信息（即不可抵赖性），同时也确保信息报文在经签名后末被篡改（即完整性）。当信息接收者收到报文后，就可以用发送者的公钥对数字签名进行验证。　 <br><br>在数字签名中有重要作用的数字指纹是通过一类特殊的散列函数（HASH函数）生成的，对这些HASH函数的特殊要求是： <br><br>接受的输入报文数据没有长度限制； <br>对任何输入报文数据生成固定长度的摘要（数字指纹）输出 <br>从报文能方便地算出摘要； <br>难以对指定的摘要生成一个报文，而由该报文反推算出该指定的摘要； <br>两个不同的报文难以生成相同的摘要<br><br>代表：DSA<br><br>第2章 在JAVA中的实现<br><br>2.1. 相关 <br>Diffie-Hellman密钥一致协议和DES程序需要JCE工具库的支持,可以到 http://java.sun.com/security/index.html 下载JCE,并进行安装。简易安装把 jce1.2.1\lib 下的所有内容复制到 %java_home%\lib\ext下,如果没有ext目录自行建立,再把jce1_2_1.jar和sunjce_provider.jar添加到CLASSPATH内,更详细说明请看相应用户手册<br><br>2.2. 消息摘要MD5和SHA的使用 <br>使用方法:<br><br>首先用生成一个MessageDigest类,确定计算方法<br><br>java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");<br><br>添加要进行计算摘要的信息<br><br>alga.update(myinfo.getBytes());<br><br>计算出摘要<br><br>byte[] digesta=alga.digest();<br><br>发送给其他人你的信息和摘要<br><br>其他人用相同的方法初始化,添加信息,最后进行比较摘要是否相同<br><br>algb.isEqual(digesta,algb.digest())<br><br>相关AIP<br><br>java.security.MessageDigest 类<br><br>static getInstance(String algorithm)<br><br>返回一个MessageDigest对象,它实现指定的算法<br><br>参数:算法名,如 SHA-1 或MD5<br><br>void update (byte input)<br><br>void update (byte[] input)<br><br>void update(byte[] input, int offset, int len)<br><br>添加要进行计算摘要的信息<br><br>byte[] digest()<br><br>完成计算,返回计算得到的摘要(对于MD5是16位,SHA是20位)<br><br>void reset()<br><br>复位<br><br>static boolean isEqual(byte[] digesta, byte[] digestb)<br><br>比效两个摘要是否相同<br><br>代码： <br>import java.security.*;<br>public class myDigest {<br>public static void main(String[] args) {<br><br>myDigest my=new myDigest();<br>my.testDigest();<br><br>}<br>public void testDigest()<br>{<br>try {<br>String myinfo="我的测试信息";<br><br>//java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5");<br>java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");<br>alga.update(myinfo.getBytes());<br>byte[] digesta=alga.digest();<br>System.out.println("本信息摘要是:"+byte2hex(digesta));<br>//通过某中方式传给其他人你的信息(myinfo)和摘要(digesta) 对方可以判断是否更改或传输正常<br>java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1");<br>algb.update(myinfo.getBytes());<br>if (algb.isEqual(digesta,algb.digest())) {<br>System.out.println("信息检查正常");<br>}<br>else<br>{<br>System.out.println("摘要不相同");<br>}<br><br>}<br>catch (java.security.NoSuchAlgorithmException ex) {<br>System.out.println("非法摘要算法");<br>}<br><br>}<br>public String byte2hex(byte[] b) //二行制转字符串<br>{<br>String hs="";<br>String stmp="";<br>for (int n=0;n<b.length;n++)<br /> {<br>stmp=(java.lang.Integer.toHexString(b[n] &amp; 0XFF));<br>if (stmp.length()==1) hs=hs+"0"+stmp;<br>else hs=hs+stmp;<br>if (n<b.length-1) hs='hs+":";<br' /> }<br>return hs.toUpperCase();<br>}<br><br>}<br><br><br><br>2.3. 数字签名DSA<br><br>对于一个用户来讲首先要生成他的密钥对,并且分别保存 <br>生成一个KeyPairGenerator实例 <br>java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");<br>如果设定随机产生器就用如相代码初始化<br>SecureRandom secrand=new SecureRandom(); <br><br>secrand.setSeed("tttt".getBytes()); //初始化随机产生器<br>keygen.initialize(512,secrand); //初始化密钥生成器<br>否则<br>keygen.initialize(512);<br>生成密钥公钥pubkey和私钥prikey<br>KeyPair keys=keygen.generateKeyPair(); //生成密钥组<br>PublicKey pubkey=keys.getPublic();<br>PrivateKey prikey=keys.getPrivate();<br>分别保存在myprikey.dat和mypubkey.dat中,以便下次不在生成<br>(生成密钥对的时间比较长<br>java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));<br>out.writeObject(prikey);<br>out.close();<br>out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));<br>out.writeObject(pubkey);<br>out.close();<br><br><br><br><br>用他私人密钥(prikey)对他所确认的信息(info)进行数字签名产生一个签名数组 <br>从文件中读入私人密钥(prikey) <br>java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));<br>PrivateKey myprikey=(PrivateKey)in.readObject();<br>in.close();<br>初始一个Signature对象,并用私钥对信息签名<br>java.security.Signature signet=java.security.Signature.getInstance("DSA");<br>signet.initSign(myprikey);<br>signet.update(myinfo.getBytes());<br>byte[] signed=signet.sign();<br>把信息和签名保存在一个文件中(myinfo.dat)<br>java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));<br>out.writeObject(myinfo);<br>out.writeObject(signed);<br>out.close();<br>把他的公钥的信息及签名发给其它用户<br><br><br><br><br>其他用户用他的公共密钥(pubkey)和签名(signed)和信息(info)进行验证是否由他签名的信息 <br>读入公钥<br>java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat")); <br>PublicKey pubkey=(PublicKey)in.readObject(); <br>in.close();<br><br>读入签名和信息<br>in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat")); <br>String info=(String)in.readObject(); <br>byte[] signed=(byte[])in.readObject(); <br>in.close();<br><br>初始一个Signature对象,并用公钥和签名进行验证<br>java.security.Signature signetcheck=java.security.Signature.getInstance("DSA"); <br>signetcheck.initVerify(pubkey); <br>signetcheck.update(info.getBytes()); <br>if (signetcheck.verify(signed)) { System.out.println("签名正常");}<br><br>对于密钥的保存本文是用对象流的方式保存和传送的,也可可以用编码的方式保存.注意要<br>import java.security.spec.* <br>import java.security.*<br><br>具休说明如下<br><br>public key是用X.509编码的,例码如下: <br>byte[] bobEncodedPubKey=mypublic.getEncoded(); //生成编码<br>//传送二进制编码<br>//以下代码转换编码为相应key对象<br>X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);<br>KeyFactory keyFactory = KeyFactory.getInstance("DSA");<br>PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);<br><br><br><br>对于Private key是用PKCS#8编码,例码如下: <br>byte[] bPKCS=myprikey.getEncoded();<br>//传送二进制编码<br>//以下代码转换编码为相应key对象<br>PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS);<br>KeyFactory keyf=KeyFactory.getInstance("DSA");<br>PrivateKey otherprikey=keyf.generatePrivate(priPKCS8);<br><br><br><br><br>常用API <br>java.security.KeyPairGenerator 密钥生成器类 <br>public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException <br>以指定的算法返回一个KeyPairGenerator 对象 <br>参数: algorithm 算法名.如:"DSA","RSA"<br><br>public void initialize(int keysize)<br><br><br>以指定的长度初始化KeyPairGenerator对象,如果没有初始化系统以1024长度默认设置<br><br><br>参数:keysize 算法位长.其范围必须在 512 到 1024 之间，且必须为 64 的倍数<br><br>public void initialize(int keysize, SecureRandom random)<br>以指定的长度初始化和随机发生器初始化KeyPairGenerator对象<br>参数:keysize 算法位长.其范围必须在 512 到 1024 之间，且必须为 64 的倍数<br>random 一个随机位的来源(对于initialize(int keysize)使用了默认随机器<br><br>public abstract KeyPair generateKeyPair()<br>产生新密钥对<br><br>java.security.KeyPair 密钥对类<br>public PrivateKey getPrivate()<br>返回私钥<br><br>public PublicKey getPublic()<br>返回公钥<br><br>java.security.Signature 签名类<br>public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException<br>返回一个指定算法的Signature对象<br>参数 algorithm 如:"DSA"<br><br>public final void initSign(PrivateKey privateKey)<br>throws InvalidKeyException<br>用指定的私钥初始化<br>参数rivateKey 所进行签名时用的私钥<br><br>public final void update(byte data)<br>throws SignatureException<br>public final void update(byte[] data)<br>throws SignatureException<br>public final void update(byte[] data, int off, int len)<br>throws SignatureException <br><br>添加要签名的信息<br><br>public final byte[] sign()<br>throws SignatureException<br>返回签名的数组,前提是initSign和update<br><br>public final void initVerify(PublicKey publicKey)<br>throws InvalidKeyException<br>用指定的公钥初始化<br>参数ublicKey 验证时用的公钥<br><br>public final boolean verify(byte[] signature)<br>throws SignatureException<br>验证签名是否有效,前提是已经initVerify初始化<br>参数: signature 签名数组 <br>*/<br>import java.security.*;<br>import java.security.spec.*;<br>public class testdsa {<br>public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception {<br>testdsa my=new testdsa();<br>my.run();<br>}<br>public void run()<br>{<br><br>//数字签名生成密钥<br>//第一步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地<br>//而mypubkey.dat给发布给其它用户<br>if ((new java.io.File("myprikey.dat")).exists()==false) {<br>if (generatekey()==false) {<br>System.out.println("生成密钥对败");<br>return;<br>};<br>}<br>//第二步,此用户<br>//从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中<br>//并且再把myinfo.dat发送出去<br>//为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送<br>try {<br>java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));<br>PrivateKey myprikey=(PrivateKey)in.readObject();<br>in.close();<br><br>// java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509);<br><br>//java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec<br>String myinfo="这是我的信息"; //要签名的信息<br>//用私钥对信息生成数字签名<br>java.security.Signature signet=java.security.Signature.getInstance("DSA");<br>signet.initSign(myprikey);<br>signet.update(myinfo.getBytes());<br>byte[] signed=signet.sign(); //对信息的数字签名<br>System.out.println("signed(签名内容)="+byte2hex(signed));<br>//把信息和数字签名保存在一个文件中<br>java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));<br>out.writeObject(myinfo);<br>out.writeObject(signed);<br>out.close();<br>System.out.println("签名并生成文件成功");<br>}<br>catch (java.lang.Exception e) {<br>e.printStackTrace();<br>System.out.println("签名并生成文件失败");<br>};<br><br>//第三步<br>//其他人通过公共方式得到此户的公钥和文件<br>//其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息.<br>//<br>try {<br><br>java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));<br>PublicKey pubkey=(PublicKey)in.readObject();<br>in.close();<br>System.out.println(pubkey.getFormat());<br><br>in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));<br>String info=(String)in.readObject();<br>byte[] signed=(byte[])in.readObject();<br>in.close();<br><br>java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");<br>signetcheck.initVerify(pubkey);<br>signetcheck.update(info.getBytes());<br>if (signetcheck.verify(signed)) {<br>System.out.println("info="+info);<br>System.out.println("签名正常");<br>}<br>else System.out.println("非签名正常");<br>}<br>catch (java.lang.Exception e) {e.printStackTrace();};<br><br><br>}<br><br>//生成一对文件myprikey.dat和mypubkey.dat---私钥和公钥,<br>//公钥要用户发送(文件,网络等方法)给其它用户,私钥保存在本地<br>public boolean generatekey()<br>{<br>try {<br>java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");<br>// SecureRandom secrand=new SecureRandom();<br>// secrand.setSeed("tttt".getBytes()); //初始化随机产生器<br>// keygen.initialize(576,secrand); //初始化密钥生成器<br>keygen.initialize(512);<br>KeyPair keys=keygen.genKeyPair();<br>// KeyPair keys=keygen.generateKeyPair(); //生成密钥组<br>PublicKey pubkey=keys.getPublic();<br>PrivateKey prikey=keys.getPrivate();<br><br>java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));<br>out.writeObject(prikey);<br>out.close();<br>System.out.println("写入对象 prikeys ok");<br>out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));<br>out.writeObject(pubkey);<br>out.close();<br>System.out.println("写入对象 pubkeys ok");<br>System.out.println("生成密钥对成功");<br>return true;<br>}<br>catch (java.lang.Exception e) {<br>e.printStackTrace();<br>System.out.println("生成密钥对失败");<br><br>return false;<br>};<br><br>}<br><br>public String byte2hex(byte[] b)<br>{<br>String hs="";<br>String stmp="";<br>for (int n=0;n<b.length;n++)<br /> {<br>stmp=(java.lang.Integer.toHexString(b[n] &amp; 0XFF));<br>if (stmp.length()==1) hs=hs+"0"+stmp;<br>else hs=hs+stmp;<br>if (n<b.length-1) hs='hs+":";<br' /> }<br>return hs.toUpperCase();<br>}<br><br>}<br><br><br><br>2.4. DESede/DES对称算法 <br>首先生成密钥,并保存(这里并没的保存的代码,可参考DSA中的方法)<br><br>KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);<br><br>SecretKey deskey = keygen.generateKey();<br><br>用密钥加密明文(myinfo),生成密文(cipherByte)<br><br>Cipher c1 = Cipher.getInstance(Algorithm);<br><br>c1.init(Cipher.ENCRYPT_MODE,deskey);<br><br>byte[] cipherByte=c1.doFinal(myinfo.getBytes());<br><br>传送密文和密钥,本文没有相应代码可参考DSA<br><br>.............<br><br>用密钥解密密文<br><br>c1 = Cipher.getInstance(Algorithm);<br><br>c1.init(Cipher.DECRYPT_MODE,deskey);<br><br>byte[] clearByte=c1.doFinal(cipherByte);<br><br>相对来说对称密钥的使用是很简单的,对于JCE来讲支技DES,DESede,Blowfish三种加密术<br><br>对于密钥的保存各传送可使用对象流或者用二进制编码,相关参考代码如下 <br>SecretKey deskey = keygen.generateKey();<br>byte[] desEncode=deskey.getEncoded();<br>javax.crypto.spec.SecretKeySpec destmp=new javax.crypto.spec.SecretKeySpec(desEncode,Algorithm);<br>SecretKey mydeskey=destmp;<br><br><br><br>相关API<br><br>KeyGenerator 在DSA中已经说明,在添加JCE后在instance进可以如下参数<br><br>DES,DESede,Blowfish,HmacMD5,HmacSHA1<br><br>javax.crypto.Cipher 加/解密器 public static final Cipher getInstance(java.lang.String transformation)<br>throws java.security.NoSuchAlgorithmException,<br>NoSuchPaddingException<br>返回一个指定方法的Cipher对象<br><br>参数:transformation 方法名(可用 DES,DESede,Blowfish)<br><br>public final void init(int opmode, java.security.Key key)<br>throws java.security.InvalidKeyException<br><br>用指定的密钥和模式初始化Cipher对象<br><br>参数pmode 方式(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)<br><br>key 密钥<br><br><br>public final byte[] doFinal(byte[] input)<br>throws java.lang.IllegalStateException,<br>IllegalBlockSizeException,<br>BadPaddingException<br><br><br><br><br>对input内的串,进行编码处理,返回处理后二进制串,是返回解密文还是加解文由init时的opmode决定<br><br>注意:本方法的执行前如果有update,是对updat和本次input全部处理,否则是本inout的内容<br><br>/*<br>安全程序 DESede/DES测试<br>*/<br>import java.security.*;<br>import javax.crypto.*;<br>public class testdes {<br>public static void main(String[] args){<br>testdes my=new testdes();<br>my.run();<br>}<br>public void run() {<br>//添加新安全算法,如果用JCE就要把它添加进去<br>Security.addProvider(new com.sun.crypto.provider.SunJCE());<br>String Algorithm="DES"; //定义 加密算法,可用 DES,DESede,Blowfish<br>String myinfo="要加密的信息";<br>try {<br>//生成密钥<br>KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);<br>SecretKey deskey = keygen.generateKey();<br><br>//加密<br>System.out.println("加密前的二进串:"+byte2hex(myinfo.getBytes()));<br>System.out.println("加密前的信息:"+myinfo);<br>Cipher c1 = Cipher.getInstance(Algorithm);<br>c1.init(Cipher.ENCRYPT_MODE,deskey);<br>byte[] cipherByte=c1.doFinal(myinfo.getBytes());<br>System.out.println("加密后的二进串:"+byte2hex(cipherByte));<br>//解密<br>c1 = Cipher.getInstance(Algorithm);<br>c1.init(Cipher.DECRYPT_MODE,deskey);<br>byte[] clearByte=c1.doFinal(cipherByte);<br>System.out.println("解密后的二进串:"+byte2hex(clearByte));<br>System.out.println("解密后的信息:"+(new String(clearByte)));<br><br>}<br>catch (java.security.NoSuchAlgorithmException e1) {e1.printStackTrace();}<br>catch (javax.crypto.NoSuchPaddingException e2) {e2.printStackTrace();}<br>catch (java.lang.Exception e3) {e3.printStackTrace();}<br>}<br>public String byte2hex(byte[] b) //二行制转字符串<br>{<br>String hs="";<br>String stmp="";<br>for (int n=0;n<b.length;n++)<br /> {<br>stmp=(java.lang.Integer.toHexString(b[n] &amp; 0XFF));<br>if (stmp.length()==1) hs=hs+"0"+stmp;<br>else hs=hs+stmp;<br>if (n<b.length-1) hs='hs+":";<br' /> }<br>return hs.toUpperCase();<br>}<br><br>}<br><br><br><br>2.5. Diffie-Hellman密钥一致协议 <br>公开密钥密码体制的奠基人Diffie和Hellman所提出的 "指数密钥一致协议"(Exponential Key Agreement Protocol),该协议不要求别的安全性 先决条件,允许两名用户在公开媒体上交换信息以生成"一致"的,可以共享的密钥。在JCE的中实现用户alice生成DH类型的密钥对,如果长度用1024生成的时间请,推荐第一次生成后保存DHParameterSpec,以便下次使用直接初始化.使其速度加快 <br><br>System.out.println("ALICE: 产生 DH 对 ...");<br>KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");<br>aliceKpairGen.initialize(512);<br>KeyPair aliceKpair = aliceKpairGen.generateKeyPair();<br><br><br><br>alice生成公钥发送组bob byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();<br><br><br><br>bob从alice发送来的公钥中读出DH密钥对的初始参数生成bob的DH密钥对<br><br>注意这一步一定要做,要保证每个用户用相同的初始参数生成的 <br>DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();<br>KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");<br>bobKpairGen.initialize(dhParamSpec);<br>KeyPair bobKpair = bobKpairGen.generateKeyPair();<br><br><br><br>bob根据alice的公钥生成本地的DES密钥<br>KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");<br>bobKeyAgree.init(bobKpair.getPrivate());<br>bobKeyAgree.doPhase(alicePubKey, true);<br>SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");<br><br><br><br>bob已经生成了他的DES密钥,他现把他的公钥发给alice,<br>byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();<br><br><br><br>alice根据bob的公钥生成本地的DES密钥<br>,,,,,,解码<br>KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");<br>aliceKeyAgree.init(aliceKpair.getPrivate());<br>aliceKeyAgree.doPhase(bobPubKey, true);<br>SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");<br><br><br><br>bob和alice能过这个过程就生成了相同的DES密钥,在这种基础就可进行安全能信<br><br>常用API<br><br>java.security.KeyPairGenerator 密钥生成器类<br>public static KeyPairGenerator getInstance(String algorithm)<br>throws NoSuchAlgorithmException<br>以指定的算法返回一个KeyPairGenerator 对象<br>参数: algorithm 算法名.如:原来是DSA,现在添加了 DiffieHellman(DH)<br><br>public void initialize(int keysize)<br>以指定的长度初始化KeyPairGenerator对象,如果没有初始化系统以1024长度默认设置<br>参数:keysize 算法位长.其范围必须在 512 到 1024 之间，且必须为 64 的倍数<br>注意:如果用1024生长的时间很长,最好生成一次后就保存,下次就不用生成了<br><br>public void initialize(AlgorithmParameterSpec params)<br>throws InvalidAlgorithmParameterException<br>以指定参数初始化<br><br>javax.crypto.interfaces.DHPublicKey<br>public DHParameterSpec getParams()<br>返回<br>java.security.KeyFactory<br><br>public static KeyFactory getInstance(String algorithm)<br>throws NoSuchAlgorithmException<br>以指定的算法返回一个KeyFactory<br>参数: algorithm 算法名SH,DH<br><br>public final PublicKey generatePublic(KeySpec keySpec)<br>throws InvalidKeySpecException<br>根据指定的key说明,返回一个PublicKey对象<br><br>java.security.spec.X509EncodedKeySpec<br>public X509EncodedKeySpec(byte[] encodedKey)<br>根据指定的二进制编码的字串生成一个key的说明<br>参数:encodedKey 二进制编码的字串(一般能过PublicKey.getEncoded()生成)<br>javax.crypto.KeyAgreement 密码一至类<br><br>public static final KeyAgreement getInstance(java.lang.String algorithm)<br>throws java.security.NoSuchAlgorithmException<br>返回一个指定算法的KeyAgreement对象<br>参数:algorithm 算法名,现在只能是DiffieHellman(DH)<br><br>public final void init(java.security.Key key)<br>throws java.security.InvalidKeyException<br>用指定的私钥初始化<br>参数:key 一个私钥<br><br>public final java.security.Key doPhase(java.security.Key key,<br>boolean lastPhase)<br>throws java.security.InvalidKeyException,<br>java.lang.IllegalStateException<br>用指定的公钥进行定位,lastPhase确定这是否是最后一个公钥,对于两个用户的<br>情况下就可以多次定次,最后确定<br>参数:key 公钥<br>lastPhase 是否最后公钥<br><br>public final SecretKey generateSecret(java.lang.String algorithm)<br>throws java.lang.IllegalStateException,<br>java.security.NoSuchAlgorithmException,<br>java.security.InvalidKeyException<br>根据指定的算法生成密钥<br>参数:algorithm 加密算法(可用 DES,DESede,Blowfish)<br><br><br>*/<br>import java.io.*;<br>import java.math.BigInteger;<br>import java.security.*;<br>import java.security.spec.*;<br>import java.security.interfaces.*;<br>import javax.crypto.*;<br>import javax.crypto.spec.*;<br>import javax.crypto.interfaces.*;<br>import com.sun.crypto.provider.SunJCE;<br><br>public class testDHKey {<br><br><br>public static void main(String argv[]) {<br>try {<br>testDHKey my= new testDHKey();<br>my.run();<br>} catch (Exception e) {<br>System.err.println(e);<br><br>}<br>}<br><br>private void run() throws Exception {<br>Security.addProvider(new com.sun.crypto.provider.SunJCE());<br><br>System.out.println("ALICE: 产生 DH 对 ...");<br>KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");<br>aliceKpairGen.initialize(512);<br>KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); //生成时间长 <br><br>// 张三(Alice)生成公共密钥 alicePubKeyEnc 并发送给李四(Bob) ,<br>//比如用文件方式,socket.....<br>byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();<br><br>//bob接收到alice的编码后的公钥,将其解码<br>KeyFactory bobKeyFac = KeyFactory.getInstance("DH");<br>X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec (alicePubKeyEnc);<br>PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec);<br>System.out.println("alice公钥bob解码成功");<br>// bob必须用相同的参数初始化的他的DH KEY对,所以要从Alice发给他的公开密钥,<br>//中读出参数,再用这个参数初始化他的 DH key对<br><br>//从alicePubKye中取alice初始化时用的参数<br>DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();<br>KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");<br>bobKpairGen.initialize(dhParamSpec);<br>KeyPair bobKpair = bobKpairGen.generateKeyPair();<br>System.out.println("BOB: 生成 DH key 对成功");<br>KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");<br>bobKeyAgree.init(bobKpair.getPrivate());<br>System.out.println("BOB: 初始化本地key成功");<br>//李四(bob) 生成本地的密钥 bobDesKey<br>bobKeyAgree.doPhase(alicePubKey, true);<br>SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");<br>System.out.println("BOB: 用alice的公钥定位本地key,生成本地DES密钥成功");<br>// Bob生成公共密钥 bobPubKeyEnc 并发送给Alice,<br>//比如用文件方式,socket.....,使其生成本地密钥<br>byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();<br>System.out.println("BOB向ALICE发送公钥");<br><br>// alice接收到 bobPubKeyEnc后生成bobPubKey<br>// 再进行定位,使aliceKeyAgree定位在bobPubKey<br>KeyFactory aliceKeyFac = KeyFactory.getInstance("DH");<br>x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc);<br>PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec);<br>System.out.println("ALICE接收BOB公钥并解码成功");<br>;<br>KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");<br>aliceKeyAgree.init(aliceKpair.getPrivate());<br>System.out.println("ALICE: 初始化本地key成功");<br><br>aliceKeyAgree.doPhase(bobPubKey, true);<br>// 张三(alice) 生成本地的密钥 aliceDesKey<br>SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");<br>System.out.println("ALICE: 用bob的公钥定位本地key,并生成本地DES密钥");<br><br>if (aliceDesKey.equals(bobDesKey)) System.out.println("张三和李四的密钥相同");<br>//现在张三和李四的本地的deskey是相同的所以,完全可以进行发送加密,接收后解密,达到<br>//安全通道的的目的<br><br>/*<br>* bob用bobDesKey密钥加密信息<br>*/<br>Cipher bobCipher = Cipher.getInstance("DES");<br>bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey);<br>String bobinfo= "这是李四的机密信息";<br>System.out.println("李四加密前原文:"+bobinfo);<br>byte[] cleartext =bobinfo.getBytes();<br>byte[] ciphertext = bobCipher.doFinal(cleartext);<br><br>/*<br>* alice用aliceDesKey密钥解密<br>*/<br>Cipher aliceCipher = Cipher.getInstance("DES");<br>aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey);<br>byte[] recovered = aliceCipher.doFinal(ciphertext);<br>System.out.println("alice解密bob的信息:"+(new String(recovered)));<br>if (!java.util.Arrays.equals(cleartext, recovered))<br>throw new Exception("解密后与原文信息不同");<br>System.out.println("解密后相同");<br><br>}<br><br>}<br><br><br><br>第3章 小结 <br>在加密术中生成密钥对时，密钥对的当然是越长越好，但费时也越多，请从中从实际出发选取合适的长度，大部分例码中的密钥是每次运行就从新生成，在实际的情况中是生成后在一段时间保存在文件中，再次运行直接从文件中读入，从而加快速度。当然定时更新和加强密钥保管的安全性也是必须的。<br><br>
<img src ="http://www.blogjava.net/junky/aggbug/115844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-05-08 09:28 <a href="http://www.blogjava.net/junky/archive/2007/05/08/115844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>20个java开发人员应该关注得网站</title><link>http://www.blogjava.net/junky/archive/2007/03/20/104953.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Tue, 20 Mar 2007 06:10:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/03/20/104953.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/104953.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/03/20/104953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/104953.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/104953.html</trackback:ping><description><![CDATA[
		<div>
				<a href="http://blog.csdn.net/evil_nowt/archive/2005/05/14/374623.aspx">
						<font color="#ffcf45">JAVA开发者应该去的20个英文网站</font>
				</a>
		</div>
		<div>
				<p>[http://www.javaalmanac.com] - Java开发者年鉴一书的在线版本. 要想快速查到某种Java技巧的用法及示例代码, 这是一个不错的去处. <br />[http://www.onjava.com] - O'Reilly的Java网站. 每周都有新文章. <br />[http://java.sun.com] - 官方的Java开发者网站 - 每周都有新文章发表. <br />[http://www.developer.com/java] - 由Gamelan.com 维护的Java技术文章网站. <br />[http://www.java.net] - Sun公司维护的一个Java社区网站. <br />[http://www.builder.com] - Cnet的Builder.com网站 - 所有的技术文章, 以Java为主. <br />[http://www.ibm.com/developerworks/java] - IBM的Developerworks技术网站; 这是其中的Java技术主页. <br />[http://www.javaworld.com] - 最早的一个Java站点. 每周更新Java技术文章. <br />[http://www.devx.com/java] - DevX维护的一个Java技术文章网站. <br />[http://www.fawcette.com/javapro] - JavaPro在线杂志网站. <br />[http://www.sys-con.com/java] - Java Developers Journal的在线杂志网站. <br />[http://www.javadesktop.org] - 位于Java.net的一个Java桌面技术社区网站. <br />[http://www.theserverside.com] - 这是一个讨论所有Java服务器端技术的网站. <br />[http://www.jars.com] - 提供Java评论服务. 包括各种framework和应用程序. <br />[http://www.jguru.com] - 一个非常棒的采用Q&amp;A形式的Java技术资源社区. <br />[http://www.javaranch.com] - 一个论坛，得到Java问题答案的地方，初学者的好去处。 <br />[http://www.ibiblio.org/javafaq/javafaq.html] - comp.lang.java的FAQ站点 - 收集了来自comp.lang.java新闻组的问题和答案的分类目录. <br />http://java.sun.com/docs/books/tutorial/] - 来自SUN公司的官方Java指南 - 对于了解几乎所有的java技术特性非常有帮助. <br />http://www.javablogs.com] - 互联网上最活跃的一个Java Blog网站. <br />http://java.about.com/] - 来自About.com的Java新闻和技术文章网站.</p>
		</div>
<img src ="http://www.blogjava.net/junky/aggbug/104953.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-03-20 14:10 <a href="http://www.blogjava.net/junky/archive/2007/03/20/104953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java中的final变量需要注意的地方</title><link>http://www.blogjava.net/junky/archive/2007/03/16/104233.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Fri, 16 Mar 2007 05:39:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/03/16/104233.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/104233.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/03/16/104233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/104233.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/104233.html</trackback:ping><description><![CDATA[
		<div class="con_sample">
				<p>对与java中的final变量，java编译器是进行了优化的。每个使用了final类型变量的地方都不会通过连接而进行访问。比如说Test类中使用了Data类中一个final的int数字fNumber=77，这时候，java编译器会将77这个常数编译到Test类的指令码或者常量池中。这样，每次Test类用到fNumber的时候，不会通过引用连接到Data类中进行读取，而是直接使用自己保存在类文件中的副本。用程序说话： Test.java: public class Test{ public static void main(String[] args){ System.out.println(Data.fNumber); } } Data.java: public class Data{ public static final int fNumber=77; } 执行命令和结果： Microsoft Windows XP [版本 5.1.2600] (C) 版权所有 1985-2001 Microsoft Corp. </p>
		</div>
		<div class="con_all">
				<p>
				</p>
				<p>
						<br />
						<font color="#000080">对与java中的final变量，java编译器是进行了优化的。每个使用了final类型变量的地方都不会通过连接而进行访问。比如说Test类中使用了Data类中一个final的int数字fNumber=77，这时候，java编译器会将77这个常数编译到Test类的指令码或者常量池中。这样，每次Test类用到fNumber的时候，不会通过引用连接到Data类中进行读取，而是直接使用自己保存在类文件中的副本。<br />用程序说话：<br />Test.java:</font>
				</p>
				<p>
						<font color="#000080">
								<span class="Code">
										<font color="#000080">public class Test{<br /> public static void main(String[] args){<br />  System.out.println(Data.fNumber);<br /> }<br />}</font>
								</span>
						</font>
				</p>
				<p>
						<br />
						<font color="#000080">Data.java:</font>
				</p>
				<p>
						<font color="#000080">
								<span class="Code" twffan="done">
										<font color="#000080">public class Data{<br /> public static final int fNumber=77; <br />}</font>
								</span>
						</font>
				</p>
				<p>
						<font color="#000080">执行命令和结果：</font>
				</p>
				<p>
						<font color="#000080">Microsoft Windows XP [版本 5.1.2600]<br />(C) 版权所有 1985-2001 Microsoft Corp.</font>
				</p>
				<p>
						<font color="#000080">C:\Documents and Settings\zangmeng&gt;cd ..</font>
				</p>
				<p>
						<font color="#000080">C:\Documents and Settings&gt;cd ..</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;javac Test.java</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;java Test<br />77</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;</font>
				</p>
				<p>
						<br />
						<font color="#000080">这时候，我们更改Data.java的内容：<br />public class Data{<br /> public static final int fNumber=777; <br />}</font>
				</p>
				<p>
						<font color="#000080">然后执行如下命令：</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;javac Data.java</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;java Test<br />77</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;</font>
				</p>
				<p>
						<font color="#000080">这里我们看到，虽然Data.java中的fNumber已经更改为777，而且已经重新编译了，但是因为编译器把fNumber的副本保存Test类中，所以在重新编译Test类的前，Test类一直把fNumber认为是77而不是777。下面我们变异Test.java，再执行，看看结果。</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;javac Test.java</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;java Test<br />777</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;<br />这时候，我们看到，重新编译的Test类将新的777数值封装到了自己类中。</font>
				</p>
				<p>
						<font color="#000080">整个过程如下：<br />Microsoft Windows XP [版本 5.1.2600]<br />(C) 版权所有 1985-2001 Microsoft Corp.</font>
				</p>
				<p>
						<font color="#000080">C:\Documents and Settings\zangmeng&gt;cd ..</font>
				</p>
				<p>
						<font color="#000080">C:\Documents and Settings&gt;cd ..</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;javac Test.java</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;java Test<br />77<br />//在这里改变了Data.java的内容<br />C:\&gt;javac Data.java</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;java Test<br />77</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;javac Test.java</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;java Test<br />777</font>
				</p>
				<p>
						<font color="#000080">C:\&gt;</font>
				</p>
				<p>
				</p>
		</div>
		<div class="story_con_point">
				<p>您认为本文应该得 <select id="oPointRange" name="oPointValue"><option value="1">1</option><option value="2">2</option><option value="3" selected="">3</option><option value="4">4</option><option value="5">5</option></select><input id="btnRankPost" onclick="return UpdateImageDescription(1)" type="button" value="打分" name="btnRankPost" /> <span id="oImageDescription" name="oImageDescription"> <img src="http://dev.csdn.net/images/tech_star1.gif" /> <img src="http://dev.csdn.net/images/tech_star1.gif" /> <img src="http://dev.csdn.net/images/tech_star1.gif" /> <img src="http://dev.csdn.net/images/tech_star3.gif" /> <img src="http://dev.csdn.net/images/tech_star3.gif" /> 共有8人参与打分</span></p>
		</div>
<img src ="http://www.blogjava.net/junky/aggbug/104233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-03-16 13:39 <a href="http://www.blogjava.net/junky/archive/2007/03/16/104233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JFreeChart综合应用</title><link>http://www.blogjava.net/junky/archive/2007/03/16/104227.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Fri, 16 Mar 2007 05:33:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/03/16/104227.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/104227.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/03/16/104227.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/104227.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/104227.html</trackback:ping><description><![CDATA[
		<div class="con_sample">
				<p>主要是网上的一些关于jfreechart的使用文章！发觉有些人就是关心你用没用过，而不是关心你会不会用~</p>
		</div>
		<div class="con_all">
				<p>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">JFreeChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">是一个开源的</span>
						<span lang="EN-US" style="COLOR: black">JAVA</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">项目，它主要用来开发各种各样的图表，这些图表包括：饼图、柱状图</span>
						<span lang="EN-US" style="COLOR: black">(</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">普通柱状图以及堆栈柱状图</span>
						<span lang="EN-US" style="COLOR: black">)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、线图、区域图、分布图、混合图、甘特图以及一些仪表盘等等。在这些不同式样的图表上可以满足目前商业系统的要求。</span>
						<span lang="EN-US" style="COLOR: black">JFreeChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">是一种基于</span>
						<span lang="EN-US" style="COLOR: black">JAVA</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">语言的图表开发技术。</span>
						<span lang="EN-US" style="COLOR: black">JFreeChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">可用于</span>
						<span lang="EN-US" style="COLOR: black">Servlet</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">JSP</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">Applet</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">Java Appication</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">环境中，通过</span>
						<span lang="EN-US" style="COLOR: black">JDBC</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">可动态显示任何数据库数据，结合</span>
						<span lang="EN-US" style="COLOR: black">Itext</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">可以输出至</span>
						<span lang="EN-US" style="COLOR: black">PDF</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">文件。</span>
						<span class="black" lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">
								<?XML:NAMESPACE PREFIX = O /?>
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">JFreeChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">主要是由三个类构成：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">A</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.servlet.ChartDeleter</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">继承自</span>
						<span lang="EN-US" style="COLOR: black">HttpSessionBindingListener</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，用于实现当</span>
						<span lang="EN-US" style="COLOR: black">Session </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">关闭时，删除临时目中的图象文件。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">B</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.servlet.DisplayChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">继承自</span>
						<span lang="EN-US" style="COLOR: black">Httpservlet </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">用于处理显示图象。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">C</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.servlet.ServletUtilities</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">有一系列方法，例如，</span>
						<span lang="EN-US" style="COLOR: black">saveChartAs*;saveChartAs*</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">是把图表按照不同的形式存储为图象；</span>
						<span lang="EN-US" style="COLOR: black">sendTempFile</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法被重载了很多次，用于把文件流发送</span>
						<span lang="EN-US" style="COLOR: black">response</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">下面以柱状图和饼图为例，介绍图形创建方法。</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN: 5pt 0cm 3pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<font lang="ZH-CN" face="黑体" size="4">1 柱状图<o:p></o:p></font>
						<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 黑体">
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.ChartFactory</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">这个工厂类有</span>
						<span lang="EN-US" style="COLOR: black">createBarChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">createStackedBarChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">createBarChart3D</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">createStackedBarChart3D</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，这几个工厂方法创建不同类型的柱状图，比较重要的是</span>
						<span lang="EN-US" style="COLOR: black"> PlotOrientation.VERTICAL </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">让平行柱垂直显示，而</span>
						<span lang="EN-US" style="COLOR: black"> PlotOrientation.HORIZONTAL </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">则让平行柱水平显示。对柱状图影响较大的几个类包括：</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.axis.CategoryAxis</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.axis.ValueAxis</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.renderer.BarRenderer</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.renderer. BarRenderer3D</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">。</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">具体实现步骤：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">1</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）创建用于图形生成所要的数据集对象。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">CategoryDataset dataset = DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">；</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">其中：</span>
						<span lang="EN-US" style="COLOR: black">rowKeys</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">表示</span>
						<span lang="EN-US" style="COLOR: black">X</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">轴数据，</span>
						<span lang="EN-US" style="COLOR: black">columnKeys</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">表示</span>
						<span lang="EN-US" style="COLOR: black">Y</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">轴数据，</span>
						<span lang="EN-US" style="COLOR: black">data</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">表示填充柱状图所要的实际数据（来自于数据库）。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">2</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）创建图形对象。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">JFreeChart chart = ChartFactory.createBarChart3D("</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">标题</span>
						<span lang="EN-US" style="COLOR: black">", null</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，</span>
						<span lang="EN-US" style="COLOR: black">null</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，</span>
						<span lang="EN-US" style="COLOR: black">dataset</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，</span>
						<span lang="EN-US" style="COLOR: black">PlotOrientation.VERTICAL,</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，</span>
						<span lang="EN-US" style="COLOR: black">true</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，</span>
						<span lang="EN-US" style="COLOR: black">false</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，</span>
						<span lang="EN-US" style="COLOR: black">false)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">；</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">createBarChart3D</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法是</span>
						<span lang="EN-US" style="COLOR: black">ChartFactory</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">工厂类里的一个方法，用于</span>
						<span lang="EN-US" style="COLOR: black">3D</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">柱状图的生成，该类继承自</span>
						<span lang="EN-US" style="COLOR: black">JFreeChart</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">。其中的八个参数分别代表：图形的标题、</span>
						<span lang="EN-US" style="COLOR: black">X</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">轴标题、</span>
						<span lang="EN-US" style="COLOR: black">Y</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">轴标题、</span>
						<span lang="EN-US" style="COLOR: black">dataset</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">就是</span>
						<span lang="EN-US" style="COLOR: black">CategoryDataset</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">类的实例对象、显示标题、启用热键、启用超键接。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">3</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）设置图形显示的属性。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">a ) ValueAxis</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">类，设置柱到图上下边的距离。实现方法是：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">ValueAxis rangeAxis = plot.getRangeAxis();<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">设置最高的一个柱与图片顶端的距离：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">rangeAxis.setUpperMargin(0.15)<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">设置最低的一个柱与图片底端的距离：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">rangeAxis.setLowerMargin(0.15)<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">b</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）</span>
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.renderer.BarRenderer3D</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">类，设置图形上显示的数值。实现方法如下：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">BarRenderer3D renderer = new BarRenderer3D();<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setBaseOutlinePaint(Color.BLACK);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">设置</span>
						<span lang="EN-US" style="COLOR: black"> Wall </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">的颜色：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setWallPaint(Color.gray);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">设置每个柱的颜色：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setSeriesPaint(0, new Color(0, 0, 255));<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setSeriesPaint(1, new Color(0, 100, 255));<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setSeriesPaint(2, Color.GREEN);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">设置每个柱的</span>
						<span lang="EN-US" style="COLOR: black"> Outline </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">颜色</span>
						<span lang="EN-US" style="COLOR: black">
								<br />renderer.setSeriesOutlinePaint(0, Color.BLACK);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setSeriesOutlinePaint(1, Color.BLACK);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setSeriesOutlinePaint(2, Color.BLACK);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">设置每个地区所包含的平行柱之间的距离</span>
						<span lang="EN-US" style="COLOR: black">
								<br />renderer.setItemMargin(0.1);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">显示每个柱的数值，并修改该数值的字体属性</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setItemLabelGenerator(new StandardCategoryItemLabelGenerator());<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setItemLabelFont(new Font("</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">黑体</span>
						<span lang="EN-US" style="COLOR: black">",Font.PLAIN,12));<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setItemLabelsVisible(true);<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">为图形加入超连接</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setItemURLGenerator(new StandardCategoryURLGenerator());<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">renderer.setToolTipGenerator(new StandardCategoryToolTipGenerator());<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN: 5pt 0cm 3pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<font lang="ZH-CN" face="黑体" size="4">2 饼图<o:p></o:p></font>
						<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 黑体">
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span lang="EN-US" style="COLOR: black">org.jfree.chart.plot</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">包，包含创建饼形图的所有方法和属性。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span style="COLOR: black; FONT-FAMILY: 宋体">笔者根据业务需求创建了</span>
						<span lang="EN-US" style="COLOR: black">setURLGenerator(PieURLGenerator generator)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法，在图片上建立连接，就是图片不同部分连接不同的资源。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span lang="EN-US" style="COLOR: black">setSectionLabelType(int type)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span style="COLOR: black; FONT-FAMILY: 宋体">指定</span>
						<span lang="EN-US" style="COLOR: black"> section </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">标签的类型，共有</span>
						<span lang="EN-US" style="COLOR: black"> 7 </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">种类型。如果不指定，默认是</span>
						<span lang="EN-US" style="COLOR: black"> NAME_LABELS</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，其中类型分别是：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span lang="EN-US" style="COLOR: black">PiePlot.NO_LABELS<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span lang="EN-US" style="COLOR: black">PiePlot.NAME_LABELS<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span lang="EN-US" style="COLOR: black">PiePlot.VALUE_LABELS<o:p></o:p></span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span lang="EN-US" style="COLOR: black">PiePlot.PERCENT_LABELS </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">PiePlot.NAME_AND_VALUE_LABELS</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">PiePlot. NAME_AND_PERCENT_LABELS</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">、</span>
						<span lang="EN-US" style="COLOR: black">PiePlot.VALUE_AND_PERCENT_LABELS</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">setDefaultOutlinePaint(java.awt.Paint paint)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法，指定</span>
						<span lang="EN-US" style="COLOR: black"> section </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">轮廓线的颜色，如果不指定，默认值为</span>
						<span lang="EN-US" style="COLOR: black">NULL</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">setDefaultOutlineStroke(java.awt.Stroke stroke)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法，指定</span>
						<span lang="EN-US" style="COLOR: black"> section </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">轮廓线的厚度。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">setRadius(double percent) </span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">和</span>
						<span lang="EN-US" style="COLOR: black"> setExplodePercent(int section, double percent)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法，抽离</span>
						<span lang="EN-US" style="COLOR: black"> section</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">，就是把某一</span>
						<span lang="EN-US" style="COLOR: black">section</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">从饼形图剥离出来，需要两个方法一起使用。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">setStartAngle(double angle)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法，设置第一个</span>
						<span lang="EN-US" style="COLOR: black">section</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">开始位置，默认从</span>
						<span lang="EN-US" style="COLOR: black">12</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">点钟方向开始。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">setPaint(int section, java.awt.Paint paint)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法指定</span>
						<span lang="EN-US" style="COLOR: black">section</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">的颜色。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">setDirection(int direction)</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">方法指定</span>
						<span lang="EN-US" style="COLOR: black">section</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">顺序，默认是顺时针方向。顺时针：</span>
						<span lang="EN-US" style="COLOR: black">PiePlot.CLOCKWISE</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">；逆时针：</span>
						<span lang="EN-US" style="COLOR: black">PiePlot.ANTICLOCKWISE</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">具体实现步骤：</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">1</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）创建用于图形生成所要的数据集对象。</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span style="COLOR: black; FONT-FAMILY: 宋体">首先实例化类</span>
						<span lang="EN-US" style="COLOR: black">DefaultPieDataset dataset = new DefaultPieDataset()</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">。然后利用</span>
						<span lang="EN-US" style="COLOR: black">DefaultPieDataset</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">类提供的</span>
						<span lang="EN-US" style="COLOR: black">setValue</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">（</span>
						<span lang="EN-US" style="COLOR: black">value1,value2</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）方法，把从数据库里提取的数据存入</span>
						<span lang="EN-US" style="COLOR: black">DefaultPieDataset</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">对象。其中</span>
						<span lang="EN-US" style="COLOR: black">value1</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">是数据名称、</span>
						<span lang="EN-US" style="COLOR: black">value2</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">是数据值。</span>
						<span lang="EN-US" style="COLOR: black">
								<o:p>
								</o:p>
						</span>
				</p>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
						<span lang="EN-US" style="COLOR: black">2</span>
						<span style="COLOR: black; FONT-FAMILY: 宋体">）创建图形对象。</span>
						<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">
								<o:p>
								</o:p>
						</span>
				</p>
				<p style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span style="COLOR: black; FONT-FAMILY: 宋体">首先实例化<span style="COLOR: black; FONT-FAMILY: 宋体">JFreeChart chart = ChartFactory.createPieChart3D(title, dataset, true, true, false)createPieChart3D</span>方法是用于饼图生成的主要方法。其中<span style="COLOR: black; FONT-FAMILY: 宋体">title</span>代表图形的标题、<span style="COLOR: black; FONT-FAMILY: 宋体">dataset</span>就是<span style="COLOR: black; FONT-FAMILY: 宋体">DefaultPieDataset</span>对象的实例。</span>
				</p>
				<center>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">
										<span style="COLOR: black; FONT-FAMILY: 宋体">3</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">）设置图形显示的属性。</span>
										<o:p>
										</o:p>
								</span>
						</p>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">String filename = ServletUtilities.saveChartAsPNG(jFreeChart, 700, 450, info, session);<o:p></o:p></span>
						</p>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">ChartUtilities.writeImageMap(pw, filename, info);<o:p></o:p></span>
						</p>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">pw.flush()<o:p></o:p></span>
						</p>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">
										<span style="COLOR: black; FONT-FAMILY: 宋体">saveChartAsPNG</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">方法在</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">ServletUtilities</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">工厂类定义完成。主要用于把图形对象</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">JFreeChart</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">以图片的形式保存。其中的</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">jFreeChart</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">就是</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">JFreeChart</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">对象的实例。该方法返回一个文件名。</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">
												<o:p>
												</o:p>
										</span>
								</span>
						</p>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">
										<span style="COLOR: black; FONT-FAMILY: 宋体">writeImageMap</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">（</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">pw, filename, info</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">）方法用于把保存的图片文件以字节流的形式写入用户界面。</span>
										<span style="COLOR: black; FONT-FAMILY: 宋体">
												<o:p>
												</o:p>
										</span>
								</span>
						</p>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">其中<span style="COLOR: black; FONT-FAMILY: 宋体">pw</span><span style="COLOR: black; FONT-FAMILY: 宋体">是</span><span style="COLOR: black; FONT-FAMILY: 宋体">java.io</span><span style="COLOR: black; FONT-FAMILY: 宋体">包的</span><span style="COLOR: black; FONT-FAMILY: 宋体">PrintWriter</span><span style="COLOR: black; FONT-FAMILY: 宋体">类的实例对象，该对象创建一个图形输出流。</span><span style="COLOR: black; FONT-FAMILY: 宋体">Filename</span><span style="COLOR: black; FONT-FAMILY: 宋体">是输出图片的文件名。该文件名来自</span><span style="COLOR: black; FONT-FAMILY: 宋体">ServletUtilities.saveChartAsPNG</span><span style="COLOR: black; FONT-FAMILY: 宋体">方法创建。</span><span style="COLOR: black; FONT-FAMILY: 宋体"><o:p></o:p></span></span>
						</p>
						<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="justify">
								<span style="COLOR: black; FONT-FAMILY: 宋体">参数<span style="COLOR: black; FONT-FAMILY: 宋体">info</span><span style="COLOR: black; FONT-FAMILY: 宋体">用于图形信息的显示。</span><span style="COLOR: black; FONT-FAMILY: 宋体"><o:p></o:p></span></span>
						</p>
				</center>
				<p class="MsoNormal" style="MARGIN-TOP: 1pt; MARGIN-BOTTOM: 1pt; TEXT-INDENT: 24pt; LINE-HEIGHT: 180%" align="left">
						<span style="COLOR: black; FONT-FAMILY: 宋体">用<span style="COLOR: black; FONT-FAMILY: 宋体">ChartRenderingInfo info=new ChartRenderingInfo(new StandardEntityCollection())</span><span style="COLOR: black; FONT-FAMILY: 宋体">创建。</span><span style="COLOR: black; FONT-FAMILY: 宋体"><o:p></o:p></span></span>
				</p>
				<span style="COLOR: black; FONT-FAMILY: 宋体">最后输出完成图形，调用<span style="COLOR: black; FONT-FAMILY: 宋体">pw.flush()</span><span style="COLOR: black; FONT-FAMILY: 宋体">方法关闭</span><span style="COLOR: black; FONT-FAMILY: 宋体">IO</span><span style="COLOR: black; FONT-FAMILY: 宋体">流。<br /><br />------------------------------------------------------------------------------------------<br /></span></span>
				<p>
						<a name="3">
								<span class="atitle">使用JFreeChart生成各种样式的图表</span>
						</a>
				</p>
				<p>限于篇幅的问题我们在这里只实现两种常用的图表，其他类型图表读者可以触类旁通。我们先给出柱状图的实现，饼图的实现再来跟柱状图进行比较。 </p>
				<p>
						<a name="N100F9">
								<span class="smalltitle">1 柱状图</span>
						</a>
				</p>
				<p>
				</p>
				<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
						<tbody>
								<tr>
										<td>
												<pre>
														<code class="section">
																<br />package lius.chart.demo;<br /><br />import java.io.*;<br /><br />import org.jfree.data.*;<br />import org.jfree.chart.*;<br />import org.jfree.chart.plot.*;<br />/**<br /> * 该类用于演示最简单的柱状图生成<br /> * @author Winter Lau<br /> */<br />public class BarChartDemo {<br /><br />	public static void main(String[] args) throws IOException{<br /><br />		CategoryDataset dataset = getDataSet2();<br />		JFreeChart chart = ChartFactory.createBarChart3D(<br />							"水果产量图", // 图表标题<br />							"水果", // 目录轴的显示标签<br />							"产量", // 数值轴的显示标签<br />							dataset, // 数据集<br />							PlotOrientation.VERTICAL, // 图表方向：水平、垂直<br />							true, 	// 是否显示图例(对于简单的柱状图必须是false)<br />							false, 	// 是否生成工具<br />							false 	// 是否生成URL链接<br />							);<br /><br />		FileOutputStream fos_jpg = null;<br />		try {<br />			fos_jpg = new FileOutputStream("D:\\fruit.jpg");<br />			ChartUtilities.writeChartAsJPEG(fos_jpg,100,chart,400,300,null);<br />		} finally {<br />			try {<br />				fos_jpg.close();<br />			} catch (Exception e) {}<br />		}<br />	}<br />	/**<br />	 * 获取一个演示用的简单数据集对象<br />	 * @return<br />	 */<br />	private static CategoryDataset getDataSet() {<br />		DefaultCategoryDataset dataset = new DefaultCategoryDataset();<br />		dataset.addValue(100, null, "苹果");<br />		dataset.addValue(200, null, "梨子");<br />		dataset.addValue(300, null, "葡萄");<br />		dataset.addValue(400, null, "香蕉");<br />		dataset.addValue(500, null, "荔枝");<br />		return dataset;<br />	}<br />	/**<br />	 * 获取一个演示用的组合数据集对象<br />	 * @return<br />	 */<br />	private static CategoryDataset getDataSet2() {<br />		DefaultCategoryDataset dataset = new DefaultCategoryDataset();<br />		dataset.addValue(100, "北京", "苹果");<br />		dataset.addValue(100, "上海", "苹果");<br />		dataset.addValue(100, "广州", "苹果");<br />		dataset.addValue(200, "北京", "梨子");<br />		dataset.addValue(200, "上海", "梨子");<br />		dataset.addValue(200, "广州", "梨子");<br />		dataset.addValue(300, "北京", "葡萄");<br />		dataset.addValue(300, "上海", "葡萄");<br />		dataset.addValue(300, "广州", "葡萄");<br />		dataset.addValue(400, "北京", "香蕉");<br />		dataset.addValue(400, "上海", "香蕉");<br />		dataset.addValue(400, "广州", "香蕉");<br />		dataset.addValue(500, "北京", "荔枝");<br />		dataset.addValue(500, "上海", "荔枝");<br />		dataset.addValue(500, "广州", "荔枝");<br />		return dataset;<br />	}<br />}<br /></code>
												</pre>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<p>程序运行结束后生成的图片文件效果如下图所示：</p>
				<br />
				<a name="N1010A">
						<strong>图4</strong>
				</a>
				<br />
				<img alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-jfreechart/images/image004.gif" />
				<br />
				<p>如果是使用简单的数据即使用getDataSet方法获取数据集时产生的图片文件如下：</p>
				<br />
				<a name="N1011A">
						<strong>图5</strong>
				</a>
				<br />
				<img alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-jfreechart/images/image005.gif" />
				<br />
				<p>
						<a name="N10125">
								<span class="smalltitle">2 饼图</span>
						</a>
				</p>
				<p>
				</p>
				<p>对于饼图而言，数据集的获取用的不是同一个数据集类，另外饼图不支持同一个类别的项目中还有子项目这样的数据。我们只给出创建饼图的代码，至于写图表到一个文件则与柱状图一致，无需重复。 </p>
				<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
						<tbody>
								<tr>
										<td>
												<pre>
														<code class="section">
																<br />package lius.chart.demo;<br /><br />import java.io.*;<br /><br />import org.jfree.data.*;<br />import org.jfree.chart.*;<br />/**<br /> * 用于演示饼图的生成<br /> * @author Winter Lau<br /> */<br />public class PieChartDemo {<br /><br />	public static void main(String[] args) throws IOException{<br />		DefaultPieDataset data = getDataSet();<br />		JFreeChart chart = ChartFactory.createPie3DChart("水果产量图",  // 图表标题<br />		data, <br />		true, // 是否显示图例<br />		false,<br />		false<br />		);<br />		//写图表对象到文件，参照柱状图生成源码<br />	}<br />	/**<br />	 * 获取一个演示用的简单数据集对象<br />	 * @return<br />	 */<br />	private static DefaultPieDataset getDataSet() {<br />		DefaultPieDataset dataset = new DefaultPieDataset();<br />		dataset.setValue("苹果",100);<br />		dataset.setValue("梨子",200);<br />		dataset.setValue("葡萄",300);<br />		dataset.setValue("香蕉",400);<br />		dataset.setValue("荔枝",500);<br />		return dataset;<br />	}<br />}<br /></code>
												</pre>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<p>生成的饼图文件效果如下： </p>
				<br />
				<a name="N10139">
						<strong>图6</strong>
				</a>
				<br />
				<img alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-jfreechart/images/image006.gif" />
				<br />
				<br />
				<table cellspacing="0" cellpadding="0" width="100%" border="0">
						<tbody>
								<tr>
										<td>
												<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
												<br />
												<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
										</td>
								</tr>
						</tbody>
				</table>
				<table class="no-print" cellspacing="0" cellpadding="0" align="right">
						<tbody>
								<tr align="right">
										<td>
												<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
												<br />
												<table cellspacing="0" cellpadding="0" border="0">
														<tbody>
																<tr>
																		<td valign="center">
																				<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																				<br />
																		</td>
																		<td valign="top" align="right">
																				<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/java/l-jfreechart/#main">
																						<strong>
																								<font color="#002c99">回页首</font>
																						</strong>
																				</a>
																		</td>
																</tr>
														</tbody>
												</table>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<br />
				<p>
						<a name="4">
								<span class="atitle">将生成的图表移到浏览器上</span>
						</a>
				</p>
				<p>为了将生成的图表直接传给客户端浏览器，只需要将前面两个例子中的文件流换成是通过HttpServletResponse对象获取到的输出流，详细代码清单如下： </p>
				<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
						<tbody>
								<tr>
										<td>
												<pre>
														<code class="section">
																<br />package lius.chart.demo;<br /><br />import java.io.IOException;<br />import javax.servlet.*;<br />import javax.servlet.http.HttpServlet;<br /><br />import org.jfree.data.*;<br />import org.jfree.chart.*;<br />/**<br /> * 演示通过servlet直接输出图表<br /> * @author Winter Lau<br /> */<br />public class ChartDemoServlet extends HttpServlet {<br /><br />	public void service(ServletRequest req, ServletResponse res)<br />		throws ServletException, IOException <br />	{<br />		res.setContentType("image/jpeg");<br />		DefaultPieDataset data = getDataSet();<br />		JFreeChart chart = ChartFactory.createPie3DChart("水果产量图",<br />		data,<br />		true,<br />		false,<br />		false<br />		);<br /><br />		ChartUtilities.writeChartAsJPEG(res.getOutputStream(),<br />			100,chart,400,300,null);<br />	}<br />	/**<br />	 * 获取一个演示用的简单数据集对象<br />	 * @return<br />	 */<br />	private static DefaultPieDataset getDataSet() {<br />		DefaultPieDataset dataset = new DefaultPieDataset();<br />		dataset.setValue("苹果",100);<br />		dataset.setValue("梨子",200);<br />		dataset.setValue("葡萄",300);<br />		dataset.setValue("香蕉",400);<br />		dataset.setValue("荔枝",500);<br />		return dataset;<br />	}<br />}<br /></code>
												</pre>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<br />
				<br />
				<br />
				<p>
						<a name="5">
								<span class="atitle">高级主题</span>
						</a>
				</p>
				<p>很多情况我们不仅仅要求可以在浏览器上显示一个图表，我们更需要客户可以直接在图表上做一下交互的操作，例如获取信息提示，点击图表某个部分进行更详细信 息的展示等等。例如前面生成的简单柱状图，用户需要在看到柱状图后点击某种水果例如是苹果即可看到各个地区苹果产量的情况。为此就要求该图形具有交互操作 的功能。在HTML中为了让一个图像具有可交互的功能就必须给该图像定义一个Map对象。下表节选一段具有该功能的HTML代码 </p>
				<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
						<tbody>
								<tr>
										<td>
												<pre>
														<code class="section">
																<br />&lt;MAP NAME="chartMap"&gt;<br />&lt;AREA SHAPE="RECT" COORDS="81,15,126,254" href="?series=0&amp;category=100" title="100 = 7,048" <br />	onclick="javascript:clickChart('100');return false;"&gt;<br />&lt;AREA SHAPE="RECT" COORDS="143,27,188,255" href="?series=0&amp;category=200" title="200 = 6,721" <br />	onclick="javascript: clickChart ('200');return false;"&gt;<br />&lt;AREA SHAPE="RECT" COORDS="205,54,250,255" href="?series=0&amp;category=300" title="300 = 5,929" <br />	onclick="javascript: clickChart ('300');return false;"&gt;<br />&lt;AREA SHAPE="RECT" COORDS="267,85,312,255" href="?series=0&amp;category=400" title="400 = 5,005" <br />	onclick="javascript: clickChart ('400');return false;"&gt;<br />&lt;AREA SHAPE="RECT" COORDS="329,17,374,255" href="?series=0&amp;category=Diet" title="Diet = 7,017" onclick="javascript: <br />	clickChart ('Diet');return false;"&gt;<br />&lt;/MAP&gt;<br /></code>
												</pre>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<p>由此就产生了一个问题：如果 根据一个图像来生成对应的MAP对象。我们回头看看刚才的代码，在创建一个图表对象时候有两个参数，我们举柱状图的例子来讲这两个参数就是 ChartFactory. createBarChart3D方法中的最后两个参数，这两个参数的类型都是布尔值。这两个参数意思分别是：是否创建工具提示(tooltip)以及是 否生成URL。这两个参数分别对应着MAP中一个AREA的title属性以及href属性。 </p>
				<p>可是我想知道的是怎么来产生这个MAP啊！哈哈，不要着急，JFreeChart已经帮我们做好生成MAP对象的功 能。为了生成MAP对象就要引入另外一个对象：ChartRenderingInfo。因为JFreeChart没有直接的方法利用一个图表对象直接生成 MAP数据，它需要一个中间对象来过渡，这个对象就是ChartRenderingInfo。下图是生成MAP数据的流程图： </p>
				<br />
				<a name="N10166">
						<strong>图7</strong>
				</a>
				<br />
				<img alt="" src="http://www-128.ibm.com/developerworks/cn/java/l-jfreechart/images/image007.gif" />
				<br />
				<p>如 上图所示，ChartUtilities类是整个流程的核心，它周围的对象都是一些例如数据对象或者是文件等。这个流程简单描述如下：首先创建一个 ChartRenderingInfo对象并在调用ChartUtilities的writeChartAsJPEG时作为最后一个参数传递进去。调用该 方法结束后将产生一个图像文件以及一个填充好MAP数据的ChartRenderingInfo对象，有了这个对象我们还是没有办法获取具体的MAP数 据，我们还必须借助于ChartUtilities的writeImageMap方法来将ChartRenderingInfo对象读取出来，获取MAP 数据的代码片断如下： </p>
				<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
						<tbody>
								<tr>
										<td>
												<pre>
														<code class="section">
																<br />		PrintWriter w = null;<br />		FileOutputStream fos_jpg = null;<br />		FileOutputStream fos_cri = null;<br />		try{<br />			//根据不同类型的图表使用不同类，以下是针对饼图的操作<br />			PiePlot plot = (PiePlot) chart.getPlot();<br />			plot.setURLGenerator(new StandardPieURLGenerator(url));<br />			//设置工具提示<br />		   plot.setToolTipGenerator(new StandardPieToolTipGenerator());<br />			fos_jpg = new FileOutputStream(“d:\\fruit.jpg”); <br />			ChartUtilities.writeChartAsJPEG(<br />				fos_jpg,<br />				100,<br />				chart,<br />				400,<br />				300,<br />				info);<br />			fos_cri = new FileOutputStream(__d:\\fruit.map__);<br />			w = new PrintWriter(fos_cri);<br />			ChartUtilities.writeImageMap(w, __mapname__, info);<br />			w.flush();<br />		}finally{<br />			try{<br />				w.close();<br />			}catch(Exception e){}	<br />			try{<br />				fos_cri.close();<br />			}catch(Exception e){}	<br />			try{<br />				fos_jpg.close();<br />			}catch(Exception e){}<br />		}<br /></code>
												</pre>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<p>打开文件D:\ fruit.map，文件的内容就是要写到页面上的MAP数据。把生成的图像文件以及MAP数据文件写到页面上即可完成热点图表的功能。至于怎么结合两者 之间的关系例如图像的useMap属性值必须与MAP对象的名称结合起来，必须根据实际的应用情况进行相应的处理。笔者建议把二者通过标签库封装起来，图 像文件的名称以及MAP对象的名称由标签库统一进行控制，这样可以保证二者的一致性。 </p>
				<p>
				</p>
		</div>
<img src ="http://www.blogjava.net/junky/aggbug/104227.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-03-16 13:33 <a href="http://www.blogjava.net/junky/archive/2007/03/16/104227.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA字符集(转)</title><link>http://www.blogjava.net/junky/archive/2007/03/16/104225.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Fri, 16 Mar 2007 05:29:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/03/16/104225.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/104225.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/03/16/104225.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/104225.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/104225.html</trackback:ping><description><![CDATA[
		<div class="con_sample">
				<p>本文主要包括以下几个方面：编码基本知识，java，系统软件，url，工具软件等。</p>
		</div>
		<div class="con_all">
				<p>
						<font color="#993300" size="2">1. 概述 <br /><br />本文主要包括以下几个方面：编码基本知识，java，系统软件，url，工具软件等。 <br /><br />在下面的描述中，将以"中文"两个字为例，经查表可以知道其GB2312编码是"d6d0 cec4"，Unicode编码为"4e2d 6587"，UTF编码就是"e4b8ad e69687"。注意，这两个字没有iso8859-1编码，但可以用iso8859-1编码来"表示"。 <br /><br />2. 编码基本知识 <br /><br />最早的编码是iso8859-1，和ascii编码相似。但为了方便表示各种各样的语言，逐渐出现了很多标准编码，重要的有如下几个。 <br /><br />2.1. iso8859-1 <br /><br />属于单字节编码，最多能表示的字符范围是0-255，应用于英文系列。比如，字母'a'的编码为0x61=97。 <br /><br />很明显，iso8859-1编码表示的字符范围很窄，无法表示中文字符。但是，由于是单字节编码，和计算机最基础的表示单位一致，所以很多时候，仍旧使用iso8859-1编码来表示。而且在很多协议上，默认使用该编码。比如，虽然"中文"两个字不存在iso8859-1编码，以gb2312编码为例，应该是"d6d0 cec4"两个字符，使用iso8859-1编码的时候则将它拆开为4个字节来表示："d6 d0 ce c4"（事实上，在进行存储的时候，也是以字节为单位处理的）。而如果是UTF编码，则是6个字节"e4 b8 ad e6 96 87"。很明显，这种表示方法还需要以另一种编码为基础。 <br /><br />2.2. GB2312/GBK <br /><br />这就是汉子的国标码，专门用来表示汉字，是双字节编码，而英文字母和iso8859-1一致（兼容iso8859-1编码）。其中gbk编码能够用来同时表示繁体字和简体字，而gb2312只能表示简体字，gbk是兼容gb2312编码的。 <br /><br />2.3. unicode <br /><br />这是最统一的编码，可以用来表示所有语言的字符，而且是定长双字节（也有四字节的）编码，包括英文字母在内。所以可以说它是不兼容iso8859-1编码的，也不兼容任何编码。不过，相对于iso8859-1编码来说，uniocode编码只是在前面增加了一个0字节，比如字母'a'为"00 61"。 <br /><br />需要说明的是，定长编码便于计算机处理（注意GB2312/GBK不是定长编码），而unicode又可以用来表示所有字符，所以在很多软件内部是使用unicode编码来处理的，比如java。 <br /><br />2.4. UTF <br /><br />考虑到unicode编码不兼容iso8859-1编码，而且容易占用更多的空间：因为对于英文字母，unicode也需要两个字节来表示。所以unicode不便于传输和存储。因此而产生了utf编码，utf编码兼容iso8859-1编码，同时也可以用来表示所有语言的字符，不过，utf编码是不定长编码，每一个字符的长度从1-6个字节不等。另外，utf编码自带简单的校验功能。一般来讲，英文字母都是用一个字节表示，而汉字使用三个字节。 <br /><br />注意，虽然说utf是为了使用更少的空间而使用的，但那只是相对于unicode编码来说，如果已经知道是汉字，则使用GB2312/GBK无疑是最节省的。不过另一方面，值得说明的是，虽然utf编码对汉字使用3个字节，但即使对于汉字网页，utf编码也会比unicode编码节省，因为网页中包含了很多的英文字符。 <br /><br />3. java对字符的处理 <br /><br />在java应用软件中，会有多处涉及到字符集编码，有些地方需要进行正确的设置，有些地方需要进行一定程度的处理。 <br /><br />3.1. getBytes(charset) <br /><br />这是java字符串处理的一个标准函数，其作用是将字符串所表示的字符按照charset编码，并以字节方式表示。注意字符串在java内存中总是按unicode编码存储的。比如"中文"，正常情况下（即没有错误的时候）存储为"4e2d 6587"，如果charset为"gbk"，则被编码为"d6d0 cec4"，然后返回字节"d6 d0 ce c4"。如果charset为"utf8"则最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1"，则由于无法编码，最后返回 "3f 3f"（两个问号）。 <br /><br />3.2. new String(charset) <br /><br />这是java字符串处理的另一个标准函数，和上一个函数的作用相反，将字节数组按照charset编码进行组合识别，最后转换为unicode存储。参考上述getBytes的例子，"gbk" 和"utf8"都可以得出正确的结果"4e2d 6587"，但iso8859-1最后变成了"003f 003f"（两个问号）。 <br /><br />因为utf8可以用来表示/编码所有字符，所以new String( str.getBytes( "utf8" ), "utf8" ) === str，即完全可逆。 <br /><br />3.3. setCharacterEncoding() <br /><br />该函数用来设置http请求或者相应的编码。 <br /><br />对于request，是指提交内容的编码，指定后可以通过getParameter()则直接获得正确的字符串，如果不指定，则默认使用iso8859-1编码，需要进一步处理。参见下述"表单输入"。值得注意的是在执行setCharacterEncoding()之前，不能执行任何getParameter()。java doc上说明：This method must be called prior to reading request parameters or reading input using getReader()。而且，该指定只对POST方法有效，对GET方法无效。分析原因，应该是在执行第一个getParameter()的时候，java将会按照编码分析所有的提交内容，而后续的getParameter()不再进行分析，所以setCharacterEncoding()无效。而对于GET方法提交表单是，提交的内容在URL中，一开始就已经按照编码分析所有的提交内容，setCharacterEncoding()自然就无效。 <br /><br />对于response，则是指定输出内容的编码，同时，该设置会传递给浏览器，告诉浏览器输出内容所采用的编码。 <br /><br />3.4. 处理过程 <br /><br />下面分析两个有代表性的例子，说明java对编码有关问题的处理方法。 <br /><br />3.4.1. 表单输入 <br /><br />User input  *(gbk:d6d0 cec4)  browser  *(gbk:d6d0 cec4)  web server  iso8859-1(00d6 00d 000ce 00c4)  class，需要在class中进行处理：getbytes("iso8859-1")为d6 d0 ce c4，new String("gbk")为d6d0 cec4，内存中以unicode编码则为4e2d 6587。 <br /><br />l 用户输入的编码方式和页面指定的编码有关，也和用户的操作系统有关，所以是不确定的，上例以gbk为例。 <br /><br />l 从browser到web server，可以在表单中指定提交内容时使用的字符集，否则会使用页面指定的编码。而如果在url中直接用?的方式输入参数，则其编码往往是操作系统本身的编码，因为这时和页面无关。上述仍旧以gbk编码为例。 <br /><br />l Web server接收到的是字节流，默认时（getParameter）会以iso8859-1编码处理之，结果是不正确的，所以需要进行处理。但如果预先设置了编码（通过request. setCharacterEncoding ()），则能够直接获取到正确的结果。 <br /><br />l 在页面中指定编码是个好习惯，否则可能失去控制，无法指定正确的编码。 <br /><br />3.4.2. 文件编译 <br /><br />假设文件是gbk编码保存的，而编译有两种编码选择：gbk或者iso8859-1，前者是中文windows的默认编码，后者是linux的默认编码，当然也可以在编译时指定编码。 <br /><br />Jsp  *(gbk:d6d0 cec4)  java file  *(gbk:d6d0 cec4)  compiler read  uincode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  compiler write  utf(gbk: e4b8ad e69687; iso8859-1: *)  compiled file  unicode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  class。所以用gbk编码保存，而用iso8859-1编译的结果是不正确的。 <br /><br />class  unicode(4e2d 6587)  system.out / jsp.out  gbk(d6d0 cec4)  os console / browser。 <br /><br />l 文件可以以多种编码方式保存，中文windows下，默认为ansi/gbk。 <br /><br />l 编译器读取文件时，需要得到文件的编码，如果未指定，则使用系统默认编码。一般class文件，是以系统默认编码保存的，所以编译不会出问题，但对于jsp文件，如果在中文windows下编辑保存，而部署在英文linux下运行/编译，则会出现问题。所以需要在jsp文件中用pageEncoding指定编码。 <br /><br />l Java编译的时候会转换成统一的unicode编码处理，最后保存的时候再转换为utf编码。 <br /><br />l 当系统输出字符的时候，会按指定编码输出，对于中文windows下，System.out将使用gbk编码，而对于response（浏览器），则使用jsp文件头指定的contentType，或者可以直接为response指定编码。同时，会告诉browser网页的编码。如果未指定，则会使用iso8859-1编码。对于中文，应该为browser指定输出字符串的编码。 <br /><br />l browser显示网页的时候，首先使用response中指定的编码（jsp文件头指定的contentType最终也反映在response上），如果未指定，则会使用网页中meta项指定中的contentType。 <br /><br />3.5. 几处设置 <br /><br />对于web应用程序，和编码有关的设置或者函数如下。 <br /><br />3.5.1. jsp编译 <br /><br />指定文件的存储编码，很明显，该设置应该置于文件的开头。例如：&lt;%@page pageEncoding="GBK"%&gt;。另外，对于一般class文件，可以在编译的时候指定编码。 <br /><br />3.5.2. jsp输出 <br /><br />指定文件输出到browser是使用的编码，该设置也应该置于文件的开头。例如：&lt;%@ page contentType="text/html; charset= GBK" %&gt;。该设置和response.setCharacterEncoding("GBK")等效。 <br /><br />3.5.3. meta设置 <br /><br />指定网页使用的编码，该设置对静态网页尤其有作用。因为静态网页无法采用jsp的设置，而且也无法执行response.setCharacterEncoding()。例如：&lt;META http-equiv="Content-Type" content="text/html; charset=GBK" /&gt; <br /><br />如果同时采用了jsp输出和meta设置两种编码指定方式，则jsp指定的优先。因为jsp指定的直接体现在response中。 <br /><br />需要注意的是，apache有一个设置可以给无编码指定的网页指定编码，该指定等同于jsp的编码指定方式，所以会覆盖静态网页中的meta指定。所以有人建议关闭该设置。 <br /><br />3.5.4. form设置 <br /><br />当浏览器提交表单的时候，可以指定相应的编码。例如：&lt;form accept-charset= "gb2312"&gt;。一般不必不使用该设置，浏览器会直接使用网页的编码。 <br /><br />4. 系统软件 <br /><br />下面讨论几个相关的系统软件。 <br /><br />4.1. mysql数据库 <br /><br />很明显，要支持多语言，应该将数据库的编码设置成utf或者unicode，而utf更适合与存储。但是，如果中文数据中包含的英文字母很少，其实unicode更为适合。 <br /><br />数据库的编码可以通过mysql的配置文件设置，例如default-character-set=utf8。还可以在数据库链接URL中设置，例如： useUnicode=true&amp;characterEncoding=UTF-8。注意这两者应该保持一致，在新的sql版本里，在数据库链接URL里可以不进行设置，但也不能是错误的设置。 <br /><br />4.2. apache <br /><br />appache和编码有关的配置在httpd.conf中，例如AddDefaultCharset UTF-8。如前所述，该功能会将所有静态页面的编码设置为UTF-8，最好关闭该功能。 <br /><br />另外，apache还有单独的模块来处理网页响应头，其中也可能对编码进行设置。 <br /><br />4.3. linux默认编码 <br /><br />这里所说的linux默认编码，是指运行时的环境变量。两个重要的环境变量是LC_ALL和LANG，默认编码会影响到java URLEncode的行为，下面有描述。 <br /><br />建议都设置为"zh_CN.UTF-8"。 <br /><br />4.4. 其它 <br /><br />为了支持中文文件名，linux在加载磁盘时应该指定字符集，例如：mount /dev/hda5 /mnt/hda5/ -t ntfs -o iocharset=gb2312。 <br /><br />另外，如前所述，使用GET方法提交的信息不支持request.setCharacterEncoding()，但可以通过tomcat的配置文件指定字符集，在tomcat的server.xml文件中，形如：&lt;Connector ... URIEncoding="GBK"/&gt;。这种方法将统一设置所有请求，而不能针对具体页面进行设置，也不一定和browser使用的编码相同，所以有时候并不是所期望的。 <br /><br />5. URL地址 <br /><br />URL地址中含有中文字符是很麻烦的，前面描述过使用GET方法提交表单的情况，使用GET方法时，参数就是包含在URL中。 <br /><br />5.1. URL编码 <br /><br />对于URL中的一些特殊字符，浏览器会自动进行编码。这些字符除了"/?&amp;"等外，还包括unicode字符，比如汉子。这时的编码比较特殊。 <br /><br />IE有一个选项"总是使用UTF-8发送URL"，当该选项有效时，IE将会对特殊字符进行UTF-8编码，同时进行URL编码。如果改选项无效，则使用默认编码"GBK"，并且不进行URL编码。但是，对于URL后面的参数，则总是不进行编码，相当于UTF-8选项无效。比如"中文.html?a=中文"，当UTF-8选项有效时，将发送链接"%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87"；而UTF-8选项无效时，将发送链接"\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"两个字只有4个字节，而前者却有18个字节，这主要时URL编码的原因。 <br /><br />当web server（tomcat）接收到该链接时，将会进行URL解码，即去掉"%"，同时按照ISO8859-1编码（上面已经描述，可以使用URLEncoding来设置成其它编码）识别。上述例子的结果分别是"\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"和"\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87"，注意前者前面的"中文"两个字恢复成了6个字符。这里用"\u"，表示是unicode。 <br /><br />所以，由于客户端设置的不同，相同的链接，在服务器上得到了不同结果。这个问题不少人都遇到，却没有很好的解决办法。所以有的网站会建议用户尝试关闭UTF-8选项。不过，下面会描述一个更好的处理办法。 <br /><br />5.2. rewrite <br /><br />熟悉的人都知道，apache有一个功能强大的rewrite模块，这里不描述其功能。需要说明的是该模块会自动将URL解码（去除%），即完成上述web server（tomcat）的部分功能。有相关文档介绍说可以使用[NE]参数来关闭该功能，但我试验并未成功，可能是因为版本（我使用的是apache 2.0.54）问题。另外，当参数中含有"?&amp; "等符号的时候，该功能将导致系统得不到正常结果。 <br /><br />rewrite本身似乎完全是采用字节处理的方式，而不考虑字符串的编码，所以不会带来编码问题。 <br /><br />5.3. URLEncode.encode() <br /><br />这是Java本身提供对的URL编码函数，完成的工作和上述UTF-8选项有效时浏览器所做的工作相似。值得说明的是，java已经不赞成不指定编码来使用该方法（deprecated）。应该在使用的时候增加编码指定。 <br /><br />当不指定编码的时候，该方法使用系统默认编码，这会导致软件运行结果得不确定。比如对于"中文"，当系统默认编码为"gb2312"时，结果是"%4e%2d%65%87"，而默认编码为"UTF-8"，结果却是"%e4%b8%ad%e6%96%87"，后续程序将难以处理。另外，这儿说的系统默认编码是由运行tomcat时的环境变量LC_ALL和LANG等决定的，曾经出现过tomcat重启后就出现乱码的问题，最后才郁闷的发现是因为修改修改了这两个环境变量。 <br /><br />建议统一指定为"UTF-8"编码，可能需要修改相应的程序。 <br /><br />5.4. 一个解决方案 <br /><br />上面说起过，因为浏览器设置的不同，对于同一个链接，web server收到的是不同内容，而软件系统有无法知道这中间的区别，所以这一协议目前还存在缺陷。 <br /><br />针对具体问题，不应该侥幸认为所有客户的IE设置都是UTF-8有效的，也不应该粗暴的建议用户修改IE设置，要知道，用户不可能去记住每一个web server的设置。所以，接下来的解决办法就只能是让自己的程序多一点智能：根据内容来分析编码是否UTF-8。 <br /><br />比较幸运的是UTF-8编码相当有规律，所以可以通过分析传输过来的链接内容，来判断是否是正确的UTF-8字符，如果是，则以UTF-8处理之，如果不是，则使用客户默认编码（比如"GBK"），下面是一个判断是否UTF-8的例子，如果你了解相应规律，就容易理解。 <br /><br />public static boolean isValidUtf8(byte[] b,int aMaxCount){ <br /><br />       int lLen=b.length,lCharCount=0; <br /><br />       for(int i=0;i&lt;lLen &amp;&amp; lCharCount&lt;aMaxCount;++lCharCount){ <br /><br />              byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;) <br /><br />              if(lByte&gt;=0) continue;//&gt;=0 is normal ascii <br /><br />              if(lByte&lt;(byte)0xc0 || lByte&gt;(byte)0xfd) return false; <br /><br />              int lCount=lByte&gt;(byte)0xfc?5:lByte&gt;(byte)0xf8?4 <br /><br />                     :lByte&gt;(byte)0xf0?3:lByte&gt;(byte)0xe0?2:1; <br /><br />              if(i+lCount&gt;lLen) return false; <br /><br />              for(int j=0;j&lt;lCount;++j,++i) if(b[i]&gt;=(byte)0xc0) return false; <br /><br />       } <br /><br />       return true; <br /><br />} <br /><br />相应地，一个使用上述方法的例子如下： <br /><br />public static String getUrlParam(String aStr,String aDefaultCharset) <br /><br />throws UnsupportedEncodingException{ <br /><br />       if(aStr==null) return null; <br /><br />       byte[] lBytes=aStr.getBytes("ISO-8859-1"); <br /><br />       return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset); <br /><br />} <br /><br />不过，该方法也存在缺陷，如下两方面： <br /><br />l 没有包括对用户默认编码的识别，这可以根据请求信息的语言来判断，但不一定正确，因为我们有时候也会输入一些韩文，或者其他文字。 <br /><br />l 可能会错误判断UTF-8字符，一个例子是"学习"两个字，其GBK编码是" \xd1\xa7\xcf\xb0"，如果使用上述isValidUtf8方法判断，将返回true。可以考虑使用更严格的判断方法，不过估计效果不大。 <br /><br />有一个例子可以证明google也遇到了上述问题，而且也采用了和上述相似的处理方法，比如，如果在地址栏中输入"http://www.google.com/search?hl=zh-CN&amp;newwindow=1&amp;q=学习"，google将无法正确识别，而其他汉字一般能够正常识别。 <br /><br />最后，应该补充说明一下，如果不使用rewrite规则，或者通过表单提交数据，其实并不一定会遇到上述问题，因为这时可以在提交数据时指定希望的编码。另外，中文文件名确实会带来问题，应该谨慎使用。 <br /><br />6. 其它 <br /><br />下面描述一些和编码有关的其他问题。 <br /><br />6.1. SecureCRT <br /><br />除了浏览器和控制台与编码有关外，一些客户端也很有关系。比如在使用SecureCRT连接linux时，应该让SecureCRT的显示编码（不同的session，可以有不同的编码设置）和linux的编码环境变量保持一致。否则看到的一些帮助信息，就可能是乱码。 <br /><br />另外，mysql有自己的编码设置，也应该保持和SecureCRT的显示编码一致。否则通过SecureCRT执行sql语句的时候，可能无法处理中文字符，查询结果也会出现乱码。 <br /><br />对于Utf-8文件，很多编辑器（比如记事本）会在文件开头增加三个不可见的标志字节，如果作为mysql的输入文件，则必须要去掉这三个字符。（用linux的vi保存可以去掉这三个字符）。一个有趣的现象是，在中文windows下，创建一个新txt文件，用记事本打开，输入"连通"两个字，保存，再打开，你会发现两个字没了，只留下一个小黑点。 <br /><br />6.2. 过滤器 <br /><br />如果需要统一设置编码，则通过filter进行设置是个不错的选择。在filter class中，可以统一为需要的请求或者回应设置编码。参加上述setCharacterEncoding()。这个类apache已经给出了可以直接使用的例子SetCharacterEncodingFilter。 <br /><br />6.3. POST和GET <br /><br />很明显，以POST提交信息时，URL有更好的可读性，而且可以方便的使用setCharacterEncoding()来处理字符集问题。但GET方法形成的URL能够更容易表达网页的实际内容，也能够用于收藏。 <br /><br />从统一的角度考虑问题，建议采用GET方法，这要求在程序中获得参数是进行特殊处理，而无法使用setCharacterEncoding()的便利，如果不考虑rewrite，就不存在IE的UTF-8问题，可以考虑通过设置URIEncoding来方便获取URL中的参数。 <br /><br />6.4. 简繁体编码转换 <br /><br />GBK同时包含简体和繁体编码，也就是说同一个字，由于编码不同，在GBK编码下属于两个字。有时候，为了正确取得完整的结果，应该将繁体和简体进行统一。可以考虑将UTF、GBK中的所有繁体字，转换为相应的简体字，BIG5编码的数据，也应该转化成相应的简体字。当然，仍旧以UTF编码存储。 <br /><br />例如，对于"语言 ?言"，用UTF表示为"\xE8\xAF\xAD\xE8\xA8\x80 \xE8\xAA\x9E\xE8\xA8\x80"，进行简繁体编码转换后应该是两个相同的 "\xE8\xAF\xAD\xE8\xA8\x80&gt;"。 <br /></font>
				</p>
		</div>
<img src ="http://www.blogjava.net/junky/aggbug/104225.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-03-16 13:29 <a href="http://www.blogjava.net/junky/archive/2007/03/16/104225.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>始终会用上的Common BeanUtils(转)</title><link>http://www.blogjava.net/junky/archive/2007/03/16/104221.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Fri, 16 Mar 2007 05:17:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/03/16/104221.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/104221.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/03/16/104221.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/104221.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/104221.html</trackback:ping><description><![CDATA[
		<p>Beanutils用了魔术般的反射技术，实现了很多夸张有用的功能，都是C/C++时代不敢想的。无论谁的项目，始终一天都会用得上它。我算是后知后觉了，第一回看到它的时候居然错过。</p>
		<p>
				<font size="3">
						<strong>1.属性的动态getter、setter </strong>
				</font>
		</p>
		<div>在这框架满天飞的年代，不能事事都保证执行getter,setter函数了，有时候属性是要根据名字动态取得的，就像这样：　　</div>
		<pre>BeanUtils.getProperty(myBean,"code");</pre>
		<div>而Common BeanUtils的更强功能在于可以直接访问内嵌对象的属性，只要使用点号分隔。</div>
		<pre>BeanUtils.getProperty(orderBean, "address.city");</pre>
		<div>相比之下其他类库的BeanUtils通常都很简单，不能访问内嵌的对象，所以有时要用Commons BeanUtils来替换它们。<br /><br />BeanUtils还支持List和Map类型的属性，如下面的语法即可取得Order的顾客列表中第一个顾客的名字</div>
		<pre>BeanUtils.getProperty(orderBean, "customers[1].name");</pre>
		<div>其中BeanUtils会使用ConvertUtils类把字符串转为Bean属性的真正类型，方便从HttpServletRequest等对象中提取bean，或者把bean输出到页面。</div>
		<div>而PropertyUtils就会原色的保留Bean原来的类型。</div>
		<p>
				<font size="3">
						<strong>2.BeanCompartor 动态排序 </strong>
				</font>
		</p>
		<div>还是通过反射，动态设定Bean按照哪个属性来排序，而不再需要在实现bean的Compare接口进行复杂的条件判断。 </div>
		<pre>List peoples = ...; // Person对象的列表Collections.sort(peoples, new BeanComparator("age"));</pre>
		<p>如果要支持多个属性的复合排序，如"Order By lastName,firstName" </p>
		<pre>ArrayList sortFields = new ArrayList();sortFields.add(new BeanComparator("lastName"));sortFields.add(new BeanComparator("firstName"));ComparatorChain multiSort = new ComparatorChain(sortFields);Collections.sort(rows,multiSort);</pre>
		<p>其中ComparatorChain属于jakata commons-collections包。<br />如果age属性不是普通类型，构造函数需要再传入一个comparator对象为age变量排序。<br />另外, BeanCompartor本身的ComparebleComparator, 遇到属性为null就会抛出异常, 也不能设定升序还是降序。这个时候又要借助commons-collections包的ComparatorUtils.</p>
		<p>
		</p>
		<pre>   Comparator mycmp = ComparableComparator.getInstance();<br />   mycmp = ComparatorUtils.nullLowComparator(mycmp);  //允许null<br />   mycmp = ComparatorUtils.reversedComparator(mycmp); //逆序<br />   Comparator cmp = new BeanComparator(sortColumn, mycmp);</pre>
		<p>
		</p>
		<font size="3">
				<strong>3.Converter 把Request或ResultSet中的字符串绑定到对象的属性 </strong>
		</font>
		<p>   经常要从request,resultSet等对象取出值来赋入bean中，如果不用MVC框架的绑定功能的话，下面的代码谁都写腻了。</p>
		<pre>   String a = request.getParameter("a");   bean.setA(a);   String b = ....<br />   bean.setB(b);<br />   ......</pre>
		<p>不妨写一个Binder自动绑定所有属性:</p>
		<pre>    MyBean bean = ...;    HashMap map = new HashMap();    Enumeration names = request.getParameterNames();    while (names.hasMoreElements())    {      String name = (String) names.nextElement();      map.put(name, request.getParameterValues(name));    }    BeanUtils.populate(bean, map);</pre>
		<p>    其中BeanUtils的populate方法或者getProperty,setProperty方法其实都会调用convert进行转换。<br />    但Converter只支持一些基本的类型，甚至连java.util.Date类型也不支持。而且它比较笨的一个地方是当遇到不认识的类型时，居然会抛出异常来。 对于Date类型，我参考它的sqldate类型实现了一个Converter，而且添加了一个设置日期格式的函数。<br />要把这个Converter注册，需要如下语句：</p>
		<pre>    ConvertUtilsBean convertUtils = new ConvertUtilsBean();<br />   DateConverter dateConverter = new DateConverter();<br />   convertUtils.register(dateConverter,Date.class);<br /><br /><br /><br />    //因为要注册converter,所以不能再使用BeanUtils的静态方法了，必须创建BeanUtilsBean实例<br />    BeanUtilsBean beanUtils = new BeanUtilsBean(convertUtils,new PropertyUtilsBean());<br />   beanUtils.setProperty(bean, name, value);</pre>
		<font size="3">
				<strong>4 其他功能</strong>
		</font>
		<div>
				<strong>4.1 ConstructorUtils，动态创建对象</strong>
		</div>
		<div>
				<pre>     public static Object invokeConstructor(Class klass, Object arg)</pre>
				<strong>4.2 MethodUtils，动态调用方法</strong>
				<pre>    MethodUtils.invokeMethod(bean, methodName, parameter);</pre>
		</div>
		<br />
		<strong>4.3 PropertyUtils，当属性为Collection,Map时的动态读取：<br /></strong>Collection: 提供index<br /><div><pre>   BeanUtils.getIndexedProperty(orderBean,"items",1);</pre>或者<pre>  BeanUtils.getIndexedProperty(orderBean,"items[1]");</pre>Map: 提供Key Value<pre>  BeanUtils.getMappedProperty(orderBean, "items","111");//key-value goods_no=111 </pre>或者<pre>  BeanUtils.getMappedProperty(orderBean, "items(111)") </pre></div><div><strong><br />4.4 PropertyUtils，直接获取属性的Class类型</strong></div><pre>     public static Class getPropertyType(Object bean, String name)</pre><div><strong>4.5 动态Bean </strong>见<a href="http://blog.csdn.net/calvinxiu/archive/2005/02/02/277765.aspx" target="__blank">用DynaBean减除不必要的VO和FormBean </a><br /></div><br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=277748</p><img src ="http://www.blogjava.net/junky/aggbug/104221.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-03-16 13:17 <a href="http://www.blogjava.net/junky/archive/2007/03/16/104221.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>递归删除文件夹内与给定的文件名不符的文件和所有的文件夹</title><link>http://www.blogjava.net/junky/archive/2007/03/14/103760.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 14 Mar 2007 05:09:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/03/14/103760.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/103760.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/03/14/103760.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/103760.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/103760.html</trackback:ping><description><![CDATA[
		<div class="con_all">
				<p>
				</p>
				<p>import java.io.*;<br />/*<br /> * 递归删除文件夹内与给定的文件名不符的文件和所有的文件夹<br /> */<br />public class Test3 {<br /> public static void checkName(String[] filelist) {<br />  File file = new File("D:\\temp");<br />  File[] files = file.listFiles();<br />  boolean flag = true;<br />  for (int i = 0; i &lt; files.length; i++) {<br />   for (int j = 0; j &lt; filelist.length; j++) {<br />    if (files[i].isFile()) {<br />     if (files[i].getName().equals(filelist[j])) {<br />      flag = false;<br />      break;<br />     } else {<br />      flag = true;<br />     }<br />    } else if (files[i].isDirectory()) {<br />     del(files[i]);<br />    }</p>
				<p>   }<br />   if (flag) {<br />    files[i].delete();<br />   }<br />  }</p>
				<p> }</p>
				<p> private static void del(File f) {<br />  if (f.isFile()) {<br />   f.delete();<br />  } else if (f.isDirectory()) {<br />   String[] files = f.list();<br />   for (int i = 0; i &lt; files.length; i++)<br />    del(new java.io.File(f.getAbsolutePath() + "\\" + files[i]));<br />   f.delete();<br />  }<br /> }</p>
				<p>
				</p>
		</div>
<img src ="http://www.blogjava.net/junky/aggbug/103760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-03-14 13:09 <a href="http://www.blogjava.net/junky/archive/2007/03/14/103760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java.util.regex.Pattern(转)</title><link>http://www.blogjava.net/junky/archive/2007/01/21/95133.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 21 Jan 2007 07:05:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2007/01/21/95133.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/95133.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2007/01/21/95133.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/95133.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/95133.html</trackback:ping><description><![CDATA[
		<span id="ArticleContent1_ArticleContent1_lblContent"> 
<p>这两天刚好想学习正则表达式，不过网上找不到什么好资料，只好自己看api，今天上午<br />边看边翻译了一些，由于第一次翻译，错误很多，望各位不吝指正：<br /><br />java.util.regex.Pattern<br /><br />正则表达式的一种已编译的实现。<br /><br />正则表达式通常以字符串的形式出现，它首先必须被编译为Pattern类的一个实例。<br />结果模型可以用来生成一个Matcher，它（生成的Macher实例）可以匹配根据<br />这个正则表达式生成的任意字符序列。在实现一个匹配器中的匹配时包括了<br />任意多的情况，并且多个匹配器可以共享同一个匹配模式。<br />下面是一个典型的调用次序：<br /><br />Pattern p = Pattern.compile("a*b");<br />Matcher m = p.matcher("aaaaab");<br />boolean b = m.matches();<br /><br />为了方便使用，Pattern类也定义了matches()方法，<br />因为有时候一个正则表达使只用到一次。<br />在一次调用中，这个方法首先编译表达式，然后匹配输入的序列。<br />下面这个句子：<br /><br />boolean b = Pattern.matches("a*b", "aaaaab");<br /><br />等价于上面的三个句子。但是由于它不允许便以后的模式被重用，所以在需要重复匹配<br />时显然比上面的方法效率要低。<br /><br />Pattern类的实例不能被改变，并且是线程安全的。注意，Matcher类并不是线程安全的<br />。<br /><br />正则表达式结构简介：<br />字符：<br />x   字符 x <br />\\  反斜杠<br />\0n     十进制数 (0 &lt;= n &lt;= 7) <br />\0nn    十进制数 0nn (0 &lt;= n &lt;= 7) <br />\0mnn   十进制数 0mnn (0 &lt;= m &lt;= 3, 0 &lt;= n &lt;= 7) <br />\xhh    十六进制数 0xhh <br />\uhhhh  十六进制数 0xhhhh <br />\t  制表符 ('\u0009') <br />\n  换行符 ('\u000A') <br />\r  回车符 ('\u000D') <br />\f  The form-feed character ('\u000C') <br />\a  The alert (bell) character ('\u0007') <br />\e  esc符号 ('\u001B') <br />\cx     x 对应的控制符<br />  <br />字符类<br />[abc]       a, b, 或 c (简单字符串) <br />[^abc]      除了 a, b, 或 c 之外的任意字符(否定) <br />[a-zA-Z]    从a 到 z 或 从A 到 Z（包括a,z,A,Z）(范围) <br />[a-d[m-p]]  从a 到 d, 或 从m 到 p: [a-dm-p] (并集) <br />[a-z&amp;&amp;[def]]    d, e, 或 f (交集) <br />[a-z&amp;&amp;[^bc]]    从a 到 z, 但 b 和 c 除外: [ad-z] (子集) <br />[a-z&amp;&amp;[^m-p]]   从a 到 z, 不包括从 m 到 p: [a-lq-z](子集) <br />  <br />预定义字符序列 <br />.   任意字符 (也可能不包括行结束符) <br />\d  数字: [0-9] <br />\D  非数字: [^0-9] <br />\s  空字符: [ \t\n\x0B\f\r] <br />\S  非空字符: [^\s] <br />\w  单字字符: [a-zA-Z_0-9] <br />\W  非单字字符: [^\w] <br />  <br />POSIX 字符类 (US-ASCII only) <br />\p{Lower}   小写字母字符: [a-z] <br />\p{Upper}   大写字母字符:[A-Z] <br />\p{ASCII}   所有 ASCII:[\x00-\x7F] <br />\p{Alpha}   单个字母字符:[\p{Lower}\p{Upper}] <br />\p{Digit}   十进制数: [0-9] <br />\p{Alnum}   单个字符:[\p{Alpha}\p{Digit}] <br />\p{Punct}   标点符号: 包括 !"#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~ <br />\p{Graph}   可视字符: [\p{Alnum}\p{Punct}] <br />\p{Print}   可打印字符: [\p{Graph}] <br />\p{Blank}   空格或制表符: [ \t] <br />\p{Cntrl}   控制字符: [\x00-\x1F\x7F] <br />\p{XDigit}  十六进制数: [0-9a-fA-F] <br />\p{Space}   空字符: [ \t\n\x0B\f\r] <br />  <br />Unicode 字符类<br />\p{InGreek}     希腊语种的字符 (simple block) <br />\p{Lu}      大写字母 (simple category) <br />\p{Sc}      货币符号 <br />\P{InGreek}     除希腊语种字符外的任意字符 (negation) <br />[\p{L}&amp;&amp;[^\p{Lu}]]  除大写字母外的任意字符 (subtraction) <br />  <br />边界匹配器 <br />^   一行的开始<br />$   一行的结束 <br />\b  单词边界 <br />\B  非单词边界<br />\A  输入的开始<br />\G  当前匹配的结束 <br />\Z  The end of the input but for the final terminator, if any <br />\z  输入的结束 <br />  <br />Greedy quantifiers <br />贪婪匹配量词（Greedy quantifiers ）（不知道翻译的对不对）<br />X?          X不出现或出现一次 <br />X*          X不出现或出现多次 <br />X+          X至少出现一次 <br />X{n}        X出现n次 <br />X{n,}       X至少出现n次 <br />X{n,m}      X至少出现n次，但不会超过m次<br />  <br />Reluctant quantifiers <br />X??         X, 不出现或出现一次<br />X*?         X, 不出现或出现多次 <br />X+?         X, 至少出现一次 <br />X{n}?       X, 出现n次 <br />X{n,}?      X, 至少出现n次  <br />X{n,m}?     X, 至少出现n次，但不会超过m次 <br />  <br />Possessive quantifiers <br />X?+     X, 不出现或出现一次<br />X*+         X, 不出现或出现多次 <br />X++         X, 至少出现一次 <br />X{n}+       X, 出现n次 <br />X{n,}+      X, 至少出现n次  <br />X{n,m}+     X, 至少出现n次，但不会超过m次 <br />  <br />逻辑运算符<br />XY  Y跟在X后面<br />X|Y     X 或 Y <br />(X)     X, as a capturing group <br />  <br />反向引用<br />\n  Whatever the nth capturing group matched <br />  <br />Quotation <br />\   引用后面的字符 <br />\Q  引用所有的字符直到 \E 出现<br />\E  结束以 \Q 开始的引用<br />  <br />Special constructs (non-capturing) <br />(?:X)           X, as a non-capturing group <br />(?idmsux-idmsux)    匹配标志开关 <br />(?idmsux-idmsux:X)      X, as a non-capturing group with the given flags on <br />- off <br />(?=X)           X, via zero-width positive lookahead <br />(?!X)           X, via zero-width negative lookahead <br />(?&lt;=X)          X, via zero-width positive lookbehind <br />(?&lt;!X)          X, via zero-width negative lookbehind <br />(?&gt;X)           X, as an independent, non-capturing group <br /><br />Backslashes, escapes, and quoting <br /><br />反斜杠字符('\')用来转义，就像上面的表中定义的那样，如果不这样做的话可能会产生<br />歧义。因此，表达式\\匹配<br />单个反斜杠，表达式\{匹配单个左花括号。<br />如果把反斜杠放在没有定义转移构造的任何字母符号前面都会发生错误，这些将被保留<br />到以后的正则表达式中扩展。反斜杠可以放在任何<br />非字母符号前面，即使它没有定义转义构造也不会发生错误。<br />在java语言规范中指出，在java代码中自符串中的反斜杠是必要的，不管用于Unicode转<br />义，还是用于普通的字符转义。因此，<br />为了保持正则表达式的完整性，在java字符串中要写两个反斜杠。例如，在正则表达式<br />中字符'\b'代表退格，'\\b'则代表单词边界。'\(hello\)'是无效的，并且会产生编译<br />时错误，你必须用<br />'\\(hello\\)'来匹配(hello)。<br /><br />Character Classes <br /><br />字符类可以出现在其他字符类内部，并且可以由并操作符和与操作符(&amp;&amp;)组成。并集操<br />作结果是，其中的任意字符，肯定在至少其中操作数中至少出现过一次。<br />交集的结果包括各个操作数中同时出现的任意字符。<br /><br />字符类操作符的优先级如下：（从高到低）<br />1     文字转义      \x <br />2     集合      [...] <br />3     范围      a-z <br />4     并集      [a-e][i-u] <br />5     交集      [a-z&amp;&amp;[aeiou]] <br /><br />请注意各个字符类的有效字符集。例如，在字符类中，正则表达式.失去了它的特别含义<br />，而-变成了元字符的范围指示。<br /><br />Line terminators <br /><br />行结束符是一个或两个字符序列，用来标识输入字符序列的一行的结束。下列都被认为<br />是行结束符：<br /><br />换行符      ('\n'), <br />回车换行符  ("\r\n"), <br />回车符      ('\r'), <br />下一行      ('\u0085'), <br />行分隔符    ('\u2028'), 或<br />段分隔符    ('\u2029). <br /><br />如果激活了 UNIX_LINES 模式，唯一的行结束符就是换行符。<br />除非你指定了 DOTALL 标志，否则正则表达式.匹配任何字符，只有行结束符除外。<br />确省情况时，在整个输入队列中，正则表达式^和$忽略行结束符，只匹配开始和结束。<br />如果激活了 MULTILINE 模式，则^匹配输入的开始和所有行结束符之后，除了整个输入<br />的结束。<br />在MULTILINE 模式下，$匹配所有行结束符之前，和整个输入的结束。<br /><br />Groups and capturing <br /><br />分组捕获通过从左到右的顺序，根据括号的数量类排序。例如，在表达式((A)(B(C)))中<br />，有四个组：<br />1     ((A)(B(C))) <br />2     (A) <br />3     (B(C)) <br />4     (C) <br /><br />0组代表整个表达式。<br />分组捕获之所以如此命名，是因为在匹配过程中，输入序列的每一个与分组匹配的子序<br />列都会被保存起来。通过向后引用，被捕获的子序列可以在后面的表达式中被再次使用<br />。<br />而且，在匹配操作结束以后还可以通过匹配器重新找到。<br />与一个分组关联的被捕获到的输入通常是被保存的最近与这个分组相匹配的队列的子队<br />列。如果一个分组被第二次求值，即使失败，它的上一次被捕获的值也会被保存起来。<br />例如，<br />表达式(a(b)?)+匹配"aba"，"b"设为子分组。在开始匹配的时候，以前被捕获的输入都<br />将被清除。<br />以(?开始的分组是完全的，无需捕获的分组不会捕获任何文本，也不会计算分组总数。<br /><br />Unicode support <br /><br /><a href="http://www.unicode.org/unicode/reports/tr18">Unicode Technical Report #18: Unicode Regular Expression Guidelines</a>通过轻微的语法改变实现了更深层次的支持。<br />在java代码中，像\u2014 这样的转义序列，java语言规范中<a href="http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#100850">？3.3</a>提供了处理方法<br />。<br />为了便于使用从文件或键盘读取的unicode转义字符，正则表达式解析器也直接实现了这<br />种转移。因此，字符串"\u2014"与"\\u2014"虽然不相等，但是编译进同一种模式，可以<br />匹配<br />十六进制数0x2014。<br /><br />在Perl中，unicode块和分类被写入\p,\P。如果输入有prop属性，\p{prop}将会匹配，<br />而\P{prop}将不会匹配。块通过前缀In指定，作为在nMongolian之中。<br />分类通过任意的前缀Is指定： \p{L} 和 \p{IsL} 都引用 Unicode 字母。块和分类可以<br />被使用在字符类的内部或外部。<br /><br /><a href="http://www.unicode.org/unicode/standard/s">The Unicode Standard, Version 3.0</a>指出了支持的块和分类。块的名字在第14章和 Unicode Character <br />Database中的 Blocks-3.txt 文件定义，<br />但空格被剔除了。例如Basic Latin"变成了  "BasicLatin"。分类的名字被定义在88页<br />，表4-5。<br /><br />Comparison to Perl 5 <br /><br />Pattern类不支持的Perl构造：<br />条件构造    (?{X}) 和 (?(condition)X|Y), <br /><br />嵌入代码构造    (?{code}) 和 (??{code}),<br /><br />嵌入注释语法    (?#comment), 和 <br /><br />操作预处理   \l \u, \L, and \U.<br /><br />Perl不支持的Pattern类构造：<br />所有权量词，它贪婪匹配任意多。<br />字符类交集和并集。<br /><br />Notable differences from Perl: <br />下面的对我无关紧要，就不翻译了。 </p><p> </p><p>第一次翻译东西，有很多都不懂，明明心里知道，可就是不知道该怎么写，我知道有很多错误，希望各位大侠多多指正，多谢！<br /></p></span>
<img src ="http://www.blogjava.net/junky/aggbug/95133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2007-01-21 15:05 <a href="http://www.blogjava.net/junky/archive/2007/01/21/95133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数字格式化输出NumberFormat </title><link>http://www.blogjava.net/junky/archive/2006/12/27/90220.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 27 Dec 2006 01:43:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/12/27/90220.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/90220.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/12/27/90220.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/90220.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/90220.html</trackback:ping><description><![CDATA[格式化输出NumberFormat<br /><br />相关内容：Local, DataFormat, MessageFormat, SimpleDateFormat, Format<br /><br />---------------------------------------------------------------<br />java.text.NumberFormat类有三个方法可以产生下列数据的标准格式化器：<br />数字<br />货币<br />百分数<br /><br />---------------------------------------------------------------<br />创建格式化器(默认地区Local格式)：<br />NumberFormat.getNumberInstance();<br />NumberFormat.getCurrencyInstance();<br />NumberFormat.getPercentInstance();<br /><br />---------------------------------------------------------------<br />例题：<br />double dbl=10000.0/3;<br />NumberFormat formatter=NumberFormat.getNumberInstance();<br />String s=formatter.format(x);<br />System.out.println(s);<br /><br />---------------------------------------------------------------<br />设定整数或小数部分所显示的最少和最多位数，可以使用NumberFormat类<br />的方法：<br />setMinimumIntegerDigits(int)<br />setMinimumFractionDigits(int)<br />setMaximumIntegerDigits(int)<br />setMaximumFractionDigits(int)<br /><br />设定小数部分的最多位很有用处。如果小数部分丢失的第一位数字大于等于5，<br />那么显示的最后一位会增1（四舍五入）。如果要显示尾随的零，可以把小数部分的最少位等于最多位。<br />如果不想显示，可以把小数部分的最少位设定为0或不设定。<br /><br />指定最多位整数相当危险，显示值将会被截断，产生一个错误的值。<br /><br />---------------------------------------------------------------<br />测试例题：<br /><br />文件名TestNumberFormat.java<br />--------------------------------------------------------<br />import java.text.NumberFormat;<br /><br />public class TestNumberFormat<br />{<br />    public static void main(String[] args) {<br /><br />            NumberFormat nFormat=NumberFormat.getNumberInstance();<br />            nFormat.setMinimumIntegerDigits(3);//设置整数部分至少为3位<br />            nFormat.setMaximumFractionDigits(5);//设置小数点后面尾数为5<br />        System.out.println("Format Out 3.2128345="+nFormat.format(3.2128345));<br /><br />            NumberFormat cFormat=NumberFormat.getCurrencyInstance();<br />            cFormat.setMaximumFractionDigits(3);<br />        System.out.println("Format Out 321283.47656="+cFormat.format(321283.47656));<br /><br />            NumberFormat pFormat=NumberFormat.getPercentInstance();<br />            pFormat.setMaximumFractionDigits(4);<br />        System.out.println("Format Out 3.2128345="+pFormat.format(3.2128345));<br /><br />        System.out.println("Format Out null="+nFormat.format(null));//参数是null,出现异常<br />        //Throws  IllegalArgumentException<br />    }<br />}<br /><br />//================= 运行结果如下 =======================<br />Format Out 3.2128345=003.21283<br />Format Out 321283.47656=￥321,283.477<br />Format Out 3.2128345=321.2834%<br />Exception in thread "main" java.lang <img src ="http://www.blogjava.net/junky/aggbug/90220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-12-27 09:43 <a href="http://www.blogjava.net/junky/archive/2006/12/27/90220.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对java 5除generic外的new features的总结 </title><link>http://www.blogjava.net/junky/archive/2006/12/27/90216.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Wed, 27 Dec 2006 01:36:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/12/27/90216.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/90216.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/12/27/90216.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/90216.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/90216.html</trackback:ping><description><![CDATA[
		<h2 style="MARGIN: 13pt 0cm">
				<span lang="EN-US">
						<font face="Arial">The for-each loop</font>
				</span>
		</h2>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span class="Code1">
						<span lang="EN-US">
								<font color="#003366">
										<font face="Verdana">for (type_name variable_name : [instance of Iterable&lt;T&gt;] or [array]) {}<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:p></o:p></font>
								</font>
						</span>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span>
				<span lang="EN-US">.net</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US">foreach</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不同的是，</span>
				<span lang="EN-US">Iterable</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的</span>
				<span lang="EN-US">type parameter</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或</span>
				<span lang="EN-US">array</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的</span>
				<span lang="EN-US">element type</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">必须是</span>
				<span lang="EN-US">for</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中使用的</span>
				<span lang="EN-US">type</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者其子类。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以下情况不适合使用</span>
				<span lang="EN-US">foreach</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">1.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当需要删除或者替换</span>
				<span lang="EN-US">current element</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo1; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">2.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当需要同时访问一个以上的</span>
				<span lang="EN-US">Iterable&lt;T&gt;</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者</span>
				<span lang="EN-US">array</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时。</span>
		</p>
		<h2 style="MARGIN: 13pt 0cm">
				<span lang="EN-US">
						<font face="Arial">Autoboxing</font>
				</span>
		</h2>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一般的代码经常会使用</span>
				<span lang="EN-US">boxing</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span>
				<span lang="EN-US">unboxing</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，如：</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">List list = new ArrayList();<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">int i = 0;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">list.add(new Integer(i)); // boxing<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">i = ((Integer) list.get(0)).intValue(); // unboxing<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">采用了</span>
				<span lang="EN-US">autoboxing</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之后，</span>
				<span lang="EN-US">java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">能够自动在</span>
				<span lang="EN-US">primitive type</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">它相应的</span>
				<span lang="EN-US">wrapper</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之间进行转换。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">// autoboxing<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">list.add(i);<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">i = list.get(0);<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以</span>
				<span lang="EN-US">Integer</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">为例，以下几点是需要注意的：</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo2; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">1.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当试图将值为</span>
				<span lang="EN-US">null</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</span>
				<span lang="EN-US">Integer</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">转为</span>
				<span lang="EN-US">int</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">时，会有</span>
				<span lang="EN-US">NullPointerException</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">int i = (Integer) null;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo2; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">2.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于</span>
				<span lang="EN-US">==</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">操作符，当它作用在</span>
				<span lang="EN-US">int</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上时是做值的比较，作用于</span>
				<span lang="EN-US">Integer</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">上时是做</span>
				<span lang="EN-US">reference</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的比较。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">int i1 = 0;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">Integer i2 = new Integer(0);<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">i1 == i2; // return true<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">i2 == i1; // return true<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">(Integer) i1 == i2; // return false<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo2; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">3.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果频繁使用</span>
				<span lang="EN-US">autoboxing</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将不利于代码的运行效率。</span>
		</p>
		<h2 style="MARGIN: 13pt 0cm">
				<span lang="EN-US">
						<font face="Arial">Enums</font>
				</span>
		</h2>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">public enum Test { // 1<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">A, B(1), C { public boolean test1() { return true; } } /* 5 */ ; // 2<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">private int i = 0;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">Test() {} // 3<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">private Test(int i) { this.i = i; } // 3<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">public boolean test1() { return false; } // 5<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">public boolean test2(Test test) { return test != A &amp;&amp; test !=B; } // 6<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">// 7<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">public boolean test3() {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">
						<span style="mso-tab-count: 1">      </span>switch (this) {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">case A: return false;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">case B: return false;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 63pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">default: return true;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US">Enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟一般的类有很多相似之处，它们都能够实现多个接口，能够定义方法、类变量，除了这些相似点之外，</span>
				<span lang="EN-US">enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有如下的特性：</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">1.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">必须使用</span>
				<span lang="EN-US">enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字来定义，不能用</span>
				<span lang="EN-US">extends</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">指定父类，假如</span>
				<span lang="EN-US">enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的名字为</span>
				<span lang="EN-US">Test</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，则它自动继承</span>
				<span lang="EN-US">Enum&lt;Test&gt;</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。与此同时，</span>
				<span lang="EN-US">enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">还自动实现</span>
				<span lang="EN-US">Serializable</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span>
				<span lang="EN-US">comparable</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口，并且自动重载了部分</span>
				<span lang="EN-US">Object</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的方法。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">2.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所有的可用</span>
				<span lang="EN-US">enum constant</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">必须放在第一行，用逗号格开，以分号结束（如果后面没有其他的代码，则分号可以省略）。通过专门设计，使得</span>
				<span lang="EN-US">Serial form</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以支持后续新增的</span>
				<span lang="EN-US">enum constant</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">3.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以定义若干不同的构造函数，构造函数只能用</span>
				<span lang="EN-US">private</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">修饰符（可以省略掉</span>
				<span lang="EN-US">private</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），当构造函数需要输入参数时，</span>
				<span lang="EN-US">enum constant</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的定义中必须提供这些参数的值。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">4.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">自动增加了</span>
				<span lang="EN-US">values()</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US">valueOf</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（</span>
				<span lang="EN-US">Class&lt;T&gt;, String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）、</span>
				<span lang="EN-US">valueOf(String)</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">三个静态方法。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">5.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以为</span>
				<span lang="EN-US">enum constant</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定义</span>
				<span lang="EN-US">constant-specific</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">6.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在代码中可以引用前面所定义的类型。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">7.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">由于</span>
				<span lang="EN-US">switch</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以应用于</span>
				<span lang="EN-US">int</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span>
				<span lang="EN-US">enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类型，在代码中可以使用</span>
				<span lang="EN-US">”switch (this) {…}”</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语句。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt; mso-list: l2 level1 lfo3; tab-stops: list 39.0pt">
				<span lang="EN-US" style="mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">8.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span>
				<span lang="EN-US">java.util</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中有专为</span>
				<span lang="EN-US">enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计的高效率的</span>
				<span lang="EN-US">EnumSet</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span>
				<span lang="EN-US">EnumMap</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，其中</span>
				<span lang="EN-US">EnumSet</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">提供对方法以使</span>
				<span lang="EN-US">enum</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">支持位与（</span>
				<span lang="EN-US">bit flags</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）操作。</span>
		</p>
		<h2 style="MARGIN: 13pt 0cm">
				<span lang="EN-US">
						<font face="Arial">Varargs</font>
				</span>
		</h2>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在方法的参数列表上，如果类型后面加上三个点，则表示该参数可能作为数组或者多个参数传入，如：</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">public void test(int… arguments) {}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">…<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">test(1);<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">test(1, 2, 3);<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">test(new int[0]);<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟</span>
				<span lang="EN-US">.net</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类似的，</span>
				<span lang="EN-US">varargs</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">必须作为方法的最后一个参数。如果对使用</span>
				<span lang="EN-US">varargs</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的方法进行重载，则在调用该方法时，有可能</span>
				<span lang="EN-US">compiler</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">无法识别代码究竟调用的是哪个方法，此时会有编译错误。</span>
		</p>
		<h2 style="MARGIN: 13pt 0cm">
				<span lang="EN-US">
						<font face="Arial">Static Import</font>
				</span>
		</h2>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US">Static import</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">用来</span>
				<span lang="EN-US">import</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类中的静态变量或静态方法，使用了</span>
				<span lang="EN-US">static import</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">之后，这些使用这些静态变量和静态方法时将不需要使用类名。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">import static java.lang.Math.PI;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">import static java.lang.Math.*;<o:p></o:p></span>
		</p>
		<h2 style="MARGIN: 13pt 0cm">
				<span lang="EN-US">
						<font face="Arial">Annotations</font>
				</span>
		</h2>
		<h3 style="MARGIN: 13pt 0cm">
				<font size="3">
						<span lang="EN-US">Annotation</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的定义</span>
				</font>
		</h3>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">public @interface Test {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">
						<span style="mso-tab-count: 1">      </span>int value();<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">
						<span style="mso-tab-count: 1">      </span>String name() default “test”;<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">定义</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用</span>
				<span lang="EN-US">@interface</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字。</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">能使用的类型为</span>
				<span lang="EN-US">primitive</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US">String</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US">Class</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US">enums</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以及以以上类型为</span>
				<span lang="EN-US">element type</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的数组。使用</span>
				<span lang="EN-US">default</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字能够设定默认值，默认值必须是</span>
				<span lang="EN-US">compile time constants</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US">Annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的使用的语法跟</span>
				<span lang="EN-US">java doc</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的语法相似，为了区分这两者，</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的命名不能使用已有的</span>
				<span lang="EN-US">java doc</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中所用的名字。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在</span>
				<span lang="EN-US">java.lang.annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中存在若干</span>
				<span lang="EN-US">mata-annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，用于</span>
				<span lang="EN-US">annotate</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">其他的</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
		</p>
		<h3 style="MARGIN: 13pt 0cm">
				<font size="3">
						<span lang="EN-US">Annotation</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的使用</span>
				</font>
		</h3>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">首先，必须</span>
				<span lang="EN-US">import annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所在的包，</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以放在在任何</span>
				<span lang="EN-US">static</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US">public</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</span>
				<span lang="EN-US">final</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字可以使用的地方，建议把</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">放在最前面。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">@Test(value=0)<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">public class A {<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">@Test(Value=0, name=”abc”) public void test(@Test(0) Object o) {}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="COLOR: #003366; FONT-FAMILY: Verdana">}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中各个变量的赋值作为</span>
				<span lang="EN-US">name value pair</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">被放在括号内，同时用逗号格开，如果</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中没有任何变量或者所有变量都有默认值，则可以省去赋值部分（连同括号），如果</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中有一个名字为</span>
				<span lang="EN-US">value</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的变量，同时没有其他的变量或者其他的变量都有默认值，则可以只提供值而省略</span>
				<span lang="EN-US">element name</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和等号。</span>
		</p>
		<h3 style="MARGIN: 13pt 0cm">
				<font size="3">
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">读出</span>
						<span lang="EN-US">annotation</span>
						<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的包含的信息</span>
				</font>
		</h3>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过</span>
				<span lang="EN-US">reflection</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以读出</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所包含的信息，有一部分</span>
				<span lang="EN-US">annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过使用</span>
				<span lang="EN-US">meta-annotation</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">被声明为</span>
				<span lang="EN-US">runtime</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不可知，这时通过分析</span>
				<span lang="EN-US">byte code</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">才能得到其信息。</span>
		</p>
<img src ="http://www.blogjava.net/junky/aggbug/90216.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-12-27 09:36 <a href="http://www.blogjava.net/junky/archive/2006/12/27/90216.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何打jar包(转)</title><link>http://www.blogjava.net/junky/archive/2006/12/15/87953.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Fri, 15 Dec 2006 07:23:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/12/15/87953.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/87953.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/12/15/87953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/87953.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/87953.html</trackback:ping><description><![CDATA[
		<p>
				<span>分类:<a href="http://limoo.bokee.com/cat.10035193.html"><font color="#fecd2a">java</font></a></span>
		</p>
		<div class="entry-body">
				<p>jar 应用 先打开命令提示符(win2000或在运行筐里执行cmd命令，win98为DOS提示符)，输入jar -help,然后回车(如果你盘上已经有了jdk1.1或以上版本)，看到什么：<br />用法：jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目录] 文件名 ... </p>
				<p>选项：<br />-c 创建新的存档 <br />-t 列出存档内容的列表 <br />-x 展开存档中的命名的（或所有的〕文件 <br />-u 更新已存在的存档 <br />-v 生成详细输出到标准输出上 <br />-f 指定存档文件名 <br />-m 包含来自标明文件的标明信息 <br />-0 只存储方式；未用ZIP压缩格式 <br />-M 不产生所有项的清单（manifest〕文件 <br />-i 为指定的jar文件产生索引信息 <br />-C 改变到指定的目录，并且包含下列文件： </p>
				<p>如果一个<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(5);" onmouseover="kwE(event,5);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)文件名','_blank');" onmouseout="kwL(event);" target="_blank">文件名</a></nobr>是一个目录，它将被递归处理。<br />清单（manifest〕文件名和存档文件名都需要被指定，按'm' 和 'f'标志指定的相同顺序. </p>
				<p>示例1：将两个class文件存档到一个名为 'classes.jar' 的存档文件中： <br />jar cvf classes.jar Foo.class Bar.class </p>
				<p>示例2：用一个存在的<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(6);" onmouseover="kwE(event,6);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)清单','_blank');" onmouseout="kwL(event);" target="_blank">清单</a></nobr>（manifest）文件 'mymanifest' 将 foo/ 目录下的所有文件<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(2);" onmouseover="kwE(event,2);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)存档','_blank');" onmouseout="kwL(event);" target="_blank">存档</a></nobr>到一个名为 'classes.jar' 的存档文件中： <br />jar cvfm classes.jar mymanifest -C foo/ . </p>
				<p>来个小例子试试看： <br />我们只有一个HelloWorld，如下：<br />public class HelloWorld{ <br />    public static void main(String[] args){ <br />        System.out.println("Hi, Hello World!"); <br />    } <br />}<br />我将这个java文件存到C盘跟目录下，ok，接下来， </p>
				<p>在先前打开的命令提示符下(跳转到C盘提示符下)，我们输入javac HelloWorld.java，然后继续输入：jar cvf hello.jar HelloWorld.class，回车后去你的C盘看看，多了什么，没错 hello.jar 。 </p>
				<p>基本的步骤我们现在都知道了，你可以自己去尝试一下随着jar后面的参数的不同，结果有什么变化。 </p>
				<p>紧接着我们看看如何运行我们的jar包。 </p>
				<p>在进入正题之前，你要先打开我们刚刚做好的jar包看看，多了什么呢，META-INF目录？再看看里面是什么，还有一个MANIFEST.MF文件是不是？用文本编辑器(我这里是UltraEdit)打开它看看： <br />Manifest-Version: 1.0 <br />Created-By: 1.4.2 (Sun Microsystems Inc.) </p>
				<p>就是这样。这里我们对它进行修改，加一句：Main-Class: HelloWorld (在第三行)。这个就是我们之前写的那个类，也就是我们的入口类。也即， <br />Manifest-Version: 1.0 <br />Created-By: 1.4.2 (Sun Microsystems Inc.) <br />Main-Class: HelloWorld </p>
				<p>接下来，我们在命令提示符里执行： <br />jar umf MANIFEST.MF app.jar </p>
				<p>这样我们使用了我们自己的MANIFEST.MF文件对原来默认的进行了更新。你不妨可以再进去看看是不是添上了Main-Class: HelloWorld这一句。 </p>
				<p>Ok，这个最后的一步了，来验证我们做的一切，在命令提示符中输入： <br />java -jar hello.jar(执行) </p>
				<p>出现了什么，――Hi, Hello World! <br />我们再来看看jar文件在tomcat中发布，注意：在tomcat中我们就不能再用jar这种格式，而改war格式，它是专门用于web应用的，其实整个过程下来基本上和jar是类似的： </p>
				<p>先准备我们要打包的资源。 </p>
				<p>找到存放tomcat的webapps目录，进到其中，新建一个文件夹，这里命名为hello，再进去新建WEB-INF文件夹，再进去新建 classes文件夹，此时我们也将我们唯一的servlet，HelloWorld.java放到这里，在与classes目录同级下建立一文件 web.xml。Ok，目前我们初步建立了一个简单的web应用。 </p>
				<p>在命令<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(3);" onmouseover="kwE(event,3);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)提示符','_blank');" onmouseout="kwL(event);" target="_blank">提示符</a></nobr>下进到先前创制的hello目录下，执行 jar cvf hello.war * ，我们便得到hello.war。将它拷贝至webapps目录下，ok，来看最后一步，打开tomcat的目录conf中的server.xml，加入：<br />reloadable="true"/&gt; <br />大功告成！运行它，启动tomcat，后在浏览器中输入<a href="http://localhost:8080/hello/HelloWorld"><font color="#fecd2a">http://localhost:8080/hello/HelloWorld</font></a>，有了吗？ </p>
				<p>好了，就这么多，希望对你有点帮助。</p>
				<p>补充： <br />############ </p>
				<p>jar基本操作： </p>
				<p>############ </p>
				<p>1. 创建jar文件 <br />jar cf jar-file input-file(s) <br />c---want to Create a JAR file. <br />f---want the output to go to a file rather than to stdout. <br />eg: 1)jar cf myjar.jar query_maintain_insert.htm <br />2)jar cvf myjar.jar query_maintain_insert.htm <br />v---Produces verbose(详细的) output. <br />3)jar cvf myjar.jar query_maintain_insert.htm mydirectory <br />4)jar cv0f myjar.jar query_maintain_insert.htm mydirectory <br />0---don't want the JAR file to be compressed. <br />5)jar cmf MANIFEST.MF myjar.jar yahh.txt <br />m---Used to include manifest information from an existing manifest file. <br />6)jar cMf MANIFEST.MF myjar.jar yahh.txt <br />M---the default manifest file should not be produced. <br />7)jar cvf myjar.jar * <br />*---create all contents in current directory. <br />2. 察看jar文件 <br />jar tf jar-file <br />t---want to view the Table of contents of the JAR file. <br />eg: 1)jar vft yahh.jar <br />v---Produces verbose(详细的) output. <br />3. 提取jar文件 <br />jar xf jar-file [archived-file(s)] <br />x---want to extract files from the JAR archive. <br />eg: 1)jar xf yahh.jar yahh.txt(仅提取文件yahh.txt) <br />2)jar xf yahh.jar alex/yahhalex.txt(仅提取目录alex下的文件yahhalex.txt) <br />3)jar xf yahh.jar(提取该jar包中的所有文件或目录) <br />4. 修改Manifest文件 <br />jar cmf manifest-addition jar-file input-file(s) <br />m---Used to include manifest information from an existing manifest file. <br />5. 更新jar文件<br />jar uf jar-file input-file(s) <br />u---want to update an existing JAR file. </p>
				<p>--&gt;生成exe:&lt;--</p>
				<p>
						<br />第一種：在jbuilder中：      <br />首先你要保证Run菜单--&gt;Run    Project能顺利运行      <br />然后Wizards菜单--&gt;Native    Executable    Builder      <br />选中Compress    the    contents    of    the    archive(产生jar文件的话)      <br />Next--&gt;Next--&gt;选中Always    include    all    classes    and    resources再Next--&gt;Next--&gt;Next      <br />选中Windows    GUI"exe"(产生EXE文件的话)--&gt;Finish      <br />再在项目的文件列表中的Native    Executable右击--&gt;Make就可以了      <br />   <br />第二種：在cmd    下生成jar文件      <br />abc.txt内容如下：      <br />Manifest-Version:    1.0          <br />Main-Class:    main-class-name(回車)      <br />在cmd下：          <br />javac    *.java      <br />jar    cvfm    abc.jar    abc.txt    *.class      <br />示例——生成能通过鼠标双击就执行的.jar文件      <br />一、            编写Java源程序Test.java如下：      </p>
				<p>//    Test.java      <br />import    javax.swing.*;      <br />/**      <br />*    @(#)    Test.java      <br />*    Copyleft    (c)    2002    RatKing      <br />*    @author    &lt;a    href="<a href="mailto:ratking@ynet.com&quot;&gt;RatKing&lt;/a"><font color="#fecd2a">ratking@ynet.com"&gt;RatKing&lt;/a</font></a>&gt;      <br />*    @version    0.1,    2002-11-7      <br />*    描述：一个测试用的Java    Application      <br />*/      <br />public    class    Test    extends    JFrame    {      <br />             public    Test(String    title)    {      <br />                             super(title);      <br />                             this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      <br />                             this.getContentPane().add(new    JLabel("测试！",    JLabel.CENTER),    SwingConstants.CENTER);      <br />                             this.pack();      <br />             }      <br />   <br />             public    static    void    main(String[]    args)    {      <br />                             try    {      <br />                                             //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());      <br />                                             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());      <br />                             }    catch(Exception    e)    {      <br />                                             e.printStackTrace();      <br />                             }      <br />                             Test    t    =    new    Test("Test    -    测试");      <br />                             t.setVisible(true);      <br />             }      <br />}      <br />   </p>
				<p>二、编译Test.java为Test.class（当然假设你事先已经设置好了JDK的环境变量PATH和CLASSPATH）      <br />在命令行执行编译命令：      <br />javac    Test.java      <br />   <br />三、用文本编辑器（比如记事本/UltraEdit等    -    甚至用ECHO命令加管道“&gt;&gt;”）编写如下manifest文件，并保存为abc.txt      <br />   <br />Manifest-Version:    1.0      <br />Main-Class:    Test      <br />   <br />【注意】文件abc.txt内必须是3行文本：      <br />第一行的内容依次是：“Manifest”、英文减号、“Version”、英文冒号、英文空格、数字“1”、英文句号、数字“0”      <br />第二行的英文冒号与Test之间必须要有一个英文空格！！！      <br />第三行是一个空行，也就是说，你要在Test之后键入一个回车，然后才可以存盘退出！！！      <br />如果冒号后面没有空格，可以生成jar文件但不能执行；如果Test后没有回车符，则生成jar文件时会报错。      <br />   <br />四、将Test.class打包成.jar文件，并使用abc.txt指明哪一个是带有public    static    void    main()的“主函数”      <br />在命令行执行编译命令：      <br />jar    cvfm    Test.jar    abc.txt    *.class      <br />   <br />你可以使用WinZip之类的解压软件看一看刚刚生成的Test.jar文件里到底有什么。      <br />   <br />五、用鼠标双击Test.jar的图标，应该可以看到Test执行后的窗口。      <br />   <br />〖说明〗如果你正确地安装了Java运行环境（JRE），那么.jar的图标应该是象一页纸并有一个A的形状，就如同写字板的图标。      <br />如果你的.jar文件默认的打开关联不对，可以重新设置：      <br />我的电脑-&gt;查看(Win9x)或工具(Win2k)-&gt;文件夹选项-&gt;文件类型-&gt;选择JAR文件-&gt;编辑该类型文件的属性-&gt;操作栏填入[    open    ](不填引号和中括号[])，并在“执行操作的应用程序”栏填入[    "C:\Program    Files\Java\j2re1.4.1\bin\javaw.exe"    -jar    "%1"    %*    ](填两对英文引号，不填[])      <br />并按“确定”、“关闭”退出对.jar文件关联的编辑。      <br />（你的javaw.exe文件是不是位于C:\Program    Files\Java\j2re1.4.1\bin\路径下，视你自己电脑的情况而定）      </p>
				<p>
						<br />我这也是网上的贴子  <br />---------------------------------------------------------------  </p>
				<p>JB中生成.exe文件  <br />1、菜单中选择【Wizards】－【Native  Executable  Builder....】弹出对话框  <br />2、在弹出的对话框中第一步（Step  1  of  7）的【Name】输入一个名称，并取消【Always  create  archive  when  building  the  project】点击【Next】  <br />3、根据需要悬着需要的类，再选择【Include  class  dependencies】，点击【Next】  <br />4、根据需要悬着需要的库文件，再选择下面的4个单选,反复所有的需要的库，点击【Next】  <br />5、默认点击【Next】  <br />6、在（Step  5  of  7）的时候选择一个主类运行点击【Next】  <br />7、在（Step  6  of  7）的时候选择运行平台【Next】  <br />8、默认点击【Finish】，这时候在工程的目录窗口出现了一个在（Step  1  of  7）输入的【Name】目录  <br />9、右击这个目录，选择【Rebuild....】，Jbuilder就开始编译和创建执行文件或是Jar文件了  <br />10、等完成之后，该目录下右几个文件，一般是有至少一个jar文件，或是一个exe文件  <br />11、在Window打开工程所在的目录，就可以看到里面的有几个刚才编译的文件  <br />12、执行jar就是用java  -jar  ***.jar、执行exe直接双击  </p>
				<p>
						<br />---------------------------------------------------------------  </p>
				<p>1、不建议使用jb因为打包后，可执行文件的图标改不了且jb的可执行文件实际上是可执行的jar文件，可以将其exe扩展名改为jar一样可执行。  <br />2、还是使用jsmooth较好，首先编写menifest文件目的指明main类，使用jar命令打包成可执行jar文件，让后使用开源的jsmooth做成exe。 </p>
				<p>来源    <a href="http://www.programfan.com/club/showtxt.asp?id=84070"><font color="#fecd2a">http://www.programfan.com/club/showtxt.asp?id=84070</font></a></p>
		</div>
<img src ="http://www.blogjava.net/junky/aggbug/87953.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-12-15 15:23 <a href="http://www.blogjava.net/junky/archive/2006/12/15/87953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java读取properties文件</title><link>http://www.blogjava.net/junky/archive/2006/12/10/86709.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 10 Dec 2006 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/12/10/86709.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/86709.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/12/10/86709.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/86709.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/86709.html</trackback:ping><description><![CDATA[
		<p>Java对properties配置文件的操作</p>
		<br />
		<p>/*<br /> * Created on 2005-1-4<br /> *<br /> * TODO To change the template for this generated file go to<br /> * Window - Preferences - Java - Code Style - Code Templates<br /> */<br />package com.yorsun;</p>
		<p>import java.io.File;<br />import java.io.FileInputStream;<br />import java.io.FileNotFoundException;<br />import java.io.FileOutputStream;<br />import java.io.IOException;<br />import java.util.Properties;</p>
		<p>import javax.servlet.ServletContext;<br />import javax.servlet.http.HttpServlet;</p>
		<p>/**<br /> * @author Administrator<br /> * <br /> * TODO To change the template for this generated type comment go to Window -<br /> * Preferences - Java - Code Style - Code Templates<br /> */<br />public class PropertiesUnit {<br /> private String filename;</p>
		<p> private Properties p;</p>
		<p> private FileInputStream in;</p>
		<p> private FileOutputStream out;</p>
		<p> public PropertiesUnit(String filename) {<br />  this.filename = filename;<br />  File file = new File(filename);<br />  try {<br />   in = new FileInputStream(file);<br />   p = new Properties();<br />   p.load(in);<br />   in.close();<br />  } catch (FileNotFoundException e) {<br />   // TODO Auto-generated catch block<br />   System.err.println("配置文件config.properties找不到！");<br />   e.printStackTrace();<br />  } catch (IOException e) {<br />   // TODO Auto-generated catch block<br />   System.err.println("读取配置文件config.properties错误！");<br />   e.printStackTrace();<br />  }<br /> }</p>
		<p> public static String getConfigFile(HttpServlet hs) {<br />  return getConfigFile(hs, "config.properties");<br /> }</p>
		<p> /**<br />  * @param hs<br />  * @param configFileName<br />  * @return configFile<br />  */<br /> private static String getConfigFile(HttpServlet hs, String configFileName) {<br />  String configFile = "";<br />  ServletContext sc = hs.getServletContext();<br />  configFile = sc.getRealPath("/" + configFileName);<br />  if (configFile == null || configFile.equals("")) {<br />   configFile = "/" + configFileName;<br />  }<br />  // TODO Auto-generated method stub<br />  return configFile;<br /> }</p>
		<p> public void list() {<br />  p.list(System.out);<br /> }</p>
		<p> public String getValue(String itemName) {<br />  return p.getProperty(itemName);<br /> }</p>
		<p> public String getValue(String itemName, String defaultValue) {<br />  return p.getProperty(itemName, defaultValue);<br /> }</p>
		<p> public void setValue(String itemName, String value) {<br />  p.setProperty(itemName, value);<br /> }</p>
		<p> public void saveFile(String filename, String description) throws Exception {<br />  try {<br />   File f = new File(filename);<br />   out = new FileOutputStream(f);<br />   p.store(out, description);<br />   out.close();<br />  } catch (IOException ex) {<br />   throw new Exception("无法保存指定的配置文件:" + filename);<br />  }<br /> }<br /> <br /> public void saveFile(String filename) throws Exception{<br />  saveFile(filename,"");<br /> }<br /> <br /> public void saveFile() throws Exception{<br />  if(filename.length()==0)<br />   throw new Exception("需指定保存的配置文件名");<br />  saveFile(filename);<br /> }<br /> <br /> public void deleteValue(String value){<br />  p.remove(value);<br /> }<br /> <br /> public static void main(String args[]){<br />  String file="/eclipse/workspace/NewsTest/WEB-INF/config.properties";<br />//  String file="D:\\eclipse\\workspace\\NewsTest\\WEB-INF\\config.properties";<br />  PropertiesUnit pu=new PropertiesUnit(file);<br />  pu.list();<br /> }</p>
		<p>}</p>
<img src ="http://www.blogjava.net/junky/aggbug/86709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-12-10 15:49 <a href="http://www.blogjava.net/junky/archive/2006/12/10/86709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用J2SE API读取Properties文件的六种方法</title><link>http://www.blogjava.net/junky/archive/2006/12/10/86708.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 10 Dec 2006 07:47:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/12/10/86708.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/86708.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/12/10/86708.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/86708.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/86708.html</trackback:ping><description><![CDATA[
		<p>使用J2SE API读取Properties文件的六种方法</p>
		<p>1。使用java.util.Properties类的load()方法<br />示例： InputStream in = lnew BufferedInputStream(new FileInputStream(name));<br />       Properties p = new Properties();<br />       p.load(in);</p>
		<p>2。使用java.util.ResourceBundle类的getBundle()方法<br />示例： ResourceBundle rb = ResourceBundle.getBundle(name, Locale.getDefault());</p>
		<p>3。使用java.util.PropertyResourceBundle类的构造函数<br />示例： InputStream in = new BufferedInputStream(new FileInputStream(name));<br />       ResourceBundle rb = new PropertyResourceBundle(in);</p>
		<p>4。使用class变量的getResourceAsStream()方法<br />示例： InputStream in = JProperties.class.getResourceAsStream(name);<br />       Properties p = new Properties();<br />       p.load(in);</p>
		<p>5。使用class.getClassLoader()所得到的java.lang.ClassLoader的getResourceAsStream()方法<br />示例： InputStream in = JProperties.class.getClassLoader().getResourceAsStream(name);<br />       Properties p = new Properties();<br />       p.load(in);</p>
		<p>6。使用java.lang.ClassLoader类的getSystemResourceAsStream()静态方法<br />示例： InputStream in = ClassLoader.getSystemResourceAsStream(name);<br />       Properties p = new Properties();<br />       p.load(in);</p>
		<p>补充</p>
		<p>Servlet中可以使用javax.servlet.ServletContext的getResourceAsStream()方法<br />示例：InputStream in = context.getResourceAsStream(path);<br />       Properties p = new Properties();<br />       p.load(in);</p>
		<p>
				<font color="#0000ff">完整的示例，可以参考附件文件<br />如何上传文件，谁知道请告诉以下。 只好把source都贴上来了<br />JProperties.java文件</font>
				<br />
				<br />
				<font color="#000880">/**<br />** This program is free software.<br />** <br />** You may redistribute it and/or modify it under the terms of the GNU<br />** General Public License as published by the Free Software Foundation.<br />** Version 2 of the license should be included with this distribution in<br />** the file LICENSE, as well as License.html. If the license is not<br />** included with this distribution, you may find a copy at the FSF web<br />** site at ´www.gnu.org´ or ´www.fsf.org´, or you may write to the<br />** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.<br />**<br />** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,<br />** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR<br />** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY<br />** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR<br />** REDISTRIBUTION OF THIS SOFTWARE. <br />**/</font>
		</p>
		<p>package com.kindani;</p>
		<p>//import javax.servlet.ServletContext;<br />import java.util.*;<br />import java.io.InputStream;<br />import java.io.IOException;<br />import java.io.BufferedInputStream;<br />import java.io.FileInputStream;</p>
		<p>
				<font color="#000880">/**<br /> * 使用J2SE API読取Properties文件的六種方法<br /> * User: SYNFORM<br /> * Date: 2005/07/12<br /> * Time: 18:40:55<br /> * To change this template use File | Settings | File Templates.<br /> */</font>
				<br />public class JProperties {</p>
		<p>    public final static int BY_PROPERTIES = 1;<br />    public final static int BY_RESOURCEBUNDLE = 2;<br />    public final static int BY_PROPERTYRESOURCEBUNDLE = 3;<br />    public final static int BY_CLASS = 4;<br />    public final static int BY_CLASSLOADER = 5;<br />    public final static int BY_SYSTEM_CLASSLOADER = 6;</p>
		<p>    public final static Properties loadProperties(final String name, final int type) throws IOException {<br />        Properties p = new Properties();<br />        InputStream in = null;<br />        if (type == BY_PROPERTIES) {<br />            in = new BufferedInputStream(new FileInputStream(name));<br />            assert (in != null);<br />            p.load(in);<br />        } else if (type == BY_RESOURCEBUNDLE) {<br />            ResourceBundle rb = ResourceBundle.getBundle(name, Locale.getDefault());<br />            assert (rb != null);<br />            p = new ResourceBundleAdapter(rb);<br />        } else if (type == BY_PROPERTYRESOURCEBUNDLE) {<br />            in = new BufferedInputStream(new FileInputStream(name));<br />            assert (in != null);<br />            ResourceBundle rb = new PropertyResourceBundle(in);<br />            p = new ResourceBundleAdapter(rb);<br />        } else if (type == BY_CLASS) {<br />            assert (JProperties.class.equals(new JProperties().getClass()));<br />            in = JProperties.class.getResourceAsStream(name);<br />            assert (in != null);<br />            p.load(in);<br />            //        return new JProperties().getClass().getResourceAsStream(name);<br />        } else if (type == BY_CLASSLOADER) {<br />            assert (JProperties.class.getClassLoader().equals(new JProperties().getClass().getClassLoader()));<br />            in = JProperties.class.getClassLoader().getResourceAsStream(name);<br />            assert (in != null);<br />            p.load(in);<br />            //         return new JProperties().getClass().getClassLoader().getResourceAsStream(name);<br />        } else if (type == BY_SYSTEM_CLASSLOADER) {<br />            in = ClassLoader.getSystemResourceAsStream(name);<br />            assert (in != null);<br />            p.load(in);<br />        }</p>
		<p>        if (in != null) {<br />            in.close();<br />        }<br />        return p;</p>
		<p>    }</p>
		<p>    // ---------------------------------------------- servlet used<br />/*<br />    public static Properties loadProperties(ServletContext context, String path) throws IOException {<br />        assert (context != null);<br />        InputStream in = context.getResourceAsStream(path);<br />        assert (in != null);<br />        Properties p = new Properties();<br />        p.load(in);<br />        in.close();<br />        return p;<br />    }<br />*/</p>
		<p>    // ---------------------------------------------- support class</p>
		<p>    /**<br />     * ResourceBundle Adapter class.<br />     */<br />    public static class ResourceBundleAdapter extends Properties {<br />        public ResourceBundleAdapter(ResourceBundle rb) {<br />            assert (rb instanceof java.util.PropertyResourceBundle);<br />            this.rb = rb;<br />            java.util.Enumeration e = rb.getKeys();<br />            while (e.hasMoreElements()) {<br />                Object o = e.nextElement();<br />                this.put(o, rb.getObject((String) o));<br />            }<br />        }</p>
		<p>        private ResourceBundle rb = null;</p>
		<p>        public ResourceBundle getBundle(String baseName) {<br />            return ResourceBundle.getBundle(baseName);<br />        }</p>
		<p>        public ResourceBundle getBundle(String baseName, Locale locale) {<br />            return ResourceBundle.getBundle(baseName, locale);<br />        }</p>
		<p>        public ResourceBundle getBundle(String baseName, Locale locale, ClassLoader loader) {<br />            return ResourceBundle.getBundle(baseName, locale, loader);<br />        }</p>
		<p>        public Enumeration&lt;String&gt; getKeys() {<br />            return rb.getKeys();<br />        }</p>
		<p>        public Locale getLocale() {<br />            return rb.getLocale();<br />        }</p>
		<p>        public Object getObject(String key) {<br />            return rb.getObject(key);<br />        }</p>
		<p>        public String getString(String key) {<br />            return rb.getString(key);<br />        }</p>
		<p>        public String[] getStringArray(String key) {<br />            return rb.getStringArray(key);<br />        }</p>
		<p>        protected Object handleGetObject(String key) {<br />            return ((PropertyResourceBundle) rb).handleGetObject(key);<br />        }</p>
		<p>    }</p>
		<p>}<br /><br /><br /><font color="#0000ff">JPropertiesTest.java文件</font><br /><br /><font color="#000880">/**<br />** This program is free software.<br />** <br />** You may redistribute it and/or modify it under the terms of the GNU<br />** General Public License as published by the Free Software Foundation.<br />** Version 2 of the license should be included with this distribution in<br />** the file LICENSE, as well as License.html. If the license is not<br />** included with this distribution, you may find a copy at the FSF web<br />** site at ´www.gnu.org´ or ´www.fsf.org´, or you may write to the<br />** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.<br />**<br />** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,<br />** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR<br />** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY<br />** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR<br />** REDISTRIBUTION OF THIS SOFTWARE. <br />**/<br /></font>package com.kindani.test;</p>
		<p>import junit.framework.*;<br />import com.kindani.JProperties;</p>
		<p>//import javax.servlet.ServletContext;<br />import java.util.Properties;</p>
		<p>public class JPropertiesTest extends TestCase {<br />    JProperties jProperties;<br />    String key = "helloworld.title";<br />    String value = "Hello World!";</p>
		<p>    public void testLoadProperties() throws Exception {<br />        String name = null;<br />        Properties p = new Properties();</p>
		<p>        name = "C:\\IDEAP\\Properties4Methods\\src\\com\\kindani\\test\\LocalStrings.properties";<br />        p = JProperties.loadProperties(name, JProperties.BY_PROPERTIES);<br />        assertEquals(value, p.getProperty(key));</p>
		<p>        name = "com.kindani.test.LocalStrings";<br />        p = JProperties.loadProperties(name,JProperties.BY_RESOURCEBUNDLE);<br />        assertEquals(value, p.getProperty(key));<br />        assertEquals(value,((JProperties.ResourceBundleAdapter)p).getString(key));</p>
		<p>        name = "C:\\IDEAP\\Properties4Methods\\src\\com\\kindani\\test\\LocalStrings.properties";<br />        p = JProperties.loadProperties(name, JProperties.BY_PROPERTYRESOURCEBUNDLE);<br />        assertEquals(value, p.getProperty(key));<br />        assertEquals(value,((JProperties.ResourceBundleAdapter)p).getString(key));</p>
		<p>        name = "<a href="http://www.java-asp.net/java/200602/&quot;file:////com//kindani//test//LocalStrings.properties&quot;">\\com\\kindani\\test\\LocalStrings.properties</a>";<br />        p = JProperties.loadProperties(name, JProperties.BY_SYSTEM_CLASSLOADER);<br />        assertEquals(value, p.getProperty(key));</p>
		<p>        name = "<a href="http://www.java-asp.net/java/200602/&quot;file:////com//kindani//test//LocalStrings.properties&quot;">\\com\\kindani\\test\\LocalStrings.properties</a>";<br />        p = JProperties.loadProperties(name, JProperties.BY_CLASSLOADER);<br />        assertEquals(value, p.getProperty(key));</p>
		<p>        name = "test\\LocalStrings.properties";<br />        p = JProperties.loadProperties(name, JProperties.BY_CLASS);<br />        assertEquals(value, p.getProperty(key));<br />    }</p>
		<p>/*<br />    public void testLoadProperties2() throws Exception {<br />        ServletContext context = null;<br />        String path = null;<br />        Properties p = null;<br />        path = "/WEB-INF/classes/LocalStrings.properties";<br />        p = JProperties.loadProperties(context, path);<br />        assertEquals(value, p.getProperty(key));<br />    }<br />*/<br />}<br /><br /><font color="#0000ff">properties文件与JPropertiesTest.java文件相同的目录下<br />LocalStrings.properties文件</font><br /># $Id: LocalStrings.properties,v 1.1 2000/08/17 00:57:52 horwat Exp $</p>
		<p># Default localized resources for example servlets<br /># This locale is en_US</p>
		<p>helloworld.title=Hello World!</p>
		<p>requestinfo.title=Request Information Example<br />requestinfo.label.method=Method:<br />requestinfo.label.requesturi=Request URI:<br />requestinfo.label.protocol=Protocol:<br />requestinfo.label.pathinfo=Path Info:<br />requestinfo.label.remoteaddr=Remote Address:</p>
		<p>requestheader.title=Request Header Example</p>
		<p>requestparams.title=Request Parameters Example<br />requestparams.params-in-req=Parameters in this request:<br />requestparams.no-params=No Parameters, Please enter some<br />requestparams.firstname=First Name:<br />requestparams.lastname=Last Name:</p>
		<p>cookies.title=Cookies Example<br />cookies.cookies=Your browser is sending the following cookies:<br />cookies.no-cookies=Your browser isn´t sending any cookies<br />cookies.make-cookie=Create a cookie to send to your browser<br />cookies.name=Name:<br />cookies.value=Value:<br />cookies.set=You just sent the following cookie to your browser:</p>
		<p>sessions.title=Sessions Example<br />sessions.id=Session ID:<br />sessions.created=Created:<br />sessions.lastaccessed=Last Accessed:<br />sessions.data=The following data is in your session:<br />sessions.adddata=Add data to your session<br />sessions.dataname=Name of Session Attribute:<br />sessions.datavalue=Value of Session Attribute:<br /></p>
<img src ="http://www.blogjava.net/junky/aggbug/86708.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-12-10 15:47 <a href="http://www.blogjava.net/junky/archive/2006/12/10/86708.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈jdbc连接sql server2000数据库</title><link>http://www.blogjava.net/junky/archive/2006/12/10/86657.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 10 Dec 2006 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/12/10/86657.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/86657.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/12/10/86657.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/86657.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/86657.html</trackback:ping><description><![CDATA[
		<p>谈jdbc连接sql server2000数据库 <br />  <br />前提：1.sql server 2000 任意版本    //本人用的是个人版<br />      2.sql server 2000 sp3升级包<br />          你可以在这里下载<a href="http://www.bossed.com.cn/download/detailcp.asp?id=74">http://www.bossed.com.cn/download/detailcp.asp?id=74</a><br />      3.sql server 2000 jdbc 驱动  //这个就需要自己找了!<br />      4.jdk1.4                      //以下的例子是该版本<br />在以上条件满足的情况下,作以下事情<br />      1.建立新数据库名为：TESTDB ,并在其中建立一个名为test_student的表<br />          包括以下几列（Sno，Sname，Sage，Ssex，Sclass）  <br />      2.开始编写你自己的连接数据库的类（我这里是借鉴他人的版权不归我所有），你也可以用自己的方法 <br />class Testj{<br />    public static void main(String args[])<br />    {  <br />        String RL = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=TESTDB";<br />        String user ="king";//这里替换成你自已的数据库用户名<br />        String password = "sql";//这里替换成你自已的数据库用户密码<br />        String sqlStr = "select * from test_student";</p>
		<p>        try{    //这里的异常处理语句是必需的.否则不能通过编译!    <br />            Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");<br />            System.out.println( "类实例化成功!" );<br />            System.out.println("slkdjf");<br />            Connection con = DriverManager.getConnection(RL,user,password);<br />            System.out.println( "创建连接对像成功!" );</p>
		<p>            Statement st = con.createStatement();<br />            System.out.println( "创建Statement成功!" );</p>
		<p>            ResultSet rs = st.executeQuery( sqlStr );<br />            System.out.println( "操作数据表成功!" );<br />            System.out.println( "----------------!" );</p>
		<p>            while(rs.next())<br />            {<br />                System.out.print(rs.getInt("Sno") + "    ");<br />                System.out.print(rs.getString("Sname") + "    ");<br />                System.out.print(rs.getInt("Sage") + "    ");<br />                System.out.print(rs.getString("Ssex") + "    ");<br />                System.out.println(rs.getString("Sclass"));<br />            }<br />            rs.close();<br />            st.close();<br />            con.close();<br />        }<br />        catch(Exception err){<br />            err.printStackTrace(System.out);<br />        }<br />    }<br />}<br />下面进行调试：<br />  javac Testj.java<br />  java Testj<br />  如果正确输出应该是：<br />  类实例化成功!<br />slkdjf<br />创建连接对像成功!<br />创建Statement成功!<br /><nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(1);" onmouseover="kwE(event,1);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)操作数','_blank');" onmouseout="kwL(event);" target="_blank">操作数</a></nobr>据表成功!<br />----------------!<br />2000    小刚               21    男    12        <br />2001    小黄               22    女    12        <br />2002    李娜               20    女    11        <br />2003    王芳               19    女    null<br />2004    <nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(4);" onmouseover="kwE(event,4);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)黄明','_blank');" onmouseout="kwL(event);" target="_blank">黄明</a></nobr>               22    男    11        <br />2005    梅兰               21    女    12        <br />2006    李玉               22    女    15        <br />2007    李平               32    女    12        </p>
		<p>注意：这里有几点要说明<br />1.<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(5);" onmouseover="kwE(event,5);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)路径','_blank');" onmouseout="kwL(event);" target="_blank">路径</a></nobr>问题：<br />  你必须配置你的classpath路径否则他在编译时会抱错<br />  java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlserver.SQLServerDriver<br />        at java.net.URLClassLoader$1.run(URLClassLoader.java:199)<br />        at java.security.AccessController.doPrivileged(Native Method)<br />        at java.net.URLClassLoader.findClass(URLClassLoader.java:187)<br />        at java.lang.ClassLoader.loadClass(ClassLoader.java:289)<br />        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)<br />        at java.lang.ClassLoader.loadClass(ClassLoader.java:235)<br />        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)<br />        at java.lang.Class.forName0(Native Method)<br />        at java.lang.Class.forName(Class.java:141)<br />        at Test.main(Test.java:11) <br />你的路径应该是这样配置：你可以在在安装jdbc驱动后看那里的帮助文档（是英文的）；<br />//这里指在xp系统下<br /> classpath = ,;C:\Program Files\Microsoft SQL Server 2000 Driver for JDBC\lib\msbase.jar;<br />              C:\Program Files\Microsoft SQL Server 2000 Driver for JDBC\lib\mssqlserver.jar;<br />              C:\Program Files\Microsoft SQL Server 2000 Driver for JDBC\lib\msutil.jar;<br />  可千万不要写错哟！<br /> 2.sp3补丁包问题：<br />    如果你在编译时出现下列问题 那么你需要下载并安装sp3补丁包<br />   java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Error establis<br />hing socket.<br />        at com.microsoft.jdbc.base.BaseExceptions.createException(Unknown Source)<br />        at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)<br />        at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)<br />        at com.microsoft.jdbc.sqlserver.tds.TDSConnection.&lt;init&gt;(Unknown Source)<br />        at com.microsoft.jdbc.sqlserver.SQLServerImplConnection.open(Unknown Source)<br />        at com.microsoft.jdbc.base.BaseConnection.getNewImplConnection(Unknown Source)<br />        at com.microsoft.jdbc.base.BaseConnection.open(Unknown Source)<br />        at com.microsoft.jdbc.base.BaseDriver.connect(Unknown Source)<br />        at java.sql.DriverManager.getConnection(Unknown Source)<br />        at java.sql.DriverManager.getConnection(Unknown Source)<br />        at Test.main(Test.java:14) <br />3.权限问题    <br />   如果你出现类似这样的问题<br />   类<nobr><a class="iAs" oncontextmenu="return false;" onmousemove="kwM(2);" onmouseover="kwE(event,2);" style="CURSOR: hand; COLOR: #0000ff; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="window.open('http://www.baidu.com/s?wd=site:(bokee.com)实例','_blank');" onmouseout="kwL(event);" target="_blank">实例</a></nobr>化成功!<br />slkdjf<br />java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]用户 'king' 登录失败。<br />原因: 未与信任 SQL Server 连接相关联。<br />    at com.microsoft.jdbc.base.BaseExceptions.createException(Unknown Source)<br />    at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)<br />    at com.microsoft.jdbc.sqlserver.tds.TDSRequest.processErrorToken(Unknown Source)<br />    at com.microsoft.jdbc.sqlserver.tds.TDSRequest.processReplyToken(Unknown Source)<br />    at com.microsoft.jdbc.sqlserver.tds.TDSLoginRequest.processReplyToken(Unknown Source)<br />    at com.microsoft.jdbc.sqlserver.tds.TDSRequest.processReply(Unknown Source)<br />    at com.microsoft.jdbc.sqlserver.SQLServerImplConnection.open(Unknown Source)<br />    at com.microsoft.jdbc.base.BaseConnection.getNewImplConnection(Unknown Source)<br />    at com.microsoft.jdbc.base.BaseConnection.open(Unknown Source)<br />    at com.microsoft.jdbc.base.BaseDriver.connect(Unknown Source)<br />    at java.sql.DriverManager.getConnection(DriverManager.java:512)<br />    at java.sql.DriverManager.getConnection(DriverManager.java:171)<br />    at Testj.main(Testj.java:14)<br />    <br />原困是未设置SQL SERVER登录认证模式为混合认证模式，因为SQL SERVER默认安装后认证模式为WINDOWS认证模式，从而导致出错。<br />解决方法：启动SQLSERVER企业管理器，选择要进行认证模式设置的服务器。右击该服务器，在弹出菜单中选择属性，SQL SERVER将<br />弹出属性对话框在属性对话框中选择安全性选项，在身份验证处选择“SQL Server和Windows”，然后确定。</p>
<img src ="http://www.blogjava.net/junky/aggbug/86657.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-12-10 11:47 <a href="http://www.blogjava.net/junky/archive/2006/12/10/86657.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>读取配置文件的几种方法</title><link>http://www.blogjava.net/junky/archive/2006/06/04/50369.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 04 Jun 2006 15:27:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/06/04/50369.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/50369.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/06/04/50369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/50369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/50369.html</trackback:ping><description><![CDATA[
		<div class="postText">在读spring in aciton 时，他用的BeanFactory factory = new XmlBeanFactory(new FileInputStream("hello.xml"));<br />可是现在的用的1.2.6版本的构造器(XmlBeanFactory)只能接收Resource接口了，所以调不出来是正常的事情，假设现在有一个文件hello.xml<br />读取方法<br /><br />1:ApplicationContext cx=new FileSystemXmlApplicationContext("hello.xml");//指定的路径去找文件<br />2:ApplicationContext factory = new ClassPathXmlApplicationContext("hello.xml");//还会在classpath去找<br />3:Resource fa = new FileSystemResource("hello.xml");<br />   BeanFactory factory=new XmlBeanFactory(fa);<br />4:这个要设制classpath了，麻烦<br />　 Resource res = new ClassPathResource("com/springinaction/chapter01/hello/hello.xml");<br />　 BeanFactory factory=new XmlBeanFactory(res);<br />好了，用了上面那种方法都可以调用getBean("your bean name")了，<br />eg: BeanFactory factory=new XmlBeanFactory(fa);<br />      hello he=(hello)factory.getBean("hello");<br />              he.getHello(); </div>
<img src ="http://www.blogjava.net/junky/aggbug/50369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-06-04 23:27 <a href="http://www.blogjava.net/junky/archive/2006/06/04/50369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM的垃圾回收机制详解和调优 5.如何从JVM中获取信息来进行调整</title><link>http://www.blogjava.net/junky/archive/2006/06/04/50366.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 04 Jun 2006 15:19:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/06/04/50366.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/50366.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/06/04/50366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/50366.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/50366.html</trackback:ping><description><![CDATA[
		<strong>5.如何从JVM中获取信息来进行调整<br /><br /></strong>　　-verbose.gc开关可显示gc的操作内容。打开它，可以显示最忙和最空闲收集行为发生的时间、收集前后的内存大小、收集需要的时间等。打开-xx:+ printgcdetails开关，可以详细了解gc中的变化。打开-XX: + PrintGCTimeStamps开关，可以了解这些垃圾收集发生的时间，自jvm启动以后以秒计量。最后，通过-xx: + PrintHeapAtGC开关了解堆的更详细的信息。为了了解新域的情况，可以通过-XX:=PrintTenuringDistribution开关了解获得使用期的对象权。<br /><br /><strong>6.Pdm系统JVM调整<br /></strong><br />　　<strong>6.1.服务器：前提内存1G 单CPU</strong><br /><br />　　可通过如下参数进行调整：－server 启用服务器模式（如果CPU多，服务器机建议使用此项）<br /><br />　　－Xms,－Xmx一般设为同样大小。 800m<br />　　－Xmn 是将NewSize与MaxNewSize设为一致。320m<br />　　－XX:PerSize 64m<br />　　－XX:NewSize 320m 此值设大可调大新对象区，减少Full GC次数<br />　　－XX:MaxNewSize 320m<br />　　－XX:NewRato NewSize设了可不设。4 <br />　　－XX: SurvivorRatio 4<br />　　－XX:userParNewGC 可用来设置并行收集 <br />　　－XX:ParallelGCThreads 可用来增加并行度 4<br />　　－XXUseParallelGC 设置后可以使用并行清除收集器<br />　　－XX：UseAdaptiveSizePolicy 与上面一个联合使用效果更好，利用它可以自动优化新域大小以及救助空间比值<br /><br />　　<strong>6.2.客户机：通过在JNLP文件中设置参数来调整客户端JVM<br /></strong><br />　　JNLP中参数：initial-heap-size和max-heap-size<br /><br />　　这可以在framework的RequestManager中生成JNLP文件时加入上述参数，但是这些值是要求根据客户机的硬件状态变化的（如客户机的内存大小等）。建议这两个参数值设为客户机可用内存的60％（有待测试）。为了在动态生成JNLP时以上两个参数值能够随客户机不同而不同，可靠虑获得客户机系统信息并将这些嵌到首页index.jsp中作为连接请求的参数。<br /><br />　　在设置了上述参数后可以通过Visualgc 来观察垃圾回收的一些参数状态，再做相应的调整来改善性能。一般的标准是减少fullgc的次数，最好硬件支持使用并行垃圾回收（要求多CPU）。<img src ="http://www.blogjava.net/junky/aggbug/50366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-06-04 23:19 <a href="http://www.blogjava.net/junky/archive/2006/06/04/50366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM的垃圾回收机制详解和调优 4.BEA JRockit JVM的使用</title><link>http://www.blogjava.net/junky/archive/2006/06/04/50364.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 04 Jun 2006 15:18:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/06/04/50364.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/50364.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/06/04/50364.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/50364.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/50364.html</trackback:ping><description><![CDATA[　　如前所述，默认状态下HotSpot对新域使用复制收集器，对旧域使用标记－清除－压缩收集器。在新域中使用复制收集器有很多意义，因为应用程序生成的大部分对象是短寿命的。理想状态下，所有过渡对象在移出Eden空间时将被收集。如果能够这样的话，并且移出Eden空间的对象是长寿命的，那么理论上可以立即把它们移进旧域，避免在救助空间反复复制。但是，应用程序不能适合这种理想状态，因为它们有一小部分中长寿命的对象。最好是保持这些中长寿命的对象并放在新域中，因为复制小部分的对象总比压缩旧域廉价。为控制新域中对象的复制，可用-XX:TargetSurvivorRatio控制救助空间的比例（该值是设置救助空间的使用比例。如救助空间位1M，该值50表示可用500K）。该值是一个百分比，默认值是50。当较大的堆栈使用较低的sruvivorratio时，应增加该值到80至90，以更好利用救助空间。用-XX:maxtenuring threshold可控制上限。<br /><br />　　为放置所有的复制全部发生以及希望对象从eden扩展到旧域，可以把MaxTenuring Threshold设置成0。设置完成后，实际上就不再使用救助空间了，因此应把SurvivorRatio设成最大值以最大化Eden空间，设置如下：<br />　　java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio＝50000 …<br /><br /><strong>4.BEA JRockit JVM的使用</strong><br />　　Bea WebLogic 8.1使用的新的JVM用于Intel平台。在Bea安装完毕的目录下可以看到有一个类似于jrockit81sp1_141_03的文件夹。这就是Bea新JVM所在目录。不同于HotSpot把Java字节码编译成本地码，它预先编译成类。JRockit还提供了更细致的功能用以观察JVM的运行状态，主要是独立的GUI控制台（只能适用于使用Jrockit才能使用jrockit81sp1_141_03自带的console监控一些cpu及memory参数）或者WebLogic Server控制台。<br /><br />　　Bea JRockit JVM支持4种垃圾收集器：<br />　　<strong>4.1.1.分代复制收集器</strong><br />　　它与默认的分代收集器工作策略类似。对象在新域中分配，即JRockit文档中的nursery。这种收集器最适合单cpu机上小型堆操作。<br /><br />　　<strong>4.1.2.单空间并发收集器</strong><br />　　该收集器使用完整堆，并与背景线程共同工作。尽管这种收集器可以消除中断，但是收集器需花费较长的时间寻找死对象，而且处理应用程序时收集器经常运行。如果处理器不能应付应用程序产生的垃圾，它会中断应用程序并关闭收集。<br /><br />　　分代并发收集器 这种收集器在护理域使用排它复制收集器，在旧域中则使用并发收集器。由于它比单空间共同发生收集器中断频繁，因此它需要较少的内存，应用程序的运行效率也较高，注意，过小的护理域可以导致大量的临时对象被扩展到旧域中。这会造成收集器超负荷运作，甚至采用排它性工作方式完成收集。<br /><br />　　<strong>4.1.3.并行收集器</strong><br />　　该收集器也停止其他进程的工作，但使用多线程以加速收集进程。尽管它比其他的收集器易于引起长时间的中断，但一般能更好的利用内存，程序效率也较高。<br /><br />　　默认状态下，JRockit使用分代并发收集器。要改变收集器，可使用-Xgc:<gc_name>，对应四个收集器分别为gencopy，singlecon，gencon以及parallel。可使用-Xms和-Xmx设置堆的初始大小和最大值。要设置护理域，则使用-Xns:java –jrockit –Xms512m –Xmx512m –Xgc:gencon –Xns128m…尽管JRockit支持-verbose:gc开关，但它输出的信息会因收集器的不同而异。JRockit还支持memory、load和codegen的输出。<br /><br />　　注意 ：如果 使用JRockit JVM的话还可以使用WLS自带的console（C:\bea\jrockit81sp1_141_03\bin下）来监控一些数据，如cpu，memery等。要想能构监控必须在启动服务时startWeblogic.cmd中加入－Xmanagement参数。<br /></gc_name><img src ="http://www.blogjava.net/junky/aggbug/50364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-06-04 23:18 <a href="http://www.blogjava.net/junky/archive/2006/06/04/50364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM的垃圾回收机制详解和调优 3.Sun HotSpot 1.4.1 JVM堆大小的调整</title><link>http://www.blogjava.net/junky/archive/2006/06/04/50363.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 04 Jun 2006 15:16:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/06/04/50363.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/50363.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/06/04/50363.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/50363.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/50363.html</trackback:ping><description><![CDATA[
		<strong>3.Sun HotSpot 1.4.1 JVM堆大小的调整<br /><br /></strong>　　Sun HotSpot 1.4.1使用分代收集器，它把堆分为三个主要的域：新域、旧域以及永久域。Jvm生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后，便获得使用期并进入旧域。在永久域中jvm则存储class和method对象。就配置而言，永久域是一个独立域并且不认为是堆的一部分。<br /><br />　　下面介绍如何控制这些域的大小。可使用-Xms和-Xmx 控制整个堆的原始大小或最大值。 
<p></p><p>　　下面的命令是把初始大小设置为128M：<br />　　java –Xms128m <br />　　–Xmx256m为控制新域的大小，可使用-XX:NewRatio设置新域在堆中所占的比例。<br /><br />　　下面的命令把整个堆设置成128m，新域比率设置成3，即新域与旧域比例为1：3，新域为堆的1/4或32M：<br />　　java –Xms128m –Xmx128m <br />　　–XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值。<br /><br />　　下面的命令把新域的初始值和最大值设置成64m: <br />　　java –Xms256m –Xmx256m –Xmn64m<br />　　永久域默认大小为4m。运行程序时，jvm会调整永久域的大小以满足需要。每次调整时，jvm会对堆进行一次完全的垃圾收集。<br /><br />　　使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic Server应用程序加载较多类时，经常需要增加永久域的最大值。当jvm加载类时，永久域中的对象急剧增加，从而使jvm不断调整永久域大小。为了避免调整，可使用-XX:PerSize标志设置初始值。</p><p>　　下面把永久域初始值设置成32m，最大值设置成64m。<br />　　java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m<br /><br />　　默认状态下，HotSpot在新域中使用复制收集器。该域一般分为三个部分。第一部分为Eden，用于生成新的对象。另两部分称为救助空间，当Eden充满时，收集器停止应用程序，把所有可到达对象复制到当前的from救助空间，一旦当前的from救助空间充满，收集器则把可到达对象复制到当前的to救助空间。From和to救助空间互换角色。维持活动的对象将在救助空间不断复制，直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio可控制新域子空间的大小。<br /><br />　　同NewRation一样，SurvivorRation规定某救助域与Eden空间的比值。比如，以下命令把新域设置成64m，Eden占32m，每个救助域各占16m：<br />　　java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2<br /></p><img src ="http://www.blogjava.net/junky/aggbug/50363.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-06-04 23:16 <a href="http://www.blogjava.net/junky/archive/2006/06/04/50363.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM的垃圾回收机制详解和调优 2.几种垃圾回收机制</title><link>http://www.blogjava.net/junky/archive/2006/06/04/50362.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 04 Jun 2006 15:15:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/06/04/50362.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/50362.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/06/04/50362.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/50362.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/50362.html</trackback:ping><description><![CDATA[
		<strong>2.几种垃圾回收机制<br /><br />2.1.标记－清除收集器</strong>
		<br />　　这种收集器首先遍历对象图并标记可到达的对象，然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。<br /><br /><strong>2.2.标记－压缩收集器</strong><br />　　有时也叫标记－清除－压缩收集器，与标记－清除收集器有相同的标记阶段。在第二阶段，则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。<br /><br /><strong>2.3.复制收集器<br /></strong>　　这种收集器将堆栈分为两个域，常称为半空间。每次仅使用一半的空间，jvm生成的新对象则放在另一半空间中。gc运行时，它把可到达对象复制到另一半空间，从而压缩了堆栈。这种方法适用于短生存期的对象，持续复制长生存期的对象则导致效率降低。<br /><br /><strong>2.4.增量收集器</strong><br />　　增量收集器把堆栈分为多个域，每次仅从一个域收集垃圾。这会造成较小的应用程序中断。<br /><br /><strong>2.5.分代收集器</strong><br />　　这种收集器把堆栈分为两个或多个域，用以存放不同寿命的对象。jvm生成的新对象一般放在其中的某个域中。过一段时间，继续存在的对象将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。<br /><br /><strong>2.6.并发收集器</strong><br />　　并发收集器与应用程序同时运行。这些收集器在某点上（比如压缩时）一般都不得不停止其他操作以完成特定的任务，但是因为其他应用程序可进行其他的后台操作，所以中断其他处理的实际时间大大降低。<br /><br /><strong>2.7.并行收集器</strong><br />　　并行收集器使用某种传统的算法并使用多线程并行的执行它们的工作。在多cpu机器上使用多线程技术可以显著的提高java应用程序的可扩展性。<br /><img src ="http://www.blogjava.net/junky/aggbug/50362.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-06-04 23:15 <a href="http://www.blogjava.net/junky/archive/2006/06/04/50362.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM的垃圾回收机制详解和调优</title><link>http://www.blogjava.net/junky/archive/2006/06/04/50349.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Sun, 04 Jun 2006 14:16:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/06/04/50349.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/50349.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/06/04/50349.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/50349.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/50349.html</trackback:ping><description><![CDATA[
		<strong>　　1.JVM的gc概述<br /><br /></strong>　　gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存。java语言并不要求jvm有gc，也没有规定gc如何工作。不过常用的jvm都有gc，而且大多数gc都使用类似的算法管理内存和执行收集操作。<br /><br />　　在充分理解了垃圾收集算法和执行过程后，才能有效的优化它的性能。有些垃圾收集专用于特殊的应用程序。比如，实时应用程序主要是为了避免垃圾收集中断，而大多数OLTP应用程序则注重整体效率。理解了应用程序的工作负荷和jvm支持的垃圾收集算法，便可以进行优化配置垃圾收集器。<br /><br />　　垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。gc首先要判断该对象是否是时候可以收集。两种常用的方法是引用计数和对象引用遍历。<br /><br /><strong>1.1.引用计数</strong><br />　　引用计数存储对特定对象的所有引用数，也就是说，当应用程序创建引用以及引用超出范围时，jvm必须适当增减引用数。当某对象的引用数为0时，便可以进行垃圾收集。<br /><br /><strong>1.2.对象引用遍历<br /></strong>　　早期的jvm使用引用计数，现在大多数jvm采用对象引用遍历。对象引用遍历从一组对象开始，沿着整个对象图上的每条链接，递归确定可到达（reachable）的对象。如果某对象不能从这些根对象的一个（至少一个）到达，则将它作为垃圾收集。在对象遍历阶段，gc必须记住哪些对象可以到达，以便删除不可到达的对象，这称为标记（marking）对象。<br /><br />　　下一步，gc要删除不可到达的对象。删除时，有些gc只是简单的扫描堆栈，删除未标记的未标记的对象，并释放它们的内存以生成新的对象，这叫做清除（sweeping）。这种方法的问题在于内存会分成好多小段，而它们不足以用于新的对象，但是组合起来却很大。因此，许多gc可以重新组织内存中的对象，并进行压缩（compact），形成可利用的空间。<br /><br />　　为此，gc需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止，只有gc运行。结果，在响应期间增减了许多混杂请求。另外，更复杂的gc不断增加或同时运行以减少或者清除应用程序的中断。有的gc使用单线程完成这项工作，有的则采用多线程以增加效率。<br /><img src ="http://www.blogjava.net/junky/aggbug/50349.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-06-04 22:16 <a href="http://www.blogjava.net/junky/archive/2006/06/04/50349.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《深入JAVA虚拟机》笔记（一）</title><link>http://www.blogjava.net/junky/archive/2006/06/02/49816.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Thu, 01 Jun 2006 16:10:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/06/02/49816.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/49816.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/06/02/49816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/49816.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/49816.html</trackback:ping><description><![CDATA[  看了第6章的java class文件这一部分，我觉得对class文件有进一步的了解。于是想作一点笔记，以备以后查时方便。<br />      这章的一个例子虽然简单，但是我觉的很有一定代表性。例子如下：<br /><br />1：class Act {<br />2：   public static void doMathForever(int m) {<br />3：      int i = 0;<br />4：     int n=4&gt;3?1:0;<br />5：        for (;;) {<br />6：           i += 1;<br />7：            i *= 2;<br />8：       }<br />9：    }<br />10：}<br /><br /><br />我用javap -verbose Act查看，代码如下：（红色为自己加上的注解）<br />Compiled from "Act.java"     <br /><font style="BACKGROUND-COLOR: #ff0000">因为编译原文件不一定必须与java语言相关，可以使用其他语言来编写程序，然后将其编译为class文件，所以这里要写上Act.java而不是Act. 呵呵，想来以前为什么javac 来编译源文件时一定要加.java，而java 执行时就不需要加.java了，当时就是搞不懂，现在明白了。</font><br />class Act extends java.lang.Object<br />  SourceFile: "Act.java"<br /><font style="BACKGROUND-COLOR: #ff0000">SourceFile属性，它提供了产生class文件的源文件的名称，它是一个可选的项，为什么说它是可选项的，因为class可以自己用UE等工具写。</font><br />  minor version: 0<br />  major version: 49<br /><font style="BACKGROUND-COLOR: #ff0000">版本号：我用的是5.0的，出来的major version 是49，书上说1.0或1.2是45，1.4我想可能是48 吧。呵呵，还没有试过。</font><br />  Constant pool:<br /><font style="BACKGROUND-COLOR: #ff0000">这个是常量池，刚看书的时候我还以为常量池放的一定是常量。错。<br />常量池就是该类型所用常量的一个有序集合，包括直接常量(String,integer,floating  point常量）和对其他类型、字段和方法的符号引用。<br /></font>const #1 = Method #3.#12; //  java/lang/Object."&lt;init&gt;":()V<br /><font style="BACKGROUND-COLOR: #ff0000">因为Constant pool#0是不用的，所以只能从#1开始，但不知为什么第一个是Method而不是class，我现在还不明白。</font><br />const #2 = class #13; //  Act<br /><font style="BACKGROUND-COLOR: #ff0000">CONSTANT_Class是对一个类或接口的符号引用。这个是指向#13</font><br />const #3 = class #14; //  java/lang/Object<br />const #4 = Asciz &lt;init&gt;;<br /><font style="BACKGROUND-COLOR: #ff0000"> 这个Asciz应该表示是CONSTANT_Utf8吧，因为C ONSTANT_Utf8可以是存储四种基本信息类型：文字字符串、被定义的类和接口描述、对其他类或接口的符号引用以及属性相关的字符串。<br />&lt;init&gt;是实例的初始化方法，是实例调用方法前必须要&lt;init&gt;的，<br />&lt;clinit&gt;是类的初始化方法。<br /></font>const #5 = Asciz ()V;<br /><font style="BACKGROUND-COLOR: #ff0000">此&lt;init&gt;的描述符，()V表示&lt;init&gt;没有带参数，返回的是void型的。<br />书上介绍：<br />()I  int getSize()  <br />() Ljava/lang/String      String toString()</font><br />const #6 = Asciz Code;<br /><font style="BACKGROUND-COLOR: #ff0000">Code在所有不是抽象或者本地方法的method_info信息中,都存在一个Code_attribute表。<br />但是我试一下在抽象的方法中同样也有code的啊，不懂中。<br /></font>const #7 = Asciz LineNumberTable;<br /><font style="BACKGROUND-COLOR: #ff0000">LineNumberTable属性建立了方法字节码流偏移量和源代码行号之间的映射关系。关于这一点，我在下面详细谈到。<br /></font>const #8 = Asciz doMathForever;<br />const #9 = Asciz (I)V;<br />const #10 = Asciz SourceFile;<br />const #11 = Asciz Act.java;<br />const #12 = NameAndType #4:#5;//  "&lt;init&gt;":()V<br /><font style="BACKGROUND-COLOR: #ff0000">NameAndType指向字段或者方法的符号引用的一部分。为什么没有指向#8,#9呢？不懂中。<br /></font>const #13 = Asciz Act;<br />const #14 = Asciz java/lang/Object; 
<p align="justify">{<br />Act();<br />  Code:<br />   Stack=1, Locals=1, Args_size=1<br /><font style="BACKGROUND-COLOR: #ff0000">需要的栈为1个，只是this的存取;本地变量为1个，也是this,方法的参数是1个，也是this传入。<br /></font>   0: aload_0<br /><font style="BACKGROUND-COLOR: #ff0000">从局部变量0中装载引用类型。</font><br />   1: invokespecial #1; //Method java/lang/Object."&lt;init&gt;":()V<br /><font style="BACKGROUND-COLOR: #ff0000">调用Object的&lt;init&gt;方法，因为每个类都是继承Object，所以实例时都要调用Object的&lt;init&gt;方法。</font><br />   4: return<br />  LineNumberTable: <br />   line 1: 0</p><p align="justify">public static void doMathForever(int);<br />  Code:<br />   Stack=2, Locals=3, Args_size=1<br />   0: iconst_0 <font style="BACKGROUND-COLOR: #ff0000">将i 压入栈<br /></font>   1: istore_1 <font style="BACKGROUND-COLOR: #ff0000">放i<br /></font>   2: iconst_1 <font style="BACKGROUND-COLOR: #ff0000">同上<br /></font>   3: istore_2<br />   4: iinc 1, 1  i++<br />  7   iload_1 <font style="BACKGROUND-COLOR: #ff0000">从局部变量1中装载int类型值。</font><br />   8: iconst_2<br />   9: imul<br />   10: istore_1<br />   11: goto 4<br />  LineNumberTable: <br />   line 3: 0  <font style="BACKGROUND-COLOR: #ff0000">源代码第3行对应Code中的0偏移量。</font><br />   line 4: 2<br />   line 6: 4<br />   line 7: 7<br />   line 8: 11</p><p align="justify">}<br /></p><img src ="http://www.blogjava.net/junky/aggbug/49816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-06-02 00:10 <a href="http://www.blogjava.net/junky/archive/2006/06/02/49816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java接口特性学习</title><link>http://www.blogjava.net/junky/archive/2006/05/30/49133.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Tue, 30 May 2006 15:29:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/05/30/49133.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/49133.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/05/30/49133.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/49133.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/49133.html</trackback:ping><description><![CDATA[
		<font size="2">在<span lang="EN-US" style="FONT-SIZE: 10pt"><font face="Times New Roman">Java</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中看到接口，第一个想到的可能就是</span><span lang="EN-US" style="FONT-SIZE: 10pt"><font face="Times New Roman">C++</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的多重继承和</span><span lang="EN-US" style="FONT-SIZE: 10pt"><font face="Times New Roman">Java</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的另外一个关键字</span><span lang="EN-US" style="FONT-SIZE: 10pt"><font face="Times New Roman">abstract</font></span><span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。从另外一个角度实现多重继承是接口的功能之一，接口的存在可以使</span><span lang="EN-US" style="FONT-SIZE: 10pt"><font face="Times New Roman">Java</font></span></font>
		<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的对象可以向上转型为多个基类型，并且和抽象类一样可以防止他人创建该类的对象，因为接口不允许创建对象。</span>
		<span lang="EN-US" style="FONT-SIZE: 10pt">
				<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
				<o:p>
				</o:p>
		</span>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
								<font face="Times New Roman"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">interface</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">关键字用来声明一个接口，它可以产生一个完全抽象的类，并且不提供任何具体实现。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">interface</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的特性整理如下：</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">1.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口中的方法可以有参数列表和返回类型，但不能有任何方法体。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">2.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口中可以包含字段，但是会被隐式的声明为</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">static</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">final</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">3.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口中的字段只是被存储在该接口的静态存储区域内，而不属于该接口。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">4.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口中的方法可以被声明为</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">public</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或不声明，但结果都会按照</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">public</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类型处理。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">5.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当实现一个接口时，需要将被定义的方法声明为</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">public</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类型的，否则为默认访问类型，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">Java</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">编译器不允许这种情况。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">6.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果没有实现接口中所有方法，那么创建的仍然是一个接口。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">7.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">扩展一个接口来生成新的接口应使用关键字</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">extends</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，实现一个接口使用</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">implements</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
								<font face="Times New Roman"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">interface</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在某些地方和</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">abstract</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有相似的地方，但是采用哪种方式来声明类主要参照以下两点：</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo2; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">1.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果要创建不带任何方法定义和成员变量的基类，那么就应该选择接口而不是抽象类。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt 18pt; TEXT-INDENT: -18pt; mso-list: l1 level1 lfo2; tab-stops: list 18.0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'">
						<span style="mso-list: Ignore">
								<font face="Times New Roman">2.<span style="FONT: 7pt 'Times New Roman'">        </span></font>
						</span>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果知道某个类应该是基类，那么第一个选择的应该是让它成为一个接口，只有在必须要有方法定义和成员变量的时候，才应该选择抽象类。因为抽象类中允许存在一个或多个被具体实现的方法，只要方法没有被全部实现该类就仍是抽象类。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<o:p>
								<font face="Times New Roman"> </font>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 18pt">
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">以上就是接口的基本特性和应用的领域，但是接口绝不仅仅如此，在</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">Java</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">语法结构中，接口可以被嵌套，既可以被某个类嵌套，也可以被接口嵌套。这在实际开发中可能应用的不多，但也是它的特性之一。需要注意的是，在实现某个接口时，并不需要实现嵌套在其内部的任何接口，而且，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt">
						<font face="Times New Roman">private</font>
				</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口不能在定义它的类之外被实现。</span>
		</p>
<img src ="http://www.blogjava.net/junky/aggbug/49133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-05-30 23:29 <a href="http://www.blogjava.net/junky/archive/2006/05/30/49133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>真正J2EE软件工程师应具备的能力(转载)</title><link>http://www.blogjava.net/junky/archive/2006/05/29/48855.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Mon, 29 May 2006 15:34:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/05/29/48855.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/48855.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/05/29/48855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/48855.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/48855.html</trackback:ping><description><![CDATA[
		<div class="postbody">
				<span class="postbody">
						<font size="2">1.熟练掌握java语言,深入理解OOP,OOA,OOD等编程思想. <br /><br />2.掌握j2ee各个技术模块 <br />(jsp/servlet, jdbc, ejb, websphere, weblogic等) <br /><br />3.熟悉各种Java IDE和相关开发工具 <br />(Eclipse, Jbuilder, WSAD&lt;最牛&gt;, CVS, ANT, Junit) <br /><br />4.理解ROB的设计原理, 熟练掌握Oracle/SQL Server/DB2 其中至少一种. <br /><br />5.熟悉UML建模, 熟练掌握Rational Rose <br /><br />6.深入理解Design Patten, 熟悉 <br />Struts,spring,hibernate等框架技术 <br /><br />7.有中,大型项目开发经验,能独立完成整个软件模块分析,设计开发,单元测试 <br /><br />8.能迅速接受新技术,快速学习和应用 <br /><br />9.熟悉软件工程,了解前沿技术规范(CMM)和先进开发模式(RUP, XP) <br /><br />10.英语,逻辑思维能力,团队精神等非技术要求. <br /><br />附：身体是本钱，要学会劳逸结合</font>
				</span>
		</div>
<img src ="http://www.blogjava.net/junky/aggbug/48855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-05-29 23:34 <a href="http://www.blogjava.net/junky/archive/2006/05/29/48855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java开源软件之开源江湖的六大帮派</title><link>http://www.blogjava.net/junky/archive/2006/05/29/48853.html</link><dc:creator>junky</dc:creator><author>junky</author><pubDate>Mon, 29 May 2006 15:31:00 GMT</pubDate><guid>http://www.blogjava.net/junky/archive/2006/05/29/48853.html</guid><wfw:comment>http://www.blogjava.net/junky/comments/48853.html</wfw:comment><comments>http://www.blogjava.net/junky/archive/2006/05/29/48853.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/junky/comments/commentRss/48853.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/junky/services/trackbacks/48853.html</trackback:ping><description><![CDATA[
		<p>
				<strong>丐帮 - Apache Software Foundation<br /><br /></strong>　　在我开始学习Java的时候，Apache的Jakarta子项目还很弱小，Apache的头牌是Apache HTTPD Server(至今也还是头牌)，如今已经成了江湖第一大帮。Apache势力庞大，背后有众多大厂商的支持，例如IBM资助了apache的好几个 project，Sun则和tomcat合作密切，而BEA砸下重资在Beehive上面。有了官府的支持，Apache理所当然了成了第一大帮。不过 Apache的问题就是组织成员太复杂了，旗下各个project来自三山五岳，良莠不齐，甚至各个门下子弟还经常发生冲突，漫无纪律。例如ant是构建工具头牌，Maven又要抢山头；OJB是持久层头牌，但是Torque还不肯让位，他两位还没有把座次安排好，iBATIS也要加入丐帮......</p>
		<p>　　对于这样一个没有组织纪律，自己内部互相冲突的丐帮来说，我已经不存什么好感了，除了丐帮还时不时有几个优秀的弟子，例如log4j，ant，common，他注定永远不能成为武林盟主。</p>
		<p>　　<strong>少林 - Eclipse Foundation<br /></strong><br />　　Eclipse来头不小，直接来自IBM，并且已经得到业界众多厂商的支持，由于有官府的大力支持，Eclipse成为武林盟主的可能性很大。 Eclipse下属的各个子项目也都身怀绝技，SWT，EMF，GEF，RCP，SDO，每个都是独当一面的好手。最关键的是Eclipse是WSAD的基础，IBM很多开发人员直接为Eclipse开发，这意味着帮派和官府的直接勾结，待到IBM把Rose XDE的功能放入Eclipse，号令天下也是指日可待。</p>
		<p>　　<strong>武当 - JBoss Inc<br /></strong><br />　　JBoss来自草莽，没有丐帮的人多势众，没有少林的官府支持，然而经过自身的努力，已经跻身江湖顶级帮派行列，并且具备了很大的发言权。 JBoss的特点是武功自成一派，旗下每个子项目都具备非常强悍的实力，但是各个子项目又可以组成一个有机的整体，组成一个阵势，发挥意想不到的威力。其中JBoss的独门武功－Hibernate则是威力最大的杀手锏，凭借这一功夫，JBoss虽然不算很大，但是已经成为了Java企业界的巨头之一，能够以自己的声音影响整个武林。</p>
		<p>　　<strong>峨嵋 - Opensymphony</strong><br />　<br />　　opensymphony不能跟上述三大帮派相比，但是她独具特色，门下弟子不多，但是各个都有绝活，因此在武林当中也站稳了脚跟。例如Webwork成为了下一代MVC框架Struts Ti的核心，OSCache是颇受欢迎的Cache产品，Quartz则是很有名的Java Job软件，Sitemesh也是一款灵巧易用的软件。所有这些虽然都不算重量级武功，但是都独当一面，在整个武林都独树一帜，令人侧目。</p>
		<p>　　<strong>逍遥派 - codehaus</strong><br /><br />　　codehaus下面的Groovy, DamageControl, XStream, Nano, Pico, AspectWerkz武功都是犹如凌波微步般, 既实用又优雅，并且该组织背后有有ThoughWorks这样一个技术至上的咨询公司撑腰，所以它的武功都是讲究敏捷，优雅，易用，于繁重的开发工作中体味出一丝丝悠闲的乐趣，真正符合了逍遥的意境。</p>
		<p>　　<strong>昆仑 - objectweb<br /></strong><br />　　objectweb僻处法国，远离IT全球中心，就好像昆仑远处西域一样。因而objectweb也和中原武学有很大的不同，剑走偏锋。例如objectweb的项目偏重于cluster和分布式方面的支持，例如c-jdbc，rmi-jdbc，Perseus，XAPool等等。正是因为他的剑走偏锋，才使得他不那么知名于中原武林，也正是因为剑走偏锋，才使得他独树一帜，保持了自己独有的特色。</p>
<img src ="http://www.blogjava.net/junky/aggbug/48853.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/junky/" target="_blank">junky</a> 2006-05-29 23:31 <a href="http://www.blogjava.net/junky/archive/2006/05/29/48853.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>