﻿<?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-denver-文章分类-J2SE</title><link>http://www.blogjava.net/denver/category/27490.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 06 Dec 2007 02:19:21 GMT</lastBuildDate><pubDate>Thu, 06 Dec 2007 02:19:21 GMT</pubDate><ttl>60</ttl><item><title>Java 技术新手入门</title><link>http://www.blogjava.net/denver/articles/162374.html</link><dc:creator>丹佛儿</dc:creator><author>丹佛儿</author><pubDate>Thu, 22 Nov 2007 06:29:00 GMT</pubDate><guid>http://www.blogjava.net/denver/articles/162374.html</guid><wfw:comment>http://www.blogjava.net/denver/comments/162374.html</wfw:comment><comments>http://www.blogjava.net/denver/articles/162374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/denver/comments/commentRss/162374.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/denver/services/trackbacks/162374.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Java 技术新手入门                                                利用 Java 教程提升 Java 编程技术                                                                                                     ...&nbsp;&nbsp;<a href='http://www.blogjava.net/denver/articles/162374.html'>阅读全文</a><img src ="http://www.blogjava.net/denver/aggbug/162374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/denver/" target="_blank">丹佛儿</a> 2007-11-22 14:29 <a href="http://www.blogjava.net/denver/articles/162374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 Eclipse Help 中如何组织 Java API 参考文档</title><link>http://www.blogjava.net/denver/articles/162366.html</link><dc:creator>丹佛儿</dc:creator><author>丹佛儿</author><pubDate>Thu, 22 Nov 2007 06:03:00 GMT</pubDate><guid>http://www.blogjava.net/denver/articles/162366.html</guid><wfw:comment>http://www.blogjava.net/denver/comments/162366.html</wfw:comment><comments>http://www.blogjava.net/denver/articles/162366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/denver/comments/commentRss/162366.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/denver/services/trackbacks/162366.html</trackback:ping><description><![CDATA[<blockquote>本文介绍了生成易用且可供搜索的 Java 应用程序编程接口（Java application programming interfaces，API）的参考文档的不同方法。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p><a name="Background"><span class="atitle">背景</span></a></p>
<table cellspacing="0" cellpadding="0" width="200" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee">
                        <p>提高产品文档的可使用性是许多项目成功的关键。项目的成功直接归因于您生成并书写优秀文档的工作。</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>本材料假设您熟悉 Java 软件、Java API 参考文档结构、Javadoc 生成，并且想要了解更多关于如何提供改进的 Java API 参考文档的信息。<br />
对于初学者，您应该了解下面这些内容：
<ul>
    <li>Javadoc，Sun Microsystems 创建的开源工具。要了解更多信息，请阅读 <a href="http://java.sun.com/j2se/javadoc/" target="_blank">java.sun.com/j2se/javadoc</a>。
    <li>JavaHelp，拥有索引和搜索能力的帮助集。要了解更多信息，请参见 <a href="http://java.sun.com/products/javahelp/" target="_blank">java.sun.com/products/javahelp</a>。
    <li>Java Help 的编写工具。要了解更多信息，参考 <a href="http://java.sun.com/products/javahelp/industry.html" target="_blank">java.sun.com/products/javahelp/industry.html</a> 上的列表。
    <li>Standard Java Coding Conventions。要了解详细情况，请参见 <a href="http://java.sun.com/docs/codeconv/index.html" target="_blank">java.sun.com/docs/codeconv</a> 和快速参考单。
    <li>Javadoc Conventions。要了解详细情况，请参见 <a href="http://java.sun.com/j2se/javadoc/writingdoccomments/index.html" target="_blank">java.sun.com/j2se/javadoc/writingdoccomments</a>。 </li>
</ul>
<p>&nbsp;</p>
<p><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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Build_Java_API_doc"><span class="atitle">构建易用且可供搜索的 Java API 文档</span></a></p>
<p>本文介绍了生成易用且可供搜索的 Java 应用程序编程接口（Java application programming interfaces，API）的参考文档的不同方法。所介绍的方法是用我开发的 JavaTOC doclet 生成的 Javadoc 标准解决方案和 Eclipse Plug-in Help System。JavaTOC doclet 生成内容表格（table-of-contents，TOC），使 Javadoc API 参考文档帮助用户很容易地在 API 参考文档中搜索具体类、接口，或方法。</p>
<p>Javadoc API 参考文档需要即是可浏览的，又是可供搜索的。标准的 Javadoc 没有完全提供此能力。充分编制文档的 API 可以满足许多目的，但是最重要的原因是令用户充分了解并搜索他们可用的 API 方法。如果没有适当的编制，或不可供搜索，那么即使是原始的作者可能也不理解源代码了。该解决方案就是要养成编制源代码文档的习惯，并且为 Java API 参考生成可供搜索的结构（TOC 导航）。JavaTOC doclet 通过为参考生成可供搜索的结构来解决此问题。</p>
<p>搜索和浏览假定信息是由特定查询的相关性拣选出来的，生成了许多特定的序列作为结果。举例来说，在标准的 Javadoc 中，对具体方法的描述的 API 信息的搜索返回整个类的描述。</p>
<p><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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Considered_Approaches"><span class="atitle">深思熟虑的方法</span></a></p>
<table cellspacing="0" cellpadding="0" width="200" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee">
                        <p>该解决方案是要养成编制源代码文档的习惯。如果没有适当的编制，那么即使是原始的作者可能也不理解源代码了。</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>生成 Java API 参考文档的工具相当多。我当前的推荐是结合 Javadoc 或 DITA API 规范使用的 JavaTOC doclet。
<ul>
    <li>Javadoc 是 Sun 所有的，将开发人员的注释从 Java 源代码中抽取出来，并输出为 HTML 的工具。Javadoc 工具生成了 Java API 参考文档的基本结构。该结果是一组包和类的 Javadoc HTML API 文档。
    <li>JavaTOC doclet 生成了 TOC 导航，以及 Java API 参考文档的搜索能力。IBM DITA API 规范团队已经开发了一个 DITA 主题类型包，用于生成 Java API 文档文件以及将包含于 Eclipse Help 系统中的参考的导航清单。 </li>
</ul>
<br />
<p>&nbsp;</p>
<p>以下的实例（<strong>没有 toc 导航的 API 参考的实例</strong>和<strong>具有 toc 导航的 API 参考的实例</strong>）使用了来自 <a href="http://sourceforge.net/project/showfiles.php?group_id=132728&amp;package_id=145774&amp;release_id=419149" name="download">DITA Open Toolkit</a> 的 Java 源代码。DITA Open Toolkit 版本 1.0.2 或之上的版本提供了 Command Prompt 接口，作为几乎不了解 Ant 的用户轻松使用工具包的选择。当您下载完 zip 文件之后，您将会在 <strong>DITA-OT1.2_src\DITA-OT1.2-src\src</strong> 目录中找到本文实例中使用的源代码。</p>
<p><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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="About_Javadoc_and_the_JavaTOC_doclet"><span class="atitle">关于 Javadoc 和 JavaTOC doclet</span></a></p>
<p>标准的 Javadoc Help 和定制的 Eclipse Javadoc Help 的最大区别是是否提供 TOC 导航。标准的 Javadoc Help 提供一些额外的框，以让您浏览包和类。定制的 Eclipse Javadoc Help 包含 Eclipse 风格的 XML 导航文件，而不是那些额外的 HTML 框。 Eclipse 风格的 XML 导航文件生成了允许用户搜索具体包、类或接口的 TOC 导航。定制的 Eclipse Java API 参考解决方案提供了将要包含于 Eclipse 帮助系统中的文档的导航清单。</p>
<p>整个 Eclipse 平台都是围绕插件的思想开发的。如果您想向 Eclipse 平台中加入您的帮助文档，那么您必须开发新的帮助插件。插件由 HTML 和图像文件、XML 格式的内容文件的表格，以及清单文件。JavaTOC doclet 自动生成整个 Eclipse 插件结构，包括直接从 Java 源代码中抽取的 XML 导航 TOC 文件。<br />
</p>
<p><strong>JavaTOC</strong> doclet 是与 Javadoc 工具一起工作的定制程序。该 doclet 提供了允许您在 Javadoc 文档文件之上生成 TOC 导航的不断增加的灵活性。</p>
<p>JavaTOC doclet 为 IBM DITA API 规范（开发它是用于为了编制及生成 Java API 参考而生成 Java DITA（XML）API 文件）集成了 DITAdoclet 工具。该解决方案还包括 Eclipse Help 系统中将包含的 Java API 参考文档的导航清单。</p>
<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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Eclipse_Javadoc_API_reference_structure_generated_with_standard_Javadoc_too"><span class="atitle">用标准的 Javadoc 工具生成的 Eclipse Javadoc API 参考结构</span></a></p>
<p>要在 Eclipse 中访问标准的 Javadoc 在线帮助，您可以在菜单栏上选择 <strong>Help &gt; Help Contents</strong>。它将在自己的浏览器中打开在线帮助。<br />
在左窗格中，有内容表格、搜索，和上下文敏感的帮助链接的选项卡视图。下面的实例，图 1，显示了标准的 Javadoc API 参考结构。它是仅仅用标准的 Javadoc 工具在 Eclipse 环境中生成的。</p>
<br />
<a name="figure1"><strong>图 1. Javadoc API 参考结构</strong></a><br />
<img height="360" alt="显示 Javadoc API 参考结构的屏幕抓取" src="http://www.ibm.com/developerworks/cn/rational/07/0320_alupului/eclipse-1.jpg" width="572" /> <br />
<p>org.eclipse.help.toc 的扩展点确定其为帮助系统的插件。</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing1"><strong>清单 1. plug-in.xml</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                &lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;?eclipse version="1.0"?&gt;
                        &lt;plugin&gt;
                        &lt;extension point="org.eclipse.help.toc"&gt;
                        &lt; toc file="doclet.toc.xml" primary="true"/&gt;
                        &lt;/extension&gt;
                        &lt;/plugin&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing2"><strong>清单 2. MANIFEST.MF</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                Manifest-Version: 1.0
                        Bundle-ManifestVersion: 2
                        Bundle-Name: Doc Plug-in
                        Bundle-SymbolicName: org.dita.dost.doc; singleton:=true
                        Bundle-Version: 1.0.0
                        Bundle-Activator: org.dita.dost.doc.DocPlugin
                        Bundle-Localization: plugin
                        Require-Bundle: org.eclipse.ui,
                        org.eclipse.core.runtime
                        Eclipse-AutoStart: true</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>或者</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing3"><strong>清单 3. plug-in.xml</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                &lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;?eclipse version="1.0"?&gt;
                        &lt;plugin
                        name = "%Plugin.name"
                        id = "org.dita.dost.user.doc"
                        version = "7.0.1.0"
                        provider-name = "%Plugin.providerName"&gt;
                        &lt;extension point="org.eclipse.help.toc"&gt;
                        &lt; toc file="doclet.toc.xml" primary="true"/&gt;
                        &lt;/extension&gt;
                        &lt;/plugin&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>将插件的名称、id、版本，和供应商名称改为适合您的工程的值。
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing4"><strong>清单 4. plugin.properties</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                         # NLS_MESSAGEFORMAT_VAR
                        # ==============================================================================
                        # Online Help - Translation Instruction: section to be translated
                        # =============================================================================
                        Plugin.name = Building DITA output
                        Plugin.providerName = IBM</pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>文件 doclet.toc.xml 指的是该插件的内容表，该文件将为 Eclipse 帮助窗口的左边窗格中的层次信息提供数据。一个简单的文件中包含如清单 2 所示的内容。</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing5"><strong>清单 5. doclet.toc.xml</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                &lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;?NLS TYPE="org.eclipse.help.toc"?&gt;
                        &lt;toc label="Building DITA output"&gt;
                        &lt;topic label="API References" href="index.html"/&gt;
                        &lt;/toc&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p><strong>href = "index.html"</strong> 是所生成的 javadoc api 参考的链接。如果您想要让右边的窗格在打开文档时不带有 HTML 框，那么该链接为 href="overview-summary.html"。</p>
<p><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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Standard_Javadoc_navigation_bar_organization"><span class="atitle">标准的 Javadoc 导航栏组织</span></a></p>
<p>标准的 Javadoc 导航栏不允许用户搜索具体的包、类，或方法。<br />
这是 SUN Javadoc 组织并描述 Javadoc 选项卡导航的方式 —— 图 2。</p>
<br />
<a name="figure2"><strong>图 2. Javadoc 选项卡导航</strong></a><br />
<img height="59" alt="显示 Javadoc 选项卡导航的屏幕抓取" src="http://www.ibm.com/developerworks/cn/rational/07/0320_alupului/javadoc-top.jpg" width="572" /> <br />
<p>
<table cellspacing="0" cellpadding="0" width="200" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee">
                        <p>
                        <table cellspacing="3" cellpadding="3" width="100%" border="1">
                            <tbody>
                                <tr align="left" bgcolor="#dce6dd">
                                    <td>
                                    <p>要生成包注释文件，您必须将其命名为 package.html，并且放在源代码树中的包目录下，和 .java 文件在一起。Javadoc 将自动寻找该位置中的此文件名。注意该文件名等同于所有包。<br />
                                    <br />
                                    包注释文件的内容是用 HTML 写的大文档注释，像其他所有注释一样，有一个 例外：<br />
                                    文档注释中不应该包含注释分隔符 <strong>/** 或 */</strong> 或主要的星号。在书写注释时，您应该在第一句中写上该包的摘要，而不是写上标题或其他文本。<br />
                                    您可以包含包标签，如同所有文档注释一样，所有的标签，除了 <strong>{@link} </strong>，都必须出现在描述之后。如果您在包注释文件中添加 <strong>@see</strong> 标签，那么它必须有全限定名。</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<table cellspacing="0" cellpadding="0" width="200" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee">
                        <p>
                        <table cellspacing="3" cellpadding="3" width="100%" border="1">
                            <tbody>
                                <tr align="right" bgcolor="#dce6dd">
                                    <td>
                                    <p>SUN <strong>Javadoc </strong>将生成源自四种不同类型的&#8220;源&#8221;文件的输出：<br />
                                    类的 Java 语言源文件（.java）、包注释文件、概要注释文件，和各式各样未处理的文件。</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<dl compact>
<dt><strong>Overview</strong>
<dd>Overview 页是此 API 文档的第一页，并且列出所有包，并带有摘要。该页还可以包含一组包的全面的描述。<strong>OBSERVATIONS：</strong>
<ul>
    <li>不要忘记在名为 Overview.html 的文件中写上包级 Javadoc。该文件应该放在代码文件所在的根目录下。Javadoc 能够挑出该文件并且使用其内容 </li>
</ul>
。 </dd></dl>
<dl compact>
<dt><strong>Package</strong>
<dd>每个包都有一个包含它的类和接口，以及对应摘要的列表的页面。该页包含五类：<strong>Interfaces、Classes、Exceptions、Errors</strong>，和 <strong>Constants。<br />
OBSERVATIONS：</strong>
<ul>
    <li>不要忘记在名为 package.html 的文件中写上包级 Javadoc。该文件应该放在这个包的代码文件所在的目录下。Javadoc 能够挑出该文件并且使用其内容 </li>
</ul>
。 </dd></dl>
<dl compact>
<dt><strong>Class/Interface</strong>
<dd>每个类、接口、内隐类和内隐接口都有其自己单独的页面。这些页面都有三个部分，包括类/接口描述、摘要表，和详细的成员描述：<br />
每个摘要项都包含来自该项的详细描述的第一句话。<br />
摘要项是按字母顺序的，而详细的描述是按照它们出现在源代码中的顺序排的。这保留了程序设计人员建立的逻辑分组。 </dd></dl>
<dl compact>
<dt><strong>Use</strong>
<dd>每个编制了文档的包、类和接口都拥有它自己的 Use 页。该页介绍了什么包、类、方法、构造方法和域使用了已知类或包的任意部分。 </dd></dl>
<dl compact>
<dt><strong>Tree (Class Hierarchy)</strong>
<dd>对于所有包有一个 Tree（Class Hierarchy）页，并且每个包有一个层次。每个层次页包含一列类和一列接口。 </dd></dl>
<dl compact>
<dt><strong>Deprecated</strong>
<dd>Deprecated API 页面列出了全部遭到反对的 API。遭到反对的 API 是不被推荐使用的，一般是由于改进了，并且替换的 API 通常是已知的。遭到反对的 API 可能在将来的实现中被去掉。 </dd></dl>
<dl compact>
<dt><strong>Index</strong>
<dd>Index 包含了所有类、接口、构造函数、方法，和域的字母表。 </dd></dl>
<dl compact>
<dt><strong>Prev/Next</strong>
<dd>这些链接将您带到下一个或前一个类、接口、包，或相关的页。 </dd></dl>
<dl compact>
<dt><strong>Frames/No Frames</strong>
<dd>这些链接显示并隐藏 HTML 框。所有的页都有框或者没有框。 </dd></dl>
<p>&nbsp;</p>
<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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Eclipse_Javadoc_API_reference_structure_generated_using_the_JavaTOC_doclet"><span class="atitle">用 JavaTOC doclet 生成的 Eclipse Javadoc API 参考结构</span></a></p>
<p>结构化的信息方法，例如那些用 XML 写的，使用 Eclipse JavaTOC doclet 和 Javadoc Help 风格，满足了可浏览的和可供搜索的 Java API 参考文档需求。</p>
<p>要使用 Eclipse 帮助插件中的导航，Information Developer（信息开发人员）必须提供 XML 文档格式的内容表（table-of-contents，TOC）。文档左边是可折叠的索引，右边是 HTML 文档。HTML 文件可以用 Javadoc 或 IBM DITA Java API 规范生成。</p>
<p>
<p>您可以手动生成 TOC，或者使用 JavaTOC doclet 自动生成。JavaTOC doclet 为您生成了罗列出包和所包含的类和接口的 Java API 参考 TOC 结构。</p>
<p>要生成 API 参考 HTML 文件，您可以运行 Javadoc 工具或使用 IBM DITA API 规范解决方案来编写并生成 Java API 参考 HTML 文件 —— 图 3。</p>
<br />
<a name="figure3"><strong>图 3. HTML—Kit 编辑器</strong></a><br />
<img height="360" alt="显示 HTML—Kit 编辑器的屏幕抓取" src="http://www.ibm.com/developerworks/cn/rational/07/0320_alupului/eclipse-2.jpg" width="572" /> <br />
<p>如果您使用 JavaTOC doclet，那么 API 参考文档既是可浏览的，又是可供搜索的。搜索能力是可能的，因为使用了结构化的信息方法（XML）。</p>
<p>使用 XML 生成 API 参考文档的结构的一个积极效果是内容将自动索引用于搜索，如果您使用标准的 Javadoc 解决方案来生成内容，那么内容将不会默认索引用于搜索。</p>
<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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Eclipse_Java_API_reference_structure_and_the_TOC generation_necessary_files"><span class="atitle">Eclipse Java API 参考结构和 TOC 生成必要文件</span></a></p>
<p>下面的清单提供了用于生成上面 Java API 参考 TOC 导航结构的 TOC XML 文件的实例。可以手动或利用 JavaTOC doclet 自动生成该文件。参见下面的下载部分，下载 Eclipse 的 Java API 参考 XML TOC 实例。</p>
<p>下面的清单展示了参考一个 TOC XML 文件的 Eclipse Java API 参考插件的实例。</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing6"><strong>清单 6. plug-in.xml</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                &lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;?eclipse version="1.0"?&gt;
                        &lt;plugin&gt;
                        &lt;extension point="org.eclipse.help.toc"&gt;
                        &lt;toc file="doclet.toc.xml" primary="true"/&gt;
                        &lt;/extension&gt;
                        &lt;/plugin&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>下面的清单展示了根据 Java 包结构参考一个以上 TOC XML 文件的 Eclipse Java API 参考插件的实例。当查看该文档时，使用一个 TOC 或多个 TOC XML 文件的方法之间没有什么差别。</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing7"><strong>清单 7. plug-in.xml</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                &lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;?eclipse version="1.0"?&gt;
                        &lt;plugin
                        name = "%Plugin.name"
                        id = "org.dita.dost.user.doc"
                        version = "7.0.1.0"
                        provider-name = "%Plugin.providerName"&gt;
                        &lt;extension point="org.eclipse.help.toc"&gt;
                        &lt;toc file="doclet.toc.xml" primary="true"/&gt;
                        &lt;toc file="org.dita.dost.exception.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.index.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.invoker.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.log.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.module.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.pipeline.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.platform.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.reader.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.util.toc.xml"/&gt;
                        &lt;toc file="org.dita.dost.writer.toc.xml"/&gt;
                        &lt;/extension&gt;
                        &lt;/plugin&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>您可以使用 navref 和 anchor 元素，以及图元素的 anchorref 属性来生成 Eclipse 输出中的集成点，在这些地方接入导航文件，或在运行时附到其本身上。参见 Eclipse 参考资料，了解更多关于编写 Eclipse 导航文件的信息。</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing8"><strong>清单 8. doclet.toc.xml</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                &lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;?NLS TYPE="org.eclipse.help.toc"?&gt;
                        &lt;toc label="Building DITA output"&gt;
                        &lt;topic label="Overview" href="doc\overview-summary.html"&gt;
                        &lt;link toc="org.dita.dost.exception.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.index.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.invoker.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.log.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.module.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.pipeline.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.platform.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.reader.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.util.toc.xml"/&gt;
                        &lt;link toc="org.dita.dost.writer.toc.xml"/&gt;
                        &lt;/topic&gt;
                        &lt;/toc&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>主要的内容的 XML 表必须有一个标题（Eclipse 中的标签），为了加载帮助的内容表。</p>
<p>文件 org.dita.dost.index.toc.xml 是另一个内容表，并且应该与任何其他 toc.xml 文件的格式一样。<br />
</p>
<p>
<table class="new" cellspacing="0" cols="1" cellpadding="5" width="70%" border="1">
    <tbody>
        <tr valign="top" align="left" bgcolor="silver">
            <td valign="top" align="left" width="720" bgcolor="#eeeeee" colspan="5"><br />
            <a name="listing9"><strong>清单 9. org.dita.dost.index.toc.xml</strong></a><br />
            <table cellspacing="0" cellpadding="0" width="100%" border="0">
                <tbody>
                    <tr>
                        <td class="code-outline">
                        <pre class="displaycode">                                &lt;?xml version="1.0" encoding="UTF-8"?&gt;
                        &lt;?NLS TYPE="org.eclipse.help.toc"?&gt;
                        &lt;toc label="org.dita.dost.index Package" link_to="../doclet.toc.xml#java.packages"&gt;
                        &lt;topic label="org.dita.dost.index Package"
                        href="doc/org/dita/dost/index/package-overview.html"&gt;
                        &lt;anchor id="org.dita.dost.index.packages"/&gt;
                        &lt;topic label="IndexTerm" href="doc/org/dita/dost/index/IndexTerm.html"/&gt;
                        topic label="IndexTermCollection"
                        href="doc/org/dita/dost/index/IndexTermCollection.html"/&gt;
                        &lt;topic label="IndexTermTarget" href="doc/org/dita/dost/index/IndexTermTarget.html"/&gt;
                        &lt;topic label="TopicrefElement" href="doc/org/dita/dost/index/TopicrefElement.html"/&gt;
                        &lt;/topic&gt;
                        &lt;/toc&gt;
                        </pre>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br />
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>
<p>
<p>
<p>编辑或向源代码文件添加完新的 API 文档之后，您应该生成文档来确保结果是您所预期的。</p>
<p>在 Eclipse 3.2 中，可以将全部的 doc 插件作为单个的 jar 文件进行加载，它包含要进入 doc.zip 文件的所有文件，以及通常的插件文件：manifest.mf、plug-in.xml、plug-in.properties，等等。在 Eclipse 3.2 之前，所生成的 Javadoc 文件和静态的 HTML 文件，以及扩展点 schema HTML 文件都会放在 doc.zip 文件中。</p>
<p>未编制文档的代码很难或不可能让人理解，不可用，并且难以管理。JavaToc doclet 是有价值的工具。我真的希望本文将帮助您找到在您的项目中使用 JavaToc doclet 的兴趣。</p>
<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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Notices"><span class="atitle">注意</span></a></p>
<p>
<table cellspacing="0" cellpadding="0" width="420" align="right" border="0">
    <tbody>
        <tr>
            <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td>
            <td>
            <table cellspacing="0" cellpadding="5" width="100%" border="1">
                <tbody>
                    <tr>
                        <td bgcolor="#eeeeee"><a name="sidebar6"><strong><span class="bboldcode">&#8220;Simplicity is the soul of efficiency&#8221;。</span> —— Austin Freeman<br />
                        </strong></a><br />
                        <p>
                        <table cellspacing="3" cellpadding="3" width="100%" border="1">
                            <tbody>
                                <tr bgcolor="#dce6dd">
                                    <td>
                                    <p>&#8220;我们生活在当今规范的时代。每个知识领域中可用的信息量如此巨大，以至于为了理解并使用它们，人们必须成为专家。随着可用的材料知识越来越多，就需要更多样化的研究和更多的专家。&#8221;</p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>
<p>
<p>此文档中提供的信息没有受到任何正式的 IBM 测试，并且&#8220;AS IS（按原样）&#8221;分布，在表示或暗示中都没有任何类型的担保。<br />
本文档中介绍的信息的使用或者这些技术的实现是读者的责任，并且依赖于读者评价并集成到它们的操作环境中的能力。<br />
<br />
<br />
</p>
<p><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="middle"><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.ibm.com/developerworks/cn/rational/07/0320_alupului/index.html?ca=j#main"><strong>回页首</strong></a></td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<p><a name="Conclusions"><span class="atitle">结束语</span></a></p>
<p>后面的文章，<strong>Eclipse Java API reference structure generated with JavaTOC doclet</strong> 将介绍利用 JavaTOC doclet 和 Eclipse Plug-in Help 系统自动生成可供搜索的 Java API 参考文档（TOC 导航）的过程。在本系列即将发表的文章中，我们还将更深入地研究 API 文档编写和生成技术，以及一些来自 IBM 的增值的提高，包括 Java DITA API 规范和如何使用它。</p>
<img src ="http://www.blogjava.net/denver/aggbug/162366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/denver/" target="_blank">丹佛儿</a> 2007-11-22 14:03 <a href="http://www.blogjava.net/denver/articles/162366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 Eclipse 3.1 中体验 J2SE 5.0 的新特性: 第三部分 ：范型</title><link>http://www.blogjava.net/denver/articles/162365.html</link><dc:creator>丹佛儿</dc:creator><author>丹佛儿</author><pubDate>Thu, 22 Nov 2007 06:00:00 GMT</pubDate><guid>http://www.blogjava.net/denver/articles/162365.html</guid><wfw:comment>http://www.blogjava.net/denver/comments/162365.html</wfw:comment><comments>http://www.blogjava.net/denver/articles/162365.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/denver/comments/commentRss/162365.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/denver/services/trackbacks/162365.html</trackback:ping><description><![CDATA[<blockquote>本文将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p>J2SE 5.0 (Tiger)的发布是Java语言发展史上的一个重要的里程碑, 是迄今为止在 Java 编程方面所取得的最大进步。</p>
<p>J2SE 5.0提供了很多令人激动的特性。这些特性包括范型(generics)的支持, 枚举类型(enumeration)的支持, 元数据(metadata)的支持, 自动拆箱(unboxing)/装箱(autoboxing), 可变个数参数(varargs), 静态导入(static imports), 以及新的线程架构(Thread framework)。</p>
<p>随着J2SE 5.0的推出, 越来越多的集成开发环境(IDE)支持J2SE 5.0的开发。 著名的开源Java IDE Eclipse从3.1M4开始支持J2SE 5.0的开发, 目前最新的版本是3.1RC4。</p>
<p>本系列将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用。本文将介绍范型。</p>
<p><a name="N1008A"><span class="atitle">3. 范型</span></a></p>
<p><a name="N10090"><span class="smalltitle">3.1范型(Generics)简介</span></a></p>
<p>J2SE 5.0中的最显著的变化之一是添加对泛型类型的支持. 在J2SE 1.4 以及之前的版本中, Java程序并不是类型安全的. 例如, Collection framework中定义的List, Map等容器类的元素都是Object类型, 即这个类包含的元素是Object对象. 使用这种方式实现的列表, 可以用来操作整数, 实数, 字符串或者任何对象类型. 例如</p>
<br />
<a name="N10099"><strong>清单3.1.1 类型不安全的代码示例</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">List stringList = new ArrayList();
            stringList.add("abcde");
            String str = (String)stringList.get(0);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>这种方法实现的列表需要使用强制类型转换(又称显示造型), 因此不是类型安全的. 在上面这段代码种, 虽然变量名为stringList, 但是我们仍然可以把一个整型对象添加到这个队列中, 例如,</p>
<br />
<a name="N100A6"><strong>清单3.1.2 类型不安全的代码示例</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">stringList.add(new Integer(5));
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在这种情况下, 从字符列表中获取对象时, 强制类型转换就会导致运行时异常.</p>
<br />
<a name="N100B3"><strong>清单3.1.3 类型不安全的代码示例</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">String str = (String)stringList.get(1); //runtime exception
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>范型是Java迈向类型安全的一个重要步骤, 使用范型可以构造出类型安全的代码.</p>
<p><a name="N100C0"><span class="smalltitle">3.2声明范型</span></a></p>
<p>所谓范型是指类型参数化(parameterized types). Java是一种强类型的语言, 在J2SE 1.4以及以前的版本中, 我们在定义一个Java类, 接口或者方法的时候, 必须指定变量的类型. 在声明范型类、接口或者函数时, 定义变量的时候不指定某些变量的具体类型, 而是用一个类型参数代替. 在使用这个类, 接口, 或者方法的时候, 这个类型参数由一个具体类型所代替.</p>
<p><strong>3.2.1 范型类</strong></p>
<p>下面的例子中介绍了如何创建一个最简单范型类</p>
<br />
<a name="N100D0"><strong>清单3.2.1, 最简单的范型类</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class GenSample&lt;T&gt; {}
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>类名后面带有&lt;T&gt;表明了这个类是范型类, 其中T被成为类型参数(type parameter), 在使用范型的时候, 类型参数可以被替换为任何的类类型, 但是不能是原始类型(primitive type), 例如int, double. </p>
<p>下面通过一个列表的例子来具体说明如果声明范型类和类型参数的用法.</p>
<br />
<a name="N100E0"><strong>清单3.2.2, 范型列表</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class GenList &lt;T&gt;{
            private T[] elements;
            private int size = 0;
            private int length = 0;
            public GenList(int size) {
            elements = (T[])new Object[size];
            this.size = size;
            }
            public T get(int i) {
            if (i &lt; length) {
            return elements[i];
            }
            return null;
            }
            public void add(T e) {
            if (length &lt; size - 1)
            elements[length++] = e;
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在列表的例子中, 类型参数T被用来表示列表中的元素的类型, 即, 这个列表中的元素是T类型的.</p>
<p>在使用这个列表时, 这个类型参数T会被具体的类型所替代. </p>
<p>注意, 由于T时类型参数不是具体的类, 所以不能使用new操作符创建T的对象,例如new T(), 或者, new T[10].</p>
<p><strong>3.2.2 范型接口</strong></p>
<p>在J2SE 5.0中, 不仅仅可以声明范型类, 也可以声明范型接口, 声明范型接口和声明范型类的语法类似, 也是在接口命称后面加上&lt;T&gt;. 例如,</p>
<br />
<a name="N100FA"><strong>清单3.2.3, 范型接口</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public interface GenInterface&lt;T&gt; {
            void func(T t);
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><strong>3.2.3声明多个类型参数的范型类或者接口</strong></p>
<p>在声明范型类的时候, 可是使用多个类型参数. 多个类型参数之间用逗号分开, 例如,</p>
<br />
<a name="N1010B"><strong>清单3.2.4, 多个类型参数的范型类</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class GenMap&lt;T, V&gt; {}
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>Eclipse 3.1的类创建向导支持创建范型类, 如下图所示,</p>
<br />
<a name="N1011A"><strong>图3.2.1 使用类向导创建范型类</strong></a><br />
<img height="578" alt="图3.2.1 使用类向导创建范型类" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe3/images/image001.jpg" width="496" border="0" /> <br />
<p>使用Eclipse接口向导创建范型接口</p>
<br />
<a name="N1012F"><strong>图3.2.2 使用接口向导创建范型接口</strong></a><br />
<img height="468" alt="图3.2.2 使用接口向导创建范型接口" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe3/images/image003.jpg" width="502" border="0" /> <br />
<p><strong>3.2.4范型方法</strong></p>
<p>类型参数(type parameter)不仅仅可以用来声明范型类或者范型接口, 也可以用来声明范型方法, 而且这种声明的范型方法可以用在非范型类中, 声明范型方法的一般格式是</p>
<br />
<a name="N10146"><strong>清单3.2.5 范型方法的一般形式</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">&lt;type-list&gt; return-type method-name(parameter-list) {}
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N10150"><strong>清单3.2.6 范型方法示例</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public &lt;T&gt; String getString(T obj) {
            return obj.toString();
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><strong>3.2.5 受限范型</strong></p>
<p>受限范型是指类型参数的取值范围是受到限制的. extends关键字不仅仅可以用来声明类的继承关系, 也可以用来声明类型参数(type parameter)的受限关系.例如, 我们只需要一个存放数字的列表, 包括整数(Long, Integer, Short), 实数(Double, Float), 不能用来存放其他类型, 例如字符串(String), 也就是说, 要把类型参数T的取值范型限制在Number极其子类中.在这种情况下, 我们就可以使用extends关键字把类型参数(type parameter)限制为数字,</p>
<br />
<a name="N10161"><strong>清单3.2.7 受限范型示例</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class Limited&lt;T extends Number&gt; {
            public static void main(String[] args) {
            Limited&lt;Integer&gt; number;   //正确
            Limited&lt;String&gt; str;       //编译错误
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在Eclipse 3.1中, 上例中的编译错误信息如下图所示</p>
<br />
<a name="N10170"><strong>图3.2.3 由于受限范型导致的编译错误</strong></a><br />
<img height="286" alt="图3.2.3 由于受限范型导致的编译错误" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe3/images/image005.png" width="565" border="0" /> <br />
<p><a name="N10180"><span class="smalltitle">3.3 在程序中使用范型</span></a></p>
<p><strong>3.3.1在程序中使用范型类</strong></p>
<p>在创建范型类的对象的时候, 和创建普通对象基本类似, 必须提供具体的类类型来替代类型参数T (J2SE 5.0目前不支持原始类型作为类型参数(type parameter)).</p>
<br />
<a name="N1018D"><strong>清单3.3.1, 使用范型类</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">//如果需要整型的列表
            GenList&lt;Integer&gt; integerList = new GenList&lt;Integer&gt;();
            //如果需要字符型的列表
            GenList&lt;String&gt; strList = new GenList&lt;String&gt;();
            //不能使用原始类型
            GenList&lt;int&gt; nList = new GenList&lt;int&gt;();  //编译错误
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><a name="N10197"><span class="smalltitle">3.3.2 使用范型解决类型安全性问题</span></a></p>
<p>使用范型实现的列表是类型安全的, 下列破坏类型安全语句会在编译的时候检查出来。 把鼠标放在错误标记上， Eclipse 3.1中的错误提示就会显示，如下图所示：</p>
<br />
<a name="N101A2"><strong>图3.3.2 破坏类型安全引起的错误</strong></a><br />
<img height="482" alt="图3.3.2 破坏类型安全引起的错误" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe3/images/image007.png" width="567" border="0" /> <br />
<p><strong>3.3.3 二义性错误</strong></p>
<p>GenMap在声明是使用了2个类型参数T和V, 因此在创建GenMap的对象的时候也需要提供2个具体的类类型来替代这2个类型参数, 例如,</p>
<br />
<a name="N101B9"><strong>清单9, 多个参数的范型类</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">GenMap&lt;Integer, String&gt; gm = new GenMap&lt;Integer, String&gt;();
            GenMap&lt;String, String&gt; gm2 = new GenMap&lt;String, String&gt;();
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>上例中, T和V虽然看起来是两个不同的类型参数, 但是在使用这个范型类的时候, T和V很有可能被替换成同一种类型. 因此在声明多个类型参数的范型类时, 要注意避免这种二义性错误, 例如,</p>
<br />
<a name="N101C6"><strong>清单10, 二义性错误</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class GenMap&lt;T, V&gt; {
            //编译错误, 二义性错误
            public void set(T t){}
            public void set(V v){}
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在上面这段代码, 如果T和V被替换成同一种类型, set函数的签名(signature)就是完全一样的, 所以编译器会报告二义性错误. 正确的用法是声明2个不同名的方法, 例如,</p>
<br />
<a name="N101D3"><strong>清单10, 二义性错误</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class GenMap&lt;T, V&gt; {
            public void setKey(T t){}
            public void setValue(V v){}
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N101DF"><strong>图3.3.3 二义性错误</strong></a><br />
<img height="251" alt="图3.3.3 二义性错误" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe3/images/image009.png" width="567" border="0" /> <br />
<p><strong>3.3.4 使用通配符</strong></p>
<p>前面我们创建了范型的列表, 如果我需要一个方法来处理范型列表, 例如, 我们希望把列表中的每个元素都打印出来, 但是类型参数(type parameter)只能使用在声明一个范型类的时候, 如果类型参数使用在函数定义里会导致编译错误</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public static void print(GenList&lt;T&gt; list){}	//编译错误
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在这种情况下, 我们需要用另外一种方法来表示一个范型类, 否则, 就可能需要书写多个print函数</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public static void print(GenList&lt;Integer&gt; list){}
            public static void print(GenList&lt;Double&gt; list){}
            &#8230;
            public static void print(GenList&lt;String&gt; list){}
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>J2SE 5.0中提供了范型的通配符"?", "?"可以用来代替任何类型, 例如使用通配符来实现print方法</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public static void print(GenList&lt;?&gt; list) {}
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><a name="N10217"><span class="smalltitle">3.4. 范型的一些局限型</span></a></p>
<p>(1) 类型参数不能实例化, 例如,</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">T t= new T();   //编译错误
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>(2) 不能实例化类型参数的数组</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">T[] ts= new T[10];   //编译错误
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>(3) 类的静态变量不能声明为类型参数类型</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class GenClass&lt;T&gt; {
            private static T t;    //编译错误
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>(4) 范型类不能继承自Throwable以及其子类</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public GenExpection&lt;T&gt; extends Exception{}    //编译错误
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><a name="N1024D"><span class="smalltitle">3.5.范型小结</span></a></p>
<p>范型是J2SE 5.0所提供的一项强大的功能, 使用范型可以创建类型安全的、可重用的代码, 虽然目前Java的范型还无法和C++的范型相提并论, 但是, 随着Java语言本事的演进, 范型会在Java语言中发挥更大的作用的.</p>
<img src ="http://www.blogjava.net/denver/aggbug/162365.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/denver/" target="_blank">丹佛儿</a> 2007-11-22 14:00 <a href="http://www.blogjava.net/denver/articles/162365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 Eclipse 3.1 中体验 J2SE 5.0 的新特性: 第二部分 ：注释类型</title><link>http://www.blogjava.net/denver/articles/162363.html</link><dc:creator>丹佛儿</dc:creator><author>丹佛儿</author><pubDate>Thu, 22 Nov 2007 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/denver/articles/162363.html</guid><wfw:comment>http://www.blogjava.net/denver/comments/162363.html</wfw:comment><comments>http://www.blogjava.net/denver/articles/162363.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/denver/comments/commentRss/162363.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/denver/services/trackbacks/162363.html</trackback:ping><description><![CDATA[<blockquote>本文将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用。</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p>J2SE 5.0 (Tiger)的发布是Java语言发展史上的一个重要的里程碑, 是迄今为止在 Java 编程方面所取得的最大进步。 </p>
<p>J2SE 5.0提供了很多令人激动的特性。这些特性包括范型(generics)的支持, 枚举类型(enumeration)的支持, 元数据(metadata)的支持, 自动拆箱(unboxing)/装箱(autoboxing), 可变个数参数(varargs), 静态导入(static imports), 以及新的线程架构(Thread framework)。 </p>
<p>随着J2SE 5.0的推出, 越来越多的集成开发环境(IDE)支持J2SE 5.0的开发。 著名的开源Java IDE Eclipse从3.1M4开始支持J2SE 5.0的开发, 目前最新的版本是3.1RC4。</p>
<p>本系列将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用。本文将介绍注释类型。</p>
<p><a name="N1008A"><span class="atitle">2. 注释类型</span></a></p>
<p><a name="N10090"><span class="smalltitle">2.1注释类型简介</span></a></p>
<p>J2SE 5.0提供了很多新的特性。其中的一个很重要的特性，就是对元数据(Metadata)的支持。在J2SE5.0中，这种元数据叫作注释(Annotation)。通过使用注释, 程序开发人员可以在不改变原有逻辑的情况下，在源文件嵌入一些补充的信息。代码分析工具，开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。举个例子，比如说你希望某个方法的参数或者返回值不为空，虽然我们可以在Java doc中说明，但是表达同样意思的说法有很多，比如"The return value should not be null"或者"null is not allowed here"。测试工具很难根据这些语言来分析出程序员所期望的前提条件(Pre-condition)和执行后的条件(Post-condition)。 而使用注释(Annotation)，这个问题就可以轻而易举的解决了。</p>
<p><a name="N10099"><span class="smalltitle">2.2定义注释</span></a></p>
<p>J2SE5.0支持用户自己定义注释。定义注释很简单，注释是由@Interface关键字来声明的。比如下面是一个最简单的注释（Annotation）。</p>
<br />
<a name="N100A2"><strong>清单1一个最简单的注释</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public @interface TODO{}
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>除了定义清单1中的注释以外，我们还可以在注释（Annotation）中加入域定义。方法很简单，不需定义Getter和Setter方法，而只需一个简单的方法，比如：</p>
<br />
<a name="N100AF"><strong>清单2 为注释加入域</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public @interface TODO{
            String priority();
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>定义了这个注释之后，我们在程序中引用就可以使用这个注释了。</p>
<br />
<a name="N100BC"><strong>清单3 使用自定义的注释</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@TODO(
            priority="high"
            )
            public void calculate(){
            //body omission
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>由于TODO中只定义了一个域，使用TODO的时候，可以简写为</p>
<br />
<a name="N100C9"><strong>清单4 单域注释的简写 </strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@TODO("high")
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>类似的，你可以在你的注释（Annotation）类型中定义多个域，也可以为每个域定义缺省值。比如：</p>
<br />
<a name="N100D6"><strong>清单5定义缺省值</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public @interface TODO{
            String priority();
            String owner();
            boolean testable() default true;
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>如果定义了缺省值，在使用的时候可以不用再赋值。比如：</p>
<br />
<a name="N100E3"><strong>清单6使用定义了缺省值的注释</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@TODO(
            priority="high"，
            owner="Catherine"
            )
            public void calculate(){
            //body omission
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在这个例子中，testable用缺省值true。</p>
<p>和上文一样，我们使用Eclipse 3.1作为集成的编译运行环境。Eclipse 3.1提供了向导帮助用户来定义注释。 1．首先我们创建一个Plug-in 项目，com.catherine.lab.annotation.demo。在Package Explorer中选中包package com.catherine.lab.annotation.demo, 2.点击New-&gt;Other-&gt;Java-&gt;Annotation，弹出了下面的对话框。4.输入注释的名称，在这里例子中输入TODO, 点击Finish, 图2中的注释就生成了。</p>
<br />
<a name="N100F5"><strong>图1 创建注释向导</strong></a><br />
<img height="500" alt="图1 创建注释向导" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image001.png" width="556" border="0" /> <br />
<br />
<a name="N10107"><strong>图2 注释向导生成的代码</strong></a><br />
<img height="97" alt="图2 注释向导生成的代码" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image003.png" width="424" border="0" /> <br />
<p><strong>2.2.1注释的类型</strong></p>
<p>从上面的例子中，我们可以看出，按照使用者所需要传入的参数数目， 注释（Annotation）的类型可以分为三种。</p>
<p><em>第一种是标记注释类型：</em></p>
<p>标记注释(Marker)是最简单的注释, 不需要定义任何域。下面要介绍的Override和Deprecated都是标记类型的。当然，如果一个注释类型提供了所有域的缺省值，那么这个注释类型也可以认为是一个注释类型。使用标记类型的语法很简单。</p>
<br />
<a name="N10125"><strong>清单7 标记注释的用法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@MarkerAnnotation
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>第二种是单值注释类型:单值注释类型只有一个域。语法也很简单：</p>
<br />
<a name="N10132"><strong>清单8 单值注释的用法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@SingleValueAnnotation("some value")
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>第三种是全值注释类型。 全注释类型其实并不算是一个真正的类型，只是使用注释类型完整的语法：</p>
<br />
<a name="N1013F"><strong>清单9 全值注释的用法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@MultipleValueAnnotation(
            key1=value1,
            key2=value2,
            key3=value3,
            )
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><strong>2.2.2 J2SE的内建注释(build-in annotation)</strong></p>
<p>在程序中不仅可以使用自己定义的注释，还可以使用J2SE5.0中内建的注释类型。下面我们就详细来介绍J2SE5.0提供的注释类型。J2SE 5.0中预定义了三种注释注释类型：</p>
<p>Override ：java.lang.Override 表示当前的方法重写了父类的某个方法，如果父类的对应的方法并不存在，将会发生编译错误。</p>
<p>Deprecated：java.lang.Deprecated 表示 并不鼓励使用当前的方法或者域变量。</p>
<p>SuppressWarnings: java.lang.SuppressWarnings关闭编译器告警，这样，在编译1.5之前的代码的时候，不会出现大量不关心的无关的告警。 </p>
<p>下面举一个使用Override的例子。Override这个注释类型在使用模板方法（Template Method，图2）非常有用。熟悉设计模式的读者们一定知道，模板方法中通常定义了抽象类，并且这个抽象类中定义了主要的控制流。子类就是通过重写父类中控制流中所调用的方法来实现自己的逻辑。有的时候，父类会将这些方法定义为抽象方法，但是有的时候也会提供缺省实现。在后者的情况下，子类可以不实现这个方法。</p>
<p>这样就带来一个问题，如果你希望在子类中重写这个方法，但是无意中写错了方法的名字，这个错误是很难被发现的。因为你希望重写的这个方法，会被编译器当作一个新的方法而不是重写父类的方法。而现在使用@Override，这个担心就是不必要的。如果你拼错了你希望重写的方法，编译器会报错，告诉你父类没有相应的方法。</p>
<br />
<a name="N10161"><strong>图2 模板方法的类图</strong></a><br />
<img height="225" alt="图2 模板方法的类图" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image005.png" width="413" border="0" /> <br />
<p>清单10给出了模板方法的一个例子。这个例子中有定义了两个类，SubClass和BaseClass。其中SubClass继承了BaseClass，并且希望重写BaseClass的方法doPartII（）。然而SubClass中错误的拼写了这个方法的名称。图3显示了SubClass中的编译错误。熟悉eclipse的读者会看到在编辑器里出现了Error Marker，说明这一行有编译错误。将鼠标指向这行，显示了错误信息。</p>
<br />
<a name="N10174"><strong>清单10 模板方法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public abstract class BaseClass{ //模板方法的基类
            public void doWork(){
            doPartI(); //先调用doPartI()方法
            doPartII();//之后调用doPartII()方法
            }
            public abstract void doPartI();
            public void doPartII(){
            }
            }
            public class SubClass extend BaseClass{
            public void doPartI(){
            };
            @Override
            public void doPortII(){//拼写错误，产生编译错误
            System.out.println("override the method of superclass");
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N10180"><strong>图3 Override应用的例子</strong></a><br />
<img height="495" alt="图3 Override应用的例子" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image007.png" width="800" border="0" /> <br />
<p><strong>2.2.3 注释的注释</strong></p>
<p>值得注意的是，J2SE5.0还提供了四种用于注释的注释类型。有以下的四种：</p>
<p>1. Target：用来指定这个注释（Annotation）是为哪种类型而定义的。比如，这个类型可能只是为method定义的。比如override,不能用@override来修饰class或者field。</p>
<p>比如清单11中定义了一个注释：TODO，而这个注释定义了Target为ElementType.method。因此，TODO只能用来修饰方法，不能用来修饰类或者类变量。图5中给出了一个非法使用TODO的例子。在MyCalculator中，定义了一个布尔型的变量 isReady,如果用TODO来修饰这个类变量的话，会出现编译错误。而用TODO来修饰方法calculateRate()，则不会出现编译错误。这是因为TODO的定义已经规定了，只能用来修饰方法。</p>
<br />
<a name="N1019D"><strong>清单11 Target的用法</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@Target({ElementType.METHOD})
            public @interface TODO {
            int priority() default 0;
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N101A9"><strong>图5 TODO注释的非法使用</strong></a><br />
<img height="347" alt="图5 TODO注释的非法使用" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image009.png" width="655" border="0" /> <br />
<p>2.Retention：Retention的策略可以从以下三种中选取：</p>
<ul>
    <li>RetentionPolicy.SOURCE：编译器编译之后会会从class file中除去注释（Annotation）。
    <li>Retention.CLASS:注释（Annotation）保留在class file中，但是VM不会处理。
    <li>RetentionPolicy.RUNTIME,：注释（Annotation）保留在class file,VM会进行处理。 </li>
</ul>
<p>请注意，如果你希望在运行时查找到这些注释在什么地方被用到，一定要在定义注释的时候，选择RetentionPolicy.RUNTIME,否则即使你用注释修饰了类变量或者方法，在运行时也没有办法获得这个信息的。</p>
<p>3.Documented：这个注释（Annotation）将作为public API的一部分。</p>
<p>4.Inherited ： 假设注释（Annotation）定义的时候使用了Inherited,那么如果这个注释（Annotation）修饰某个class，这个类的子类也被这个注释（Annotation）所修饰。</p>
<p><a name="N101D1"><span class="smalltitle">2.3注释的应用</span></a></p>
<p>下面各小节显示了在哪些情况下可以使用注释以及如何使用注释。　</p>
<p><strong>2.3.1动态查找注释</strong></p>
<p>当我们定义好了注释以后，我们可以开发一些分析工具来解释这些注释。这里通常要用到Java的反射特性。比如说我们希望找到某个对象/方法/域使用了哪些注释，或者获得某个特定的注释，或者判断是否使用某个特定的注释, 我们可以参考下面这个例子。这个例子中定义了两个注释：TODO和TOFORMATE。在MyCalculator类中，TODO用来修饰方法calculateRate，而TOFORMATE用来修饰类变量concurrency和debitDate。而在类TestCalculator的main函数中，通过Java反射特性，我们查找到使用这些注释的类变量和方法。清单12-清单15分别显示这些类的定义。</p>
<br />
<a name="N101E1"><strong>清单12 TODO注释的定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@Target({ElementType.METHOD})
            @Retention(RetentionPolicy.RUNTIME)
            public @interface TODO {
            int priority() default 0;
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N101EB"><strong>清单13 TOFORMATE的定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@Target({ElementType.FIELD})
            @Retention(RetentionPolicy.RUNTIME)
            public @interface TOFORMATE {
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N101F5"><strong>清单14 使用注释的类MyCalculator</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class MyCalculator {
            boolean isReady;
            @TOFORMATE double concurrency;
            @TOFORMATE Date debitDate;
            public MyCalculator() {
            super();
            }
            @TODO
            public void calculateRate(){
            System.out.println("Calculating...");
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N101FF"><strong>清单15动态查找注释</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class TestCalculator {
            public static void main(String[] args) {
            MyCalculator cal = new MyCalculator();
            cal.calculateRate();
            try {
            Class c = cal.getClass();
            Method[] methods = c.getDeclaredMethods();
            for (Method m: methods) {
            // 判断这个方法有没有使用TODO
            if (m.isAnnotationPresent(TODO.class))
            System.out.println("Method "+m.getName()+": the TODO is present");
            }
            Field[] fields = c.getDeclaredFields();
            for (Field f : fields) {
            // 判断这个域有没有使用TOFORMATE
            if (f.isAnnotationPresent(TOFORMATE.class))
            System.out.println("Field "+f.getName()+": the TOFORMATE is present");
            }
            } catch (Exception exc) {
            exc.printStackTrace();
            }
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>下面我们来运行这个例子，这个例子的运行结果如图10所示。</p>
<p>运行结果和我们先前的定义是一致的。在运行时，我们可以获得注释使用的相关信息。</p>
<br />
<a name="N10211"><strong>图6 运行结果</strong></a><br />
<img height="123" alt="图6 运行结果" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image011.png" width="577" border="0" /> <br />
<p>在我们介绍了什么是注释以后，你可能会想知道注释可以应用到什么地方呢？使用注释有什么好处呢？在下面的小节中我们将介绍一个稍复杂的例子。从这个例子中，你将体会到注释所以提供的强大的描述机制（declarative programming）。</p>
<p><strong>2.3.2 使用注释替代Visitor模式</strong></p>
<p>在J2SE 5.0以前，我们在设计应用的时候，我们经常会使用Visitor这个设计模式。Visitor这个模式一般是用于为我们已经设计好了一组类添加方法，而不需要担心改变定义好的类。比如说我们已经定义了好了一组类结构，但是我们希望将这些类的对象部分数据输出到某种格式的文件中。</p>
<p>Vistor模式的实现</p>
<p>使用Vistor模式，首先我们在Employee这个类中加入export方法，export方法如图11所示。Export方法接受Exporter对象作为参数，并在方法体中调用exporter对象的visit()方法。</p>
<br />
<a name="N10233"><strong>图11 使用Vistor模式实现格式输出</strong></a><br />
<img height="337" alt="图11 使用Vistor模式实现格式输出" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image014.gif" width="553" border="0" /> <br />
<p>在这里我们定义了一个Exporter抽象类，我们可以通过继承Exporter类，重写其visit方法来实现不同格式的文件输出。图11种给出visit方法的实现是一个简单的例子。如果要实现输出成XML格式的，可以定义Exporter子类：XMLExporter。如果希望输出成文本的可以定义TXTExporter。但是这样做不够灵活的地方在于，如果Employee加入其他的域变量，那么相应的visitor类也需要进行修改。这就违反了面向对象Open for Extension, close for Modification的原则。</p>
<p>使用注释替代Vistor模式</p>
<p>使用注释（Annotation），也可以完成数据输出的功能。首先定义一个新的注释类型：@Exportable。然后定义一个抽象的解释器ExportableGenerator，将Employee 对象传入解释器。在解释器中，查找哪些域使用了Exportable这个注释（Annotation），将这些域(Field)按照一定格式输出。图12给出了Exportable注释的定义。</p>
<br />
<a name="N1024C"><strong>清单16注释Exportable的定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">@Target({ElementType.FIELD})
            @Retention(RetentionPolicy.RUNTIME)
            @Inherited
            public @interface Exportable {
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>清单17-清单20中给出了包含数据的这些类的定义以及这些类是如何使用注释Exportable的。 图18定义了Main函数，使用ExporterGenerator来产生输出文件。清单21给出了使用注释来实现这一功能的两个类：ExporterGenerator和TXTExporterGenerator。其中ExporterGenerator定义了一个基本的框架。而TXTExporterGenerator继承了ExporterGenerator，并且重写了outputField方法，在这个方法中实现了特定格式的输出。用户可以继承这个ExporterGenerator，并且实现其中的抽象方法来定义自己期望的格式。</p>
<br />
<a name="N10259"><strong>清单17 Employee的类定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public abstract class Employee {
            public abstract String getName();
            public abstract String getEmpNo();
            public Employee() {
            super();
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N10263"><strong>清单18 Regular的类定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class Regular extends Employee{
            @Exportable String name;
            @Exportable String address;
            @Exportable String title;
            @Exportable String phone;
            @Exportable String location;
            @Exportable Date onboardDate;
            @Exportable ArrayList&lt;Employee&gt; team;
            String empNo;
            public Regular(String name, String address, String title, String phone,
            String location, Date date) {
            super();
            this.name = name;
            this.address = address;
            this.title = title;
            this.phone = phone;
            this.location = location;
            onboardDate = date;
            team = new ArrayList&lt;Employee&gt;();
            }
            public void addMemeber(Employee e){
            team.add(e);
            }
            @Override
            public String getName() {
            // TODO Auto-generated method stub
            return name;
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N1026D"><strong>清单19 Vendor的类定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class Vendor extends Employee {
            @Exportable String name;
            @Exportable String company;
            @Exportable String team;
            @Exportable String workingHours;
            String empNo;
            public Vendor(String name, String company, String team, String hours) {
            super();
            this.name = name;
            this.company = company;
            this.team = team;
            workingHours = hours;
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N10277"><strong>清单20 Contractor的类定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class Contractor extends Employee{
            @Exportable String name;
            @Exportable String company;
            @Exportable String contractDuration;
            String empNo;
            public Contractor(String name, String company) {
            super();
            // TODO Auto-generated constructor stub
            this.name = name;
            this.company = company;
            contractDuration ="1";
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N10281"><strong>清单21 Supplemental的类定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class Contractor extends Employee{
            @Exportable String name;
            @Exportable String company;
            @Exportable String contractDuration;
            String empNo;
            public Contractor(String name, String company) {
            super();
            this.name = name;
            this.company = company;
            contractDuration ="1";
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N1028B"><strong>清单22使用ExportableGenerator的程序</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">  public class TestExportable {
            public TestExportable() {
            super();
            }
            public static void main(String[] args) {
            Regular em=new Regular("Catherine","IBM","Software Engineer","82888288","BJ", new Date());
            Employee vn1=new Vendor("Steve","IBM","PVC","8");
            Employee vn2=new Vendor("Steve","IBM","PVC","8");
            Employee ct=new Contractor("Joe","IBM");
            Employee sup=new Supplemental("Linda","IBM","8");
            em.addMemeber(vn1);
            em.addMemeber(vn2);
            em.addMemeber(ct);
            em.addMemeber(sup);
            PrintWriter ps;
            try {
            ps = new PrintWriter(new FileOutputStream(new File("C:\\test.output"),true));
            ExportableGenerator eg=new TXTExportableGenerator(ps);
            eg.genDoc(em,0);
            eg.flush();
            } catch (FileNotFoundException e) {
            e.printStackTrace();
            }
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N10295"><strong>清单23 ExportableGenerator</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">	public abstract class ExportableGenerator {
            PrintWriter out = null;
            public ExportableGenerator(PrintWriter out) {
            super();
            this.out = out;
            }
            public void genDoc(Employee e, int tagNum) {
            Class employee = e.getClass();
            Field[] fields = employee.getDeclaredFields();
            outputFieldHeader(out,e);
            for (Field f : fields) {
            if (f.isAnnotationPresent(Exportable.class)) {
            if (f.getType() != ArrayList.class) {
            for(int i=0; i&lt;tagNum;i++){
            out.print("***");
            }
            outputSimpleField(out, f, e);
            }else{
            try {
            ArrayList team=(ArrayList)f.get(e);
            out.println("-----------------------------");
            for(int i=0;i &lt;team.size();i++){
            Employee member=(Employee)team.get(i);
            genDoc(member,tagNum+1);
            out.println("-----------------------------");
            }
            } catch (IllegalArgumentException e1) {
            e1.printStackTrace();
            } catch (IllegalAccessException e1) {
            e1.printStackTrace();
            }
            }
            }
            }
            outputFieldFooter(out,e);
            }
            public void flush(){
            out.flush();
            out.close();
            }
            protected String value(Field f, Object obj) {
            Class type = f.getType();
            try {
            if (type == String.class)
            return (String) f.get(obj);
            if (type == Date.class) {
            return DateFormat.getDateInstance().format((Date)f.get(obj));
            }
            } catch (IllegalArgumentException e) {
            e.printStackTrace();
            return f.getName();
            } catch (IllegalAccessException e) {
            e.printStackTrace();
            return f.getName();
            }
            return f.getName();
            }
            protected abstract void outputSimpleField(PrintWriter out, Field f,
            Object obj);
            protected abstract void outputFieldHeader(PrintWriter out,Object e);
            protected abstract void outputFieldFooter(PrintWriter out,Object e);
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<br />
<a name="N1029F"><strong>清单24 TXTExportableGenerator</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class TXTExportableGenerator extends ExportableGenerator {
            public TXTExportableGenerator(PrintWriter out) {
            super(out);
            }
            @Override
            protected void outputSimpleField(PrintWriter out, Field f,Object obj) {
            out.print(f.getName());
            out.print("=");
            out.print(value(f,obj));
            out.print(";");
            out.println();
            }
            @Override
            protected void outputFieldHeader(PrintWriter out,Object e) {
            }
            @Override
            protected void outputFieldFooter(PrintWriter out,Object e) {
            //out.println(e.getClass().getName()+":");
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在这个例子中，我们将一个Employee对象的部分内容输出到文件C:\test.output中。图19显示了这个例子的输出结果。</p>
<br />
<a name="N102AE"><strong>图12 输出结果</strong></a><br />
<img height="438" alt="图12  输出结果" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe2/images/image015.png" width="776" border="0" /> <br />
<p>通过这种方法，我们可以动态生成Employee对象的域输出，而不需要在程序中写明要输出哪些确定的域。如果需要更为丰富的格式，我们可以定义多个注释类型。通过对不同注释以及属性的解析，实现格式化的文件输出。</p>
<p><a name="N102C1"><span class="smalltitle">2.4注释类型的小结</span></a></p>
<p>所谓元数据，指的是关于信息的信息。一般而言，代码分析工具，测试工具或者部署工具会使用元数据来产生配置信息以及使用配置信息产生控制逻辑。这些工具通常使用Java的反射特性，重构元数据的信息，并对这些信息进行解释。</p>
<p>新的技术会不断改变程序设计和开发人员的设计思想。那么注释（Annotation）给我们带来了什么呢? 仅仅在代码分析，或者是开发测试框架和部署框架的时候才有用么？ 我认为并不是这样。从上面的例子可以看出，注释（Annotation）的应用范围其实是很广泛的。在我们的应用中充分的利用元数据，可以提高的软件的质量和可维护性。</p>
<img src ="http://www.blogjava.net/denver/aggbug/162363.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/denver/" target="_blank">丹佛儿</a> 2007-11-22 13:57 <a href="http://www.blogjava.net/denver/articles/162363.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在 Eclipse 3.1 中体验 J2SE 5.0 的新特性: 第一部分 ：枚举类型</title><link>http://www.blogjava.net/denver/articles/162357.html</link><dc:creator>丹佛儿</dc:creator><author>丹佛儿</author><pubDate>Thu, 22 Nov 2007 05:38:00 GMT</pubDate><guid>http://www.blogjava.net/denver/articles/162357.html</guid><wfw:comment>http://www.blogjava.net/denver/comments/162357.html</wfw:comment><comments>http://www.blogjava.net/denver/articles/162357.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/denver/comments/commentRss/162357.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/denver/services/trackbacks/162357.html</trackback:ping><description><![CDATA[<blockquote>本文将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用.</blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
<p>J2SE 5.0 (Tiger)的发布是Java语言发展史上的一个重要的里程碑, 是迄今为止在 Java 编程方面所取得的最大进步.</p>
<p>J2SE 5.0提供了很多令人激动的特性.这些特性包括范型(generics)的支持, 枚举类型(enumeration)的支持, 元数据(metadata)的支持, 自动拆箱(unboxing)/装箱(autoboxing), 可变个数参数(varargs), 静态导入(static imports), 以及新的线程架构(Thread framework).</p>
<p>随着J2SE 5.0的推出, 越来越多的集成开发环境(IDE)支持J2SE 5.0的开发. 著名的开源Java IDE Eclipse从3.1M4开始支持J2SE 5.0的开发, 目前最新的版本是3.1RC4.</p>
<p>本系列将介绍J2SE 5.0中三个比较重要的特性: 枚举类型, 注释类型, 范型, 并在此基础上介绍在如何在Eclipse 3.1开发环境中开发枚举类型, 注释类型和范型应用.本文将介绍枚举类型.</p>
<p><a name="N1008A"><span class="atitle">1. 枚举类型</span></a></p>
<p><a name="N10090"><span class="smalltitle">1.1枚举类型简介</span></a></p>
<p>J2SE 5.0 以及之前的JDK有两种基本方法可以来定义新类型：通过Classes 以及Interface. 对于大部分面向对象编程来说，这两种方法看起来似乎足够了.但是在一些特殊情况下，这些方法就不适合.例如，我们想定义一个类型 Priority， 它只能接受 High, Medium, Low 三种值. 其他任何值都是非法的.J2SE 5.0 以前的JDK是可以构造这种类型的，但是需要做很多工作，有可能会带来如不安全(类型安全性问题???)等潜在问题，而J2SE 5.0的枚举类型（Enum） 能避免这些问题.</p>
<p>Eclipse 是JAVA程序员最常用的开发平台，而Eclipse 3.1提供对J2SE 5.0的支持，它为J2SE 5.0的新功能提供了帮助工具.在对枚举类型的支持上，它不仅提供了枚举类型的创建模板，而且为枚举类型的各种开发错误提供错误提示及帮助修改.</p>
<p>本文首先介绍枚举类型的创建基本概念以及如何在Eclipse 3.1平台上创建枚举类型，然后我们通过在Eclipse 3.1开发环境中的例子来说明枚举类型的应用.</p>
<p><a name="N1009F"><span class="smalltitle">1.2 创建枚举类型</span></a></p>
<p>下面的例子显示了如何创建一个最基本的枚举类型：</p>
<br />
<a name="N100A8"><strong>清单 1. 枚举类型的定义</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public enum Priority {High, Medium, Low };
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>它包括一个关键字enum　，一个新枚举类型的名字 Priority 以及为Priority定义的一组值.</p>
<p>在Eclipse 3.1平台上，按照下面步骤来生成枚举类型：(Eclipse 3.1提供了一个新的枚举类型创建向导(wizard)以方便用户创建枚举类型)</p>
<p>1) File-&gt;New-&gt;Other, 模板列表显示出来.</p>
<p>2) 在模板列表上选中 Java-&gt;Enum, 点击 Next 按钮</p>
<p>3) 按图 1填写每一个域 如下:</p>
<br />
<a name="N100C3"><strong>图 1: Eclipse 3.1 枚举类型创建模板</strong></a><br />
<img height="458" alt="图 1: Eclipse 3.1 枚举类型创建模板" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image001.png" width="556" border="0" /> <br />
<p>4) 点击 Finish 按钮, 生成Priority 的类(定义???), 并声明Priority 的每一个值,如下图 2所示:(High, Medium, low从何而来???)</p>
<br />
<a name="N100D8"><strong>图 2: 枚举类型Priority</strong></a><br />
<img height="418" alt="图 2: 枚举类型Priority" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image003.png" width="601" border="0" /> <br />
<p>在创建枚举类型时，注意几个重要的概念.</p>
<ul>
    <li>
    <p>所有创建的枚举类型都扩展于 java.lang.Enum. Enum 是在J2SE 5.0 里定义的一个新类， 它本身不是枚举类型.在创建枚举类型时，必须用enum 关键字，不能直接地定义一个继承Enum的类来创建一个枚举类型，尽管所有创建的枚举类型实际上都是Enum 的子类. 如果直接继承Enum， compiler 就会报错(会导致编译错误).如图3 所示</p>
    <br />
    <a name="N100F4"><strong>图3. 直接继承Enum 类</strong></a><br />
    <img height="359" alt="图3. 直接继承Enum 类" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image005.png" width="643" border="0" /> <br />
    <li>
    <p>枚举类型里定义的每一个值都是枚举类型的一个实例,比方说High是Priority的一个实例.枚举类型又是扩展于Enum. 所以枚举类型的每一个值声明时， 缺省时都将映射到Enum(String name, int ordinal) 构造函数中.换句话说，enum Priority {High, Medium, Low } 的实现是调用了下面的Enum 构造函数：</p>
    <br />
    清单2 映射的构造函数调用<br />
    <table cellspacing="0" cellpadding="0" width="100%" border="0">
        <tbody>
            <tr>
                <td class="code-outline">
                <pre class="displaycode">  new Enum&lt; Priority &gt;("High", 0);
                new Enum&lt; Priority &gt;("Medium", 1);
                new Enum&lt; Priority &gt;("Low", 2);
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <p>每一个创建的枚举类型都是Enum 的子类，除了上面调用父类 Enum 的构造函数外，枚举类型可以使用参数为定义一些自己的构造函数.当声明值时，只需调用此枚举类型定义的构造函数，而且不必添加 new 关键字.在清单3里， Priority 的一个实例生成，这个实例就是High （38）.</p>
    <br />
    清单3.其它构造函数调用<br />
    <table cellspacing="0" cellpadding="0" width="100%" border="0">
        <tbody>
            <tr>
                <td class="code-outline">
                <pre class="displaycode"> enum Priority {
                High (38),
                Medium(36.5),
                Low (5.2);
                double temperature;
                Priority (double p)
                temperature = p;
                }
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <p>另外要强调的两点: 一是这些枚举类型的构造函数都是私有的.它是不能被其它的类或者其它的枚举类型调用的. 而且这个私有修饰符是由编译器自动加的,如果我们定义这些构造函数时,在前面加上public 修饰符, 就会导致编译错误, 如下图5所示. 二是变量定义必须在枚举类型值定义之后. 上图中double temperature 必须在枚举类型值定义完了(分号表示枚举类型值定义完了， 如 Low(5.2);) 才能声明.</p>
    <br />
    <a name="N10122"><strong>图4. 枚举类型的构造函数是私有的</strong></a><br />
    <img height="463" alt="图5. 枚举类型的构造函数是私有的" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image007.png" width="800" border="0" /> <br />
    <li>
    <p>在J2SE 5.0以前，当我们实现一个枚举类时，一般都是把一个整数关联到此枚举类的某一个值的名字，出现的问题是同一个整数可以代表不同枚举类的值. 下面的例子里定义两个枚举类 Course and Grade 如下：</p>
    <br />
    清单4.<br />
    <table cellspacing="0" cellpadding="0" width="100%" border="0">
        <tbody>
            <tr>
                <td class="code-outline">
                <pre class="displaycode">public class Course {
                public static final int EnglishLit       = 1;
                public static final int Calculus         = 2;
                public static final int MusicTheory      = 3;
                public static final int MusicPerformance = 4;
                }
                public class Grade {
                public static final int A = 1;
                public static final int B = 2;
                public static final int C = 3;
                public static final int D = 4;
                public static final int F = 5;
                public static final int INCOMPLETE = 6;
                }
                </pre>
                </td>
            </tr>
        </tbody>
    </table>
    <br />
    <p>如果开发者误把student1.assignGrade(Grade.A)写成student1.assignGrade(Course.EnglishList);　在编译 阶段是不能发现问题的，如果用J2SE 5.0 枚举类型（enum）可以避免这些问题.</p>
    <li>枚举类型每一个值都是public, static and final的.也就是说，这些值是唯一的而且一旦定义了是不能被重写或修改.而且尽管在枚举类型每一个值声明时没有出现static关键字， 实际上值都是静态的, 而且我们不能在值前面加上static, public，final 修饰符,否则就会出现下图 6的错误. <br />
    <a name="N10148"><strong>图5 枚举类型值的错误声明</strong></a><br />
    <img height="431" alt="图6 枚举类型值的错误声明" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image009.png" width="800" border="0" /> <br />
    <li>枚举类型都实现了java.lang.Comparable，枚举类型的值是可以比较排序的，排列顺序就是枚举类型定义这些值的顺序. </li>
</ul>
<p><a name="N1015D"><span class="smalltitle">1.3 枚举类型的应用</span></a></p>
<p>下面各小节介绍了枚举类型的各种应用.</p>
　
<p><strong>1.3.1循环（Iteration）</strong> </p>
<p>当我们写程序时，常常遇到对数组或列表里的每一个对象进行处理的情况.在J2SE 5.0以前，如果要在一个数组或列表里进行轮循时，我们的做法比较繁琐，需要借助java.util.Iterator 类， 如下所示：</p>
<br />
<a name="N1016F"><strong>清单5：</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">List priorities = Priority.values().;
            for (Iterator iter = priorities.iterator(); iter.hasNext();) {
            Priority p = (Priority) iter.next();
            process(p);
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>现在我们可以通过J2SE 5.0 的for/in loop和枚举类型一起使用. 这能使以前花很多时间写的程序简单化，如上面清单5的程序可简化为：</p>
<br />
<a name="N1017C"><strong>清单6：</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">for (Priority g: Priority.values()){
            process(g);
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>我们把上面的伪代码写成程序在Eclipse3.1上运行，如下图所示，在右下控制平台视图里显示了运行结果.如果看不见控制平台，点击Window-&gt;Other Views-&gt;Console, 控制平台就会出现在右下角. </p>
<br />
<a name="N1018B"><strong>图6 枚举类型在循环中的应用</strong></a><br />
<img height="503" alt="图7 枚举类型在循环中的应用" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image011.png" width="663" border="0" /> <br />
<p>我们在使用for/in loop 时要求它的表达式要求必须是数组或者是实现了java.lang.Iterable的集合，而枚举类型的values()函数返回的就是一个数组.另外循环变量的声明必须是在loop里, 包括变量类型和变量名.</p>
<p>我们不能在循环里使用一个在循环之外声明的变量.这和J2SE 5.0以前for loop 里用的循环变量的声明不同.</p>
<p><strong>1.3.2 转换（Switch）</strong> </p>
<p>我们常用的一种判断语句就是Switch-case 语句. 在Switch 语句中使用枚举类型，不仅能简化程序，而且增强了程序的可读性.</p>
<br />
<a name="N101AA"><strong>清单8.</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">File1: Task.java
            public class Task {
            Priority myPriority;
            public Task (Priority p) {
            myPriority=p;
            }
            public Priority getPriority(){
            return myPriority;
            }}
            File2: TestSwitch.java
            public class TestSwitch (
            Task task = new Task(Priority.Medium);
            switch (task.getPriority( )) {
            case High:
            //do case High
            break;
            case Midum: // fall through to Low
            case Low:
            //do case Low
            break;
            default: throw new AssertionError("Unexpected enumerated value!");
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>在Switch语句里使用枚举类型时，一定不能在每一个枚举类型值的前面加上枚举类型的类名，否则编译器就会报错(会导致编译错误???). 我们把上面的程序稍作修改，在case 语句里加上枚举类型的类名并运行在Eclipse 3.1 平台上. 我们发现Eclipse 的问题视图里提示case 语句里枚举类型值的前面加上枚举类型的类名是错误的， 如下图8所示.</p>
<br />
<a name="N101B9"><strong>图7: case 语句里枚举类型的值</strong></a><br />
<img height="419" alt="图8: case 语句里枚举类型的值" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image013.png" width="884" border="0" /> <br />
<p>原因是J2SE 5.0的实现要求case 语句里每一个枚举类型值是不能有枚举类型类作为前缀的.前面谈到过每一个枚举类型的值都是枚举类型的一个实例.那么当编译器编译case语句时, 是如何处理这些实例的? 这有两种情况：如果switch 与枚举类型定义在同一个编译单元, 第一次编译时一个新表会创建在内存里. 在这个表里, 每一个枚举类型的值都和它在枚举类型里定义的顺序关联起来. 编译器编译结果就和下面清单9显示的的程序很像.只不过顺序号没有加到程序里, 而是编译器在表里快速查询. 如果枚举类型被修改或从定义,表会被更新.</p>
<br />
<a name="N101CC"><strong>清单 9:</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class TestSwitch (
            Task task = new Task();
            switch (task.getPriority( )) {
            case 0:
            //do case High
            break;
            case 1: // fall through to Low
            case 2:
            //do case Low
            break;
            default: throw new AssertionError("Unexpected enumerated value!");
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>还有一种经常出现的情况是 switch 与枚举类型定义不是在同一个编译单元.在这种情况下, 大多数编译器就会把switch-case 语句翻译成一系列的if/else 语句:</p>
<br />
<a name="N101D9"><strong>清单 10:</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">Priority tmp = task.getPriority( );
            if (tmp == High)
            //do case High
            else if (tmp == Midium)
            else if (tmp == Low)
            //do case Low
            else {
            throw new AssertionError("Unexpected enumerated value!");
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p><strong>1.3.3 Maps of Enum and Sets of Enum </strong></p>
<p>在J2SE 5.0 的java.util 程序包中提供两个新类：EnumMap 和 EnumSet，这两个类与枚举类型的结合应用可使以前非常繁琐的程序变得简单方便.EnumMap 类提供了java.util.Map 接口的一个特殊实现，该接口中的键（key）是一个枚举类型.</p>
<br />
<a name="N101EC"><strong>清单 11:. EnumMap 例子 </strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public void test() throws IOException {
            EnumMap&lt;Priority, String&gt; descriptionMessages =
            new EnumMap&lt; Priority, String&gt;( Priority.class);
            descriptionMessages.put(Priority.High,   "High means ...");
            descriptionMessages.put(Priority.Medium,  " Medium represents...");
            descriptionMessages.put(Priority.Low, " Low means...");
            for (Priority p : Priority.values( ) ) {
            System.out.println("For priority " + p + ", decription is: " +
            descriptionMessages.get(p));
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>EnumSet 类提供了 java.util.Set 接口的实现，该接口保存了某种枚举类型的值的集合.EnumSet的作用类似于特性的集合，或者类似于某个枚举类型的所有元素的值的子集.EnumSet 类拥有一系列的静态方法，可以用这些方法从枚举类型中获取单个元素或某些元素， 下面的程序例子显示如何这些静态方法： </p>
<br />
<a name="N101F9"><strong>清单 12:.EnumSet 例子</strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">  public class TestEnumSet {
            public enum ColorFeature {
            RED,BLUE, GREEN, YELLOW,BLACK
            } ;
            public static void main(String[] args) {
            EnumSet allFeatures = EnumSet.allOf(ColorFeature.class);
            EnumSet warmColorFeatures = EnumSet.of(ColorFeature.RED,
            ColorFeature.YELLOW);
            EnumSet non_warmColorFeatures = EnumSet.complementOf(warmColorFeatures);
            EnumSet notBlack = EnumSet.range(ColorFeature.RED, ColorFeature.YELLOW);
            for (ColorFeature cf : ColorFeature.values()){
            if (warmColorFeatures.contains(cf)) {
            System.out.println("warmColor "+cf.name());
            }
            if (non_warmColorFeatures.contains(cf)) {
            System.out.println("non_WarmColor "+cf.name());
            }
            }
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>我们在Eclipse3.1环境中运行上面的程序，结果如下图：</p>
<br />
<a name="N10208"><strong>图8: EnumSet 样例运行结果</strong></a><br />
<img height="166" alt="图9: EnumSet 样例运行结果" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image015.png" width="766" border="0" /> <br />
<strong>1.3.4 枚举类型的函数定义</strong>
<p>在介绍创建枚举类型中曾提到枚举类型都是java.lang.Enum的子类. 也就是说, 枚举类型都是可编译的Java 的类，那么就可以在枚举类型里添加构造函数和其它函数，如清单13里的getDescription（）</p>
<br />
<a name="N1021E"><strong>清单 13: </strong></a><br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">        public enum ColorFeature {
            RED(0),
            BLUE(0),
            GREEN(300),
            YELLOW(0),
            BLACK(0);
            /** The degree for each kind of color*/
            private int degree;
            ColorFeatures(int degree) {
            this.degree = degree;
            }
            public int getDegree( ) {
            return degree;
            }
            public String getDescription( ) {
            switch(this) {
            case RED:       return "the color is red";
            case BLUE:      return "the color is blue";
            case GREEN:     return "the color is green";
            case BLACK:     return "the color is black";
            case YELLOW:    return "the color is yellow"
            default:        return "Unknown Color";
            }
            }}
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>枚举类型的函数定义的应用是很有用的， 例如可以让多个枚举类型实现同一个interface 来达到程序设计的模式化. 例如一个定义了getDescription （）接口的interface,让有同样需求的不同枚举类型来实现它.上面的colorFeature 可以实现它, 另一个FontFeature也可以实现它.</p>
<p><strong>1.3.5 特定于常量的类主体</strong> </p>
<p>在上一节里提到枚举类型可以定义自己的函数，其实更进一步，枚举类型的每一个值都可以实现枚举类型里定义的抽象函数，这听起来很不可思议，我们可以先看下面的例子.</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public enum Priority implements Feature {
            High (38) {
            public void perform() {
            System.out.println("high 38");
            }
            },
            Medium(36.5) {
            public void perform() {
            System.out.println("medium 36.5");
            }
            },
            Low (5.2){
            public void perform() {
            System.out.println("low 5.2");
            }
            };
            public abstract void perform();
            public String getDescription(Priority p) {
            return null;
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>枚举类型Priority 定义了一个抽象函数perform()，Priority的每一个值都对perform 函数实现了重载，这就是枚举类型的特定于常量的类主体.在这种情况下，每声明一个值，枚举类型的一个子类生成，然后生成这个子类的唯一的实例来表示这个值.不同的值，就有对应的不同的子类.每个子类可以对父类的抽象函数进行重载.我们可以用下面的程序在Eclipse3.1环境中运行来证明此时3个子类生成.</p>
<br />
<table cellspacing="0" cellpadding="0" width="100%" border="0">
    <tbody>
        <tr>
            <td class="code-outline">
            <pre class="displaycode">public class Task {
            Priority myPriority;
            public Task (Priority p) {
            myPriority=p;
            }
            public Priority getPriority(){
            return myPriority;
            }
            public void test() throws IOException {
            if (myPriority == Priority.High)
            System.out.println(Priority.High.getClass().getName());
            if (myPriority == Priority.Medium)
            System.out.println(Priority.Medium.getClass().getName());
            if (myPriority == Priority.Low)
            System.out.println(Priority.Low.getClass().getName());
            }}
            public class TestSwitch {
            public static void main(String[] args) {
            Task task = new Task(Priority.High);
            Task task1 = new Task(Priority.Medium);
            Task task2 = new Task(Priority.Low);
            try {
            task.test();
            task1.test();
            task2.test();
            } catch (IOException e) {
            e.printStackTrace();
            }
            }
            </pre>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>运行结果如下图10.</p>
<br />
<a name="N1024E"><strong>图9 测试特定于常量的类主体运行结果</strong></a><br />
<img height="90" alt="图10 测试特定于常量的类主体运行结果" src="http://www.ibm.com/developerworks/cn/java/j-tiger-eclispe1/images/image017.png" width="680" border="0" /> <br />
<p>由于特定于常量的类主体难理解容易出错，它的应用比较少，大多数情况下可以用switch-case 语句替代. 在这里简单介绍，仅供参考.</p>
<p><a name="N10261"><span class="smalltitle">1.4 枚举类型的小结</span></a></p>
<p>使用枚举类型是很简单的.它定义一个固定的、封闭的值集合，然后，在需要这些值中的某一个值时，可以通过它的名称来指定它，这就是枚举类型的简单性.枚举类型的值就是枚举类型的实例，编译器会确保没有传入其他的类型，这就是枚举类型的安全性.这些枚举类型就是类本身，因此，可以对类进行的所有操作同样可以作用于枚举类型上.我们要小心使用构造函数和函数重载方法，不要因为这些特性可用就任意使用它们.比如特定于常量的类主体，大多情况下可以用Switch语句来代替，更容易让人理解而且不容易出错.我们也看到了Eclipse 3.1平台对枚举类型的支持，包括提供创建模板，错误信息提示等.总之，枚举类型的灵活应用能极大的方便和简化了我们的开发工作.</p>
<img src ="http://www.blogjava.net/denver/aggbug/162357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/denver/" target="_blank">丹佛儿</a> 2007-11-22 13:38 <a href="http://www.blogjava.net/denver/articles/162357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2SE 5.0新特性之static import</title><link>http://www.blogjava.net/denver/articles/162340.html</link><dc:creator>丹佛儿</dc:creator><author>丹佛儿</author><pubDate>Thu, 22 Nov 2007 04:38:00 GMT</pubDate><guid>http://www.blogjava.net/denver/articles/162340.html</guid><wfw:comment>http://www.blogjava.net/denver/comments/162340.html</wfw:comment><comments>http://www.blogjava.net/denver/articles/162340.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/denver/comments/commentRss/162340.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/denver/services/trackbacks/162340.html</trackback:ping><description><![CDATA[<p>在<a href="http://www.qqread.com/z/netprogram/J2SE/index.html" target="_blank">J2SE</a> 5.0版本中，<a href="http://www.qqread.com/keys/java/index.html" target="_blank">java</a>语言引入了很多新的特性，本文将主要介绍static import。static import主要解决的问题是方便<nobr oncontextmenu="return false;" onmousemove="kwM(1);" id="key1" onmouseover="kwE(event,1, this);" style="color: #6600ff; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">开发</nobr>人员创建和使用全局的常量以及静态的方法。要使用这一新的特性您应该首先从<nobr oncontextmenu="return false;" onmousemove="kwM(0);" id="key0" onmouseover="kwE(event,0, this);" style="color: #6600ff; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">java</nobr>.sun.com下载最新的j2sdk 5.0。 </p>
<div id="w_hzh">&nbsp; 在《effective java》中作者曾经谈到在接口中定义常量是很糟糕的一种使用方法，我们应该始终使用接口来定义类型。但是在实际开发<nobr oncontextmenu="return false;" onmousemove="kwM(3);" id="key3" onmouseover="kwE(event,3, this);" style="color: #6600ff; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">工作</nobr>中还是有很多人这样使用接口，他们这样做的原因是这样定义常量使用起来很方便。例如如下定义方式：<br />
&nbsp;&nbsp; public interface BadIrrationalConstants {<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double SQRT_TWO = 1.414;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double SQRT_THREE = 1.732;<br />
&nbsp;&nbsp; }</div>
<p>&nbsp;public interface BadTranscendentalConstants {<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double PI = 3.14159;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double E = 2.71828;<br />
&nbsp;&nbsp; }<br />
如果你想在自己的类中使用这些接口中定义的常量的时候，那么你必须要实现这些接口。比如<br />
&nbsp;public class BadUseOfConstants implements<br />
&nbsp;&nbsp;&nbsp;&nbsp; BadTranscendentalConstants, BadIrrationalConstants {</p>
<p>&nbsp;&nbsp;&nbsp; public static double sinPiOverFour() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SQRT_TWO / 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Pi is approximately " + PI);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("The sin of Pi/4 is about " +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sinPiOverFour());<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
这样这些常量就变成你的类的一部分了，如果这个类不是final的话，其它的类继承了这个类又使得它继承了这些常量，但是这也许不是用户需要的结果。</p>
<p>&nbsp;&nbsp;&nbsp; 针对这样的情况，我们可以这样做，那就是在一个类中定义这些常量，使用的时候可以通过ClassName.variableName来访问他们。例如<br />
package staticEx;</p>
<p>&nbsp;&nbsp; public class IrrationalConstants {<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double SQRT_TWO = 1.414;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double SQRT_THREE = 1.732;<br />
&nbsp;&nbsp; }<br />
package staticEx;<br />
<br />
&nbsp;&nbsp; public class TranscendentalConstants {<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double PI = 3.14159;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double E = 2.71828;<br />
&nbsp;&nbsp; }<br />
现在J2SE 5.0提供了静态导入的<nobr oncontextmenu="return false;" onmousemove="kwM(2);" id="key2" onmouseover="kwE(event,2, this);" style="color: #6600ff; border-bottom: 0px dotted; background-color: transparent; text-decoration: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">功能</nobr>，你只需要在import关键字后面写一个static关键字就可以直接使用类中定义的常量了，例如<br />
&nbsp;&nbsp; import static staticEx.IrrationalConstants.SQRT_TWO;<br />
&nbsp;&nbsp; import static staticEx.IrrationalConstants.SQRT_THREE;<br />
&nbsp;&nbsp; import static staticEx.TranscendentalConstants.PI;<br />
当然你也可以使用.*的格式，例如<br />
import static staticEx.IrrationalConstants.*；的格式<br />
&nbsp;&nbsp;<br />
package staticEx;<br />
<br />
&nbsp;&nbsp; import static staticEx.IrrationalConstants.SQRT_TWO;<br />
&nbsp;&nbsp; import static staticEx.IrrationalConstants.SQRT_THREE;<br />
&nbsp;&nbsp; import static staticEx.TranscendentalConstants.PI;<br />
<br />
&nbsp;&nbsp; public class ConstantsWithStaticImport {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static double sinPiOverFour() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SQRT_TWO / 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Pi is approximately " + PI);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("The sin of Pi/4 is about " +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sinPiOverFour());<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
运行该程序会得到<br />
&nbsp;&nbsp; Pi is approximately 3.14159<br />
&nbsp;&nbsp; The sin of Pi/4 is about 0.707<br />
在这里提醒大家一下，如果你过多的使用.*的样式，那么可能会给程序的可读性带来负面的影响。因为你很难看出这个变量在哪里定义的。</p>
<p>&nbsp;&nbsp;&nbsp; 对常量定义是如此，对静态方法的使用也适用。例如下面的例子<br />
&nbsp; package staticEx;<br />
<br />
&nbsp;&nbsp; public class IrrationalConstants2 {<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double SQRT_TWO = 1.414;<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static final double SQRT_THREE = 1.732;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static double sinPiOverFour() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return SQRT_TWO / 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
package staticEx;<br />
<br />
&nbsp;&nbsp; import static staticEx.IrrationalConstants2.*;<br />
&nbsp;&nbsp; import static staticEx.TranscendentalConstants.*;<br />
<br />
&nbsp;&nbsp; public class ConstantsWithStaticImport2 {<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Pi is approximately " + PI);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("The sin of Pi/4 is about " +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sinPiOverFour());<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
在ConstantsWithStaticImport2类中静态导入IrrationalConstants2后就可以直接使用它的静态方法sinPiOverFour()了。</p>
<p>&nbsp;&nbsp;&nbsp; 以上简单的介绍了如何使用static import，您可以参考一下连接获得更多的介绍：<br />
http://java.sun.com/developer/JDCTechTips/2004/tt1005.html<br />
http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html</p>
 <img src ="http://www.blogjava.net/denver/aggbug/162340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/denver/" target="_blank">丹佛儿</a> 2007-11-22 12:38 <a href="http://www.blogjava.net/denver/articles/162340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>