<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>bulargy</title>
    <description></description>
    <link>http://bulargy.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>JSP、Servlet、Tomcat、JDK、J2EE版本比较</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/209858" style="color:red;">http://bulargy.javaeye.com/blog/209858</a>&nbsp;
          发表时间: 2008年06月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一 JSP2.0与JSP1.2比较<br />JSP 2.0是对JSP 1.2的升级，新增功能：<br />1. Expression Language<br /><br />2. 新增Simple Tag和Tag File<br /><br />3.web.xml新增&lt;jsp:config>元素<br /><br />特别说明web.xml.<br />web.xml新增&lt;jsp:config>元素<br /><br />&lt;jsp-config> 元素主要用来设定JSP相关配置，&lt;jsp-config> 包括&lt;taglib>和&lt;jsp-property-group><br />子元素。<br /><br />(1)其中&lt;taglib>以前的Jsp1.2中就有的,taglib主要作用是作为页面taglib标签中的uri和tld文件的一个映射关系<br /><br />(2)其中&lt;jsp-property-group>是JSP2.0种新增的元素。<br />&lt;jsp-property-group> 主要包括8个子元素，它们分别是：<br /><br />&lt;jsp-property-group><br /><br />&lt;description><br />设定的说明<br />&lt;/description><br /><br />&lt;display-name>设定名称&lt;/display-name><br /><br />&lt;url-pattern>设定值所影响的范围&lt;/url-pattern><br /><br />&lt;el-ignored>若为true则不支持EL语法&lt;／el-ignored><br /><br />&lt;page-encoding>ISO-8859-1&lt;/page-encoding><br /><br />&lt;scripting-invalid> 若为true则不支持&lt;% scripting%> 语法&lt;/scripting-invalid><br /><br />&lt;include-prelude>设置JSP网页的抬头,扩展名为.jspf &lt;/include-prelude><br /><br />&lt;include-coda>设置JSP网页的结尾,扩展名为.jspf&lt;/include-coda><br /><br />&lt;/jsp-property-group><br /><br />例如: 其中抬头程序:<br />prelude.jspf<br />&lt;br><br />&lt;center><br />文本内容<br />&lt;/center><br />&lt;hr><br /><br />结尾程序:<br />coda.jspf<br />&lt;br><br />&lt;center><br />文本内容<br />&lt;/center><br />&lt;hr><br /><br />二、Servlet个版本比较<br />servlet 2.3 新增功能:<br />2000年10月份出来<br />Servlet API 2.3中最重大的改变是增加了filters<br /><br /><br />servlet 2.4 新增功能:<br />2003年11月份出来<br />1、web.xml DTD改用了XML Schema;<br /><br />Servlet 2.3之前的版本使用DTD作为部署描述文件的定义，其web.xml的格式为如下所示：<br /><br />&lt;?xml version="1.0" encoding="IS0-8859-1"?><br />&lt;!DOCTYPE web-app<br />PUBLIC "-//sunMicrosystems,Inc.//DTD WebApplication 2.3f//EN"<br />"http://java.sun.com/j2ee/dtds/web-app_2.3.dtd"><br />&lt;web-app><br />.......<br />&lt;/web-app><br /><br />Servlet 2.4版首次使用XML Schema定义作为部署描述文件，这样Web容器更容易校验web.xml语法。同时XML Schema提供了更好的扩充性，其web.xml中的格式如下所示：<br /><br />&lt;?xml version="1.0" encoding="UTF-8"?><br />&lt;web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"<br />xmlns:workflow="http://www.workflow.com"<br />xmins:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee<br />http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><br />.........<br />&lt;/web-app><br /><br />注意: 改为Schema后主要加强了两项功能:<br />(1) 元素不依照顺序设定<br />(2) 更强大的验证机制<br />主要体现在:<br />a.检查元素的值是否为合法的值<br />b.检查元素的值是否为合法的文字字符或者数字字符<br />c.检查Servlet,Filter,EJB-ref等等元素的名称是否唯一<br />2.新增Filter四种设定：REQUEST、FORWARD、INCLUDE和ERROR。<br />3.新增Request Listener、Event和Request Attribute Listener、Enent。<br />4.取消SingleThreadModel接口。当Servlet实现SingleThreadModel接口时，它能确保同时间内，只能有一个thread执行此Servlet。<br />5.&lt;welcome-file-list>可以为Servlet。<br />6.ServletRequest接口新增一些方法。<br />public String getLocalName()<br />public String getLocalAddr()<br />public int getLocalPort()<br />public int getRemotePort()<br /><br /><br />Servlet 2.5的新特征<br />2005年9月发布Servlet 2.5<br />Servlet2.5一些变化的介绍：<br />1） 基于最新的J2SE 5.0开发的。<br />2） 支持annotations 。<br />3） web.xml中的几处配置更加方便。<br />4） 去除了少数的限制。<br />5） 优化了一些实例<br /><br /><br />servlet的各个版本对监听器的变化有：<br />(1)servlet2.2和jsp1.1<br />新增Listener:HttpSessionBindingListener<br />新增Event: HttpSessionBindingEvent<br />(2)servlet2.3和jsp1.2<br />新增Listener:ServletContextListener,ServletContextAttributeListener<br />,HttpSessionListener,HttpSessionActivationListener,HttpSessionAttributeListener<br />新增Event: ServletContextEvent,ServletContextAttributeEvent,HttpSessionEvent<br />(3)servlet2.4和jsp2.0<br />新增Listener:ServletRequestListener,ServletRequestAttribureListener<br />新增Event: ServletRequestEvent,ServletRequestAttributeEvent<br />三、J2EE规范版本比较<br />1.J2EE的发展<br /><br />1997 年Servlet技术的产生以及紧接着JSP的产生，为Java对抗PHP，ASP等等服务器端语言带来了筹码。1998年，Sun发布了EJB1.0标准，至此J2EE平台的三个核心技术都已经出现。于是，1999年，Sun正式发布了J2EE的第一个版本。并与1999年底发布了J2EE1.2，在 2001年发布了J2EE1.3，2003年发布了J2EE1.4。<br /><br />2.J2EE1.3<br />J2EE1.3的架构，其中主要包含了Applet容器，Application Client容器，Web容器和EJB容器，并且包含了Web Component，EJB Component，Application Client Component，以JMS，JAAS，JAXP，JDBC，JAF，JavaMail，JTA等等技术做为基础。<br /><br />1.3中引入了几个值得注意的功能：Java消息服务（定义了JMS的一组API），J2EE连接器技术（定义了扩展J2EE服务到非J2EE应用程序的标准），XML解析器的一组Java API，Servlet2.3，JSP1.2也都进行了性能扩展与优化，全新的CMP组件模型和MDB（消息Bean）。<br /><br /><br />3.J2EE1.4<br /><br />J2EE1.4 大体上的框架和J2EE1.3是一致的，1.4增加了对Web服务的支持，主要是Web Service，JAX-RPC，SAAJ，JAXR，还对EJB的消息传递机制进行了完善（EJB2.1）,部署与管理工具的增强（JMX），以及新版本的Servlet2.4和JSP2.0使得Web应用更加容易。<br /><br />四、Tomcat版本比较<br />Tomcat 3.x<br />servlet2.2和jsp1.1标准<br />Tomcat 4.x<br />Servlet 2.3 和 JSP 1.2 版本<br />Tomcat 5.x<br />Servlet 2.4或2.5 和 JSP 2.0 版本<br /><br />五、JDK版本比较<br />已发行的版本:<br />版本号 名称 中文名 发布日期<br />JDK 1.1.4 Sparkler 宝石 1997-09-12<br />JDK 1.1.5 Pumpkin 南瓜 1997-12-13<br />JDK 1.1.6 Abigail 阿比盖尔--女子名 1998-04-24<br />JDK 1.1.7 Brutus 布鲁图--古罗马政治家和将军 1998-09-28<br />JDK 1.1.8 Chelsea 切尔西--城市名 1999-04-08<br />J2SE 1.2 Playground 运动场 1998-12-04<br />J2SE 1.2.1 none 无 1999-03-30<br />J2SE 1.2.2 Cricket 蟋蟀 1999-07-08<br />J2SE 1.3 Kestrel 美洲红隼 2000-05-08<br />J2SE 1.3.1 Ladybird 瓢虫 2001-05-17<br />J2SE 1.4.0 Merlin 灰背隼 2002-02-13<br />J2SE 1.4.1 grasshopper 蚱蜢 2002-09-16<br />J2SE 1.4.2 Mantis 螳螂 2003-06-26<br />将发行的版本:<br />J2SE 5.0 (1.5.0) Tiger 老虎 已发布<br />J2SE 5.1 (1.5.1) Dragonfly 蜻蜓 未发布<br />J2SE 6.0 (1.6.0) Mustang 野马 已发布
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/209858#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 30 Jun 2008 17:40:59 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/209858</link>
        <guid>http://bulargy.javaeye.com/blog/209858</guid>
      </item>
      <item>
        <title>eclipse.ini说明</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/198611" style="color:red;">http://bulargy.javaeye.com/blog/198611</a>&nbsp;
          发表时间: 2008年05月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          网上关于eclipse.ini的说明已经很多了，自己把适合自己机子的配置弄出来以备后用<br />--launcher.XXMaxPermSize //eclipse启动时的非堆最大内存<br />-vmargs //设置jvm<br />-Xms //JVM初始分配的内存<br />-Xmx //JVM最大分配的内存,默认空余堆内存小于40%时，JVM就会增大堆直到-Xmx的最大限制,空余堆内存大于70%时，JVM会减少堆直到- Xms的最小限制<br />-XX:PermSize //非堆内存初始值<br />-XX:MaxPermSize //最大非堆内存<br />-XX:+UseParallelGC //双核使用加快gc<br /><br />自己开发机是1G的内存，奔4 3.0Gcpu winxp sp2 myeclipse6.0.1<br />感觉这样的配置速度还行：<br />-showsplash<br />com.genuitec.myeclipse.product<br />--launcher.XXMaxPermSize<br />256m<br />-vmargs<br />-Xms128m<br />-Xmx512m<br />-Duser.language=en <br />-XX:PermSize=64M <br />-XX:MaxPermSize=256M
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/198611#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 30 May 2008 11:36:20 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/198611</link>
        <guid>http://bulargy.javaeye.com/blog/198611</guid>
      </item>
      <item>
        <title>Bea技术日</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/193415" style="color:red;">http://bulargy.javaeye.com/blog/193415</a>&nbsp;
          发表时间: 2008年05月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          周2去参加bea的技术日，一直都在讲soa什么的。还是和去年一样adobe去讲了不少。感觉今年的比去年的要好一点，技术含量也高一点。讲的也好一点。<br />冲着那件比较酷的黑色T-恤去的。感觉还不错。<br />今天的抽奖还可以有软件有书有iphone。可惜我什么都没抽到，郁闷一下~~~
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/193415#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 May 2008 21:11:45 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/193415</link>
        <guid>http://bulargy.javaeye.com/blog/193415</guid>
      </item>
      <item>
        <title>碰到一个钉子户，请大家给点意见</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/193218" style="color:red;">http://bulargy.javaeye.com/blog/193218</a>&nbsp;
          发表时间: 2008年05月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          事情是这样的，小弟第1次做TL,带4个人一起做一个平台，其中有一位实习生是某一个公司资格很老的项目经理的亲戚弄进来，此人看上去虽然还算机灵，但是基础很差，并且十分的不虚心。其他组员都对他感到很无奈，我也对他很无奈。曾经向我的老大反应过这个问题，但是老大也没办法，可能是公司高层也很看重那位项目经理的缘故，拉不下面子来。<br />    我和我的老大都找这个实习生谈过，我老大还说他甚至已经把话说的比较重了。但是他好了3天又开始犯毛病了。<br /><br />列举一下他的部分让我郁闷的行为：<br />1. 长期不更新代码或者下载svn上最新的代码。<br />    经常自己改了2，30个类后再提交，我每次更新总能发现有鲜红的叉叉，然后对照的迁入日志找到他，去问他，他就说他的没问题；我一看他的代码还是几天前的。<br />2. 超级喜欢推卸责任<br />    不管是不是他的问题导致了开发中的一些bug或者错误，你只要问他，他连想都不想就脱口而出“肯定是XXX把什么改掉了”或者是“我什么都没动过”。我真的很讨厌这样的行为。作为一个实习生，一个新人，一个基础很差的开发者，犯错的机会是很大的。你做的或者和你的做的相关东西发生的问题，你总该去检查一下看看么。记得我刚工作那会，出了问题我都很紧张，生怕是自己什么地方写错了，影响到别人。<br />3. 超级不虚心<br />    这个也是让人非常受不了了，让他做什么，要么就是讨价还价“这样不好做啊，还是xxx这样吧”，要么就是“这个我不会，你帮我写一下”。有时候有不懂的问我或者其他成员，还没给他解释一半，就开始“这个我知道，那个我知道”，我靠，你都知道你问个xx啊~~~<br />4. 超级贪功<br />    我在我们的部门的confluence上列了一个项目的任务列表，让大家领取并且更新状态。本着开放的心态我让他们都可以更新，结果您猜怎么着，他老人家把我给他分的一个“xxx管理”任务自己拆成了5，6个“xxx查询”、“xxx修改”这样的任务了，生怕人家不知道他做了事情。真是无语啊。。。<br /><br />    其实大家都是从新人过来的，就算现在我也只是算一个比较不那么新的新人；对待新人我都是比较宽容的，不会分太复杂的任务，也不会用要求自己的要求去要求他，但是碰到这样的人，我真的很无奈。并且看样子似乎不可能把他踢出局的。不知大家有没什么好的建议。。。小弟先谢过了
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/193218#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 May 2008 11:17:11 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/193218</link>
        <guid>http://bulargy.javaeye.com/blog/193218</guid>
      </item>
      <item>
        <title>郁闷的acegi</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/186601" style="color:red;">http://bulargy.javaeye.com/blog/186601</a>&nbsp;
          发表时间: 2008年04月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近捣鼓捣鼓acegi，对于登陆认证的过程倒是很方便，虽然配置较多，但是不复杂。捣鼓起来还满顺手的。但是要和现在系统的权限结合简直就是要了我的命啊。后来看acl更郁闷，调了半天都报错误的sql语句call identity()。把整个工作里唯有的2句在ContactDaoSpring里的call identity()改成了SELECT LAST_INSERT_ID()还是报那个错。最后再一个e文的网站上找到了答案。原来是在他的jar档里就有写死的sql语句啊，我用的1.0.6是在org.acegisecurity.acls.jdbc.JdbcMutableAclService里有句<br /><pre name="code" class="java"> private String identityQuery = "call identity()";</pre><br />真是灰常的郁闷啊~~~~
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/186601#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 25 Apr 2008 09:20:00 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/186601</link>
        <guid>http://bulargy.javaeye.com/blog/186601</guid>
      </item>
      <item>
        <title>忙里偷闲一下</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/186534" style="color:red;">http://bulargy.javaeye.com/blog/186534</a>&nbsp;
          发表时间: 2008年04月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          昨天晚上更新代码到google code 的svn居然down掉了，郁闷的要死。今天早上起来才发现它又好了~~~嘿嘿~~~<br />刚无意去apache的网站逛逛，居然发现他改版了。真是稀奇啊。记得自打我知道apache以来貌似他的网站就是那个样子了，现在居然都改版了，看来时代变化快啊。。<br />事情好多，好忙。灌灌水继续忙了~~~~
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/186534#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 24 Apr 2008 21:14:05 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/186534</link>
        <guid>http://bulargy.javaeye.com/blog/186534</guid>
      </item>
      <item>
        <title>struts2.0的标签学习</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/182337" style="color:red;">http://bulargy.javaeye.com/blog/182337</a>&nbsp;
          发表时间: 2008年04月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          用过struts1.x的人都知道，标签库有html、bean、logic、tiles，<br />而struts2.0里的标签却没有分类，只用在jsp头文件加上<br />&lt;%@ taglib prefix="s" uri="/struts-tags" %><br />就能使用struts2.0的标签库<br /><br />A：<br />&lt;s:a href="">&lt;/s:a>-----超链接，类似于html里的&lt;a>&lt;/a><br />&lt;s:action name="">&lt;/s:action>-----执行一个view里面的一个action<br />&lt;s:actionerror/>-----如果action的errors有值那么显示出来<br />&lt;s:actionmessage/>-----如果action的message有值那么显示出来<br />&lt;s:append>&lt;/s:append>-----添加一个值到list，类似于list.add();<br />&lt;s:autocompleter>&lt;/s:autocompleter>-----自动完成&lt;s:combobox>标签的内容，这个是ajax<br /><br />B：<br />&lt;s:bean name="">&lt;/s:bean>-----类似于struts1.x中的，JavaBean的值<br /><br />C：<br />&lt;s:checkbox>&lt;/s:checkbox>-----复选框<br />&lt;s:checkboxlist list="">&lt;/s:checkboxlist>-----多选框<br />&lt;s:combobox list="">&lt;/s:combobox>-----下拉框<br />&lt;s:component>&lt;/s:component>-----图像符号<br /><br />D：<br />&lt;s:date/>-----获取日期格式<br />&lt;s:datetimepicker>&lt;/s:datetimepicker>-----日期输入框<br />&lt;s:debug>&lt;/s:debug>-----显示错误信息<br />&lt;s:div>&lt;/s:div>-----表示一个块，类似于html的&lt;div>&lt;/div><br />&lt;s:doubleselect list="" doubleName="" doubleList="">&lt;/s:doubleselect>-----双下拉框<br /><br />E：<br />&lt;s:if test="">&lt;/s:if><br />&lt;s:elseif test="">&lt;/s:elseif><br />&lt;s:else>&lt;/s:else>-----这3个标签一起使用，表示条件判断<br /><br />F：<br />&lt;s:fielderror>&lt;/s:fielderror>-----显示文件错误信息<br />&lt;s:file>&lt;/s:file>-----文件上传<br />&lt;s:form action="">&lt;/s:form>-----获取相应form的值<br /><br />G：<br />&lt;s:generator separator="" val="">&lt;/s:generator>----和&lt;s:iterator>标签一起使用<br /><br />H：<br />&lt;s:head/>-----在&lt;head>&lt;/head>里使用，表示头文件结束<br />&lt;s:hidden>&lt;/s:hidden>-----隐藏值<br /><br />I：<br />&lt;s:i18n name="">&lt;/s:i18n>-----加载资源包到值堆栈<br />&lt;s:include value="">&lt;/s:include>-----包含一个输出，servlet或jsp页面<br />&lt;s:inputtransferselect list="">&lt;/s:inputtransferselect>-----获取form的一个输入<br />&lt;s:iterator>&lt;/s:iterator>-----用于遍历集合<br /><br />L：<br />&lt;s:label>&lt;/s:label>-----只读的标签<br /><br />M：<br />&lt;s:merge>&lt;/s:merge>-----合并遍历集合出来的值<br /><br />O：<br />&lt;s:optgroup>&lt;/s:optgroup>-----获取标签组<br />&lt;s:optiontransferselect doubleList="" list="" doubleName="">&lt;/s:optiontransferselect>-----左右选择框<br /><br />P：<br />&lt;s:param>&lt;/s:param>-----为其他标签提供参数<br />&lt;s:password>&lt;/s:password>-----密码输入框<br />&lt;s:property/>-----得到'value'的属性<br />&lt;s:push value="">&lt;/s:push>-----value的值push到栈中,从而使property标签的能够获取value的属性<br /><br />R：<br /><br />&lt;s:radio list="">&lt;/s:radio>-----单选按钮<br />&lt;s:reset>&lt;/s:reset>-----重置按钮<br /><br />S：<br />&lt;s:select list="">&lt;/s:select>-----单选框<br />&lt;s:set name="">&lt;/s:set>-----赋予变量一个特定范围内的值<br />&lt;s:sort comparator="">&lt;/s:sort>-----通过属性给list分类<br />&lt;s:submit>&lt;/s:submit>-----提交按钮<br />&lt;s:subset>&lt;/s:subset>-----为遍历集合输出子集<br /><br />T：<br />&lt;s:tabbedPanel id="">&lt;/s:tabbedPanel>-----表格框<br />&lt;s:table>&lt;/s:table>-----表格<br />&lt;s:text name="">&lt;/s:text>-----I18n文本信息<br />&lt;s:textarea>&lt;/s:textarea>-----文本域输入框<br />&lt;s:textfield>&lt;/s:textfield>-----文本输入框<br />&lt;s:token>&lt;/s:token>-----拦截器<br />&lt;s:tree>&lt;/s:tree>-----树<br />&lt;s:treenode label="">&lt;/s:treenode>-----树的结构<br /><br />U：<br />&lt;s:updownselect list="">&lt;/s:updownselect>-----多选择框<br />&lt;s:url>&lt;/s:url>-----创建url
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/182337#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 13 Apr 2008 16:42:56 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/182337</link>
        <guid>http://bulargy.javaeye.com/blog/182337</guid>
      </item>
      <item>
        <title>小白乱弹xml和annotation配置</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/179781" style="color:red;">http://bulargy.javaeye.com/blog/179781</a>&nbsp;
          发表时间: 2008年04月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          以前的项目都没有用到annotation，大量的xml配置文件让所有的开发人员都有一点心寒。于是最近的一个项目大范围使用annotation的项目，虽然在项目之初，我是绝对站在annotation这一边说话的，但是随着项目的推进，慢慢的我开始体会到annotation的一些不足，甚至有些怀恋xml了。 <br />   <br />因为之前团队里很多人对大量xml产生一些恐惧或者说是反感，认为大量的xml让人维护起来实在是眼花缭乱，而且由于xml里的很多配置都基本是差不多的，在复制粘贴这些配置的时候很容易忘记改掉某些地方而产生问题。所以当一些拥有annotation的框架出现在新项目选型的范围之内时，大家都十分愿意接受它。问题就这样产生了，annotation被我们当成了救命稻草，几乎只要是能用annotation的地方绝对不用xml配置。 <br /><br />我们采用了struts2+spring2.5+hibernate3的主框架结构。在刚开始的一段时间annotation&ldquo;成绩斐然&rdquo;，我们所有的xml配置文件的内容几乎压缩到比以前方式配置helloworld多不了多少的程度了。大家对这样的成果都十分的满意，于是annotation开始被我们神话了。随着框架搭建的深入，事务、日志、安全等等考虑加入其中以后我发现问题有些不对劲了。采用annotation配置事务需要到每一个负责事务的类里面去编写相关的规则，很多相似的东西都要在每个类里重复的写。而且如此讲事务控制的代码分散在类中实在是不便于管理和调试修改。此时，我开始对annotation产生了怀疑。于是改了我的qq留言，没过2天javaeye上也看到了相关的讨论。与此同事，老大也发现了类似的一些问题。例如，我们的实体上都有很多的标签去定义，这样如果开发者仅仅是想看看某个实体有什么属性，他将不得不看到一大堆的标签，而且如果我们将此实体当作一个普通的pojo使用的话，也会附带很多无用的annotation在其上。 <br /><br />当天下午，我通过IM向以前的一位前辈请教，我问他对于xml和annotation的看法。问为什么现在annotation如此的火爆，有些用起来并不好的地方也被滥用了。他的回答是：我最近好一段时间都没在开发一线了，具体的可能我也说不太准，可能技术人员都喜欢捣鼓新技术吧。我觉得他的话也有一定的道理。。。。。 <br /><br />后来我又好好的想了一想，annotation现在肯定是被我们滥用了，这个情况需要改善。那么什么时候该用annotation什么时候该用xml呢?既然这么些流行的框架都提供的annotation的方式，那他们的用意又是什么呢？我还有几点疑惑：<br /> <br /><span style="color: olive">1.用annotation配置难道不是配置吗？我们以前是害怕大量的xml，难道我们就不害怕大量的anntation吗？xml还是在一个地方管理，annotation散布在类中，如果后期发现前期一些设定不合适，例如事务等等，难道还跑到每个类里去修改吗？<br /> <br />2.用annotation注释spring管理的bean，如果我们忘记写annotation或者我们写错了，那么只用在运行代码的时候（可能是测试用例）才能发现这些问题，并且还可能打开多个类去检查。而xml的配置一般都是集中在一起便于检查，而且也只打开一个xml文件。<br /><br />3.我们为什么要配置？我认为配置的初衷就是为了方便更改可配置的项，方便统一管理。换句话说就是从代码中抽出可能的变化。既然是这样，那么annotation把配置信息分散到类中的行为岂不是有为这个初衷？ </span><br /><br />由于有了这些疑问我自己都不能给自己一个很好的解释，所以我在google上又搜索一些关于xml和anntation的讨论。发现有一些观点还是不错的。 <br /><br />有一种说法就是java语法过于对象化，以至于很多操作调用的过程规规矩矩过于繁琐，annotation是sun为了弥补这样的情况提高java语法的功能而产生的产物。所以annotation应该用于加强java语法的地方而不是用在做配置的方面。例如在action里通过annotation来简化传递参数的过程等。我觉得还是比较合理的解释。 <br /><br />还有一种说法就是认为annotation适合于稳定的建模过程中，用于那些不易更改的对象。提高内聚，认为这些行为本来就属于模型本身。这个我也基本同意，只要是这个模型或者实体不用于其他方面，职责单一的情况下是比较合理的说法。 <br /><br />既然看上去xml并没有什么不好，那么大家为什么有些反感xml呢？<br />一个好几千行的xml确实让人眼花缭乱。我觉得首先是xml划分要合理，如果比较多一定要细分模块的配置文件，让模块内的配置尽量的少一些，看起来比较舒服。<br />其次就是xml配置项中有很多看起来都重复的地方，这个可以通过泛型通用类去解决一些只有CRUD相关操作的类的配置，可以大大减少配置文件的大小和重复性。又或是充分利用一些新版本框架对通配符的匹配来减少相似配置的出现。<br /><br />最后总结一下，目前看来annotation和xml谁是谁非似乎还没有一个完全让大多数人信服的说辞。希望随着实际应用的增多，最后能有一个让大多数人信服的最佳实践产生。也希望自己在当前的项目中，进一步的对这2者的进行更深入的理解比较。实践才是检验真理的唯一标准啊。
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/179781#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 06 Apr 2008 03:18:27 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/179781</link>
        <guid>http://bulargy.javaeye.com/blog/179781</guid>
      </item>
      <item>
        <title>svn备份</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/178680" style="color:red;">http://bulargy.javaeye.com/blog/178680</a>&nbsp;
          发表时间: 2008年04月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          版本控制最关键的一件事是保证数据的安全性，不能因为磁盘损坏，程序故障造成版本库无可挽回的错误，为此必须制定较完备的备份策略。<br />在Subversion中，我们有三种备份方式：完全备份，增量备份和同步版本库。<br /><br />1. 完全备份：<br /><br />最常见和简单的备份就是直接使用拷贝命令，将版本库目录拷贝到备份目录上，就可以了。但是这样不是很安全的方式，因为如果在拷贝时版本库发生变化，将会造成备份的结果不够准确，失去备份的作用，为此Subversion提供了“svnadmin hotcopy”命令，可以防止这种问题。<br />比如有如下版本库：<br /><br />D:\svnroot<br />├─project1<br />│     ├─conf<br />│     ├─dav<br />│     ├─db<br />│     │     ├─revprops<br />│     │     ├─revs<br />│     │     └─transactions<br />│     ├─hooks<br />│     └─locks<br />└─project2<br />       ├─conf<br />       ├─dav<br />       ├─db<br />       │     ├─revprops<br />       │     ├─revs<br />       │     └─transactions<br />       ├─hooks<br />└─locks<br /><br />如果要把project1备份到D:\svnrootbackup目录下，只需要运行：svnadmin hotcopy d:\svnroot\project1 d:\ svnrootbackup \project1<br /><br />PS:如果我们目录下有很多版本库，需要为每个版本库写这样一条语句备份，必须想办法优化这个过程。为此，建立以下的2个bat文件，<br />simplebackup.bat：<br />@echo 正在备份版本库%1......<br />@%SVN_HOME%\bin\svnadmin hotcopy %1 %BACKUP_DIRECTORY%\%2<br />@echo 版本库%1成功备份到了%2！<br /><br />backup.bat：<br />echo off<br />rem Subversion的安装目录<br />set SVN_HOME="D:\Subversion"<br />rem 所有版本库的父目录<br />set SVN_ROOT=D:\svnroot<br />rem 备份的目录<br />set BACKUP_SVN_ROOT=D:\svnrootbak<br />set BACKUP_DIRECTORY=%BACKUP_SVN_ROOT%\%date:~0,10%<br />if exist %BACKUP_DIRECTORY% goto checkBack<br />echo 建立备份目录%BACKUP_DIRECTORY%>>%SVN_ROOT%/backup.log<br />mkdir %BACKUP_DIRECTORY%<br />rem 验证目录是否为版本库，如果是则取出名称备份<br />for /r %SVN_ROOT% %%I in (.) do @if exist "%%I\conf\svnserve.conf" %SVN_ROOT%\simplebackup.bat "%%~fI" %%~nI<br />goto end<br />:checkBack<br />echo 备份目录%BACKUP_DIRECTORY%已经存在，请清空。<br />goto end<br />:end<br /><br />使用的时候，只需要修改backup.bat开头的三个路径，将两个脚本拷贝到"SVN_ROOT"下就可以了。根据以上的配置，你只需要运行backup.bat，就可以把"SVN_ROOT"下的版本库都备份到"BACKUP_SVN_ROOT"里，并且存放在备份所在的目录里。<br /><br />2. 增量备份：<br />尽管完全备份非常简单，但是也是有代价的，当版本库非常巨大时，经常进行完全备份是不现实的，也并不必要，但是一旦版本库在备份之间发生问题，该如何呢，这里我们就用到了增量备份。<br />增量备份通常要与完全备份结合使用，记录着每次Subversion提交的变化，然后在需要恢复时能够回到最新的可用状态。<br />我们使用的是，svnadmin dump命令进行增量的备份，使用方法是：<br />svnadmin dump d:\sourcecode\project1 --revision 15 --incremental > d:\sourcecode\dumpfile<br /><br />上面的命令实现了对修订版本15进行增量的备份，其中的输出文件dumpfile只保存了修订版本15更改的内容<br /><br />恢复增量备份时，使用方法是：<br />svnadmin load d:\sourcecode\project1 &lt; d:\sourcecode\dumpfile<br />上面的命令实现了对增量备份文件恢复到版本库project1中<br /><br />使用钩子脚本Hooks实现自动增量备份：<br />1) 建立deltabackup.bat文件，内容为：<br />@echo 正在备份版本库%2......<br />%SVN_HOME%\bin\svnadmin dump %SVN_ROOT%\%1 --incremental --revision %2 >> %DELTA_BACKUP_SVN_ROOT%\%1.dump<br />@echo 版本库%2成功备份到了%3！<br />2) 建立post-commit.bat文件，内容为：<br />echo off<br />set SVN_HOME="C:\Program Files\Subversion"<br />set SVN_ROOT=D:\svnroot<br />set UNIX_SVN_ROOT=D:/svnroot<br />set DELTA_BACKUP_SVN_ROOT=D:\svnrootbak\delta<br />set LOG_FILE=%1\backup.log<br />echo backup revision %2 >> %LOG_FILE%<br />for /r %SVN_ROOT% %%I in (.) do if D:/svnroot/%%~nI == %1 %SVN_ROOT%\%%~nI\hooks\deltaBackup.bat %%~nI %2<br />goto end<br />:end<br />3) 把以上两个脚本可以直接拷贝到版本库的hooks目录下，就可以实现版本库的自动备份。<br /><br />3. 同步版本库：<br />同步机制，可以实现一个版本库同另一个版本库的同步（但好像只是单向的），我们可以用来实现版本库的备份或镜像。<br />例如：同步版本库d:\sourcecode\project1<br />1) 新建一个空的版本库project2<br />运行命令：<br />svnadmin create d:\sourcecode\project2<br /><br />2) 为新的版本库创建pre-revprop-change钩子脚本(hook script)<br />在d:\sourcecode\project2\hooks目录下新建一个空的pre-revprop-change.bat文件<br /><br />3) 初始化版本库<br />运行命令：<br />svnsync init file:///d:/sourcecode/project2 file:///d:/sourcecode/project1<br /><br />4) 同步版本库<br />运行命令：<br />svnsync sync file:///d:/sourcecode/project2<br />  <br />5) 至此，版本库同步已经完成。<br />在使用新的版本库之前，还需要根据需要对版本库的访问权限等进行配置。<br /><br />使用钩子脚本Hooks实现自动同步：<br />1) 建立post-commit.bat文件，内容为：<br />echo off<br />set SVN_HOME="D:\Subversion"<br />%SVN_HOME%\bin\svnsync sync     --non-interactive svn://localhost/project2<br />2) 把post-commit.bat文件放到版本库project1下的hooks目录下，这样project1每次提交，都会引起project2的同步<br /><br /><br /><br /><br />转自：http://hi.baidu.com/vb1980/blog/item/1306ee226ff370a74623e8a9.html
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/178680#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 02 Apr 2008 09:47:13 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/178680</link>
        <guid>http://bulargy.javaeye.com/blog/178680</guid>
      </item>
      <item>
        <title>myeclipse绿色版的制作</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/175419" style="color:red;">http://bulargy.javaeye.com/blog/175419</a>&nbsp;
          发表时间: 2008年03月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          myeclipse是一个比较好用的插件，但是每次安装起来实在太麻烦，特别是6以后，那速度跟啥似的。我开发机的配置已经算比较高了，但是最后一步的时候仍然够我去泡杯coffe喝了。于是想办法把它弄成绿色版。其实很容易。<br />myeclipse也仅仅是eclipse的一个插件，插件有2中安装方式，一种直接放到eclipse的插件目录下，另一种就是link的形式。myeclipse就是link的形式安装的。所以我们互相拷来拷去只要目录结构不对就不能用。<br />参考网上的做法。用myeclipse6.0 all in one的版本实践。<br />首先将你所有需要用到的常用插件全部装好，并验证ok。<br />然后将myeclipse\eclipse\links下的com.genuitec.eclipse.MyEclipse.link里的内容由具体的磁盘地址改为相对地址即可：<br />path=..\\myeclipse<br />如果你想在myeclipse目录下就启动它，那么加一个bat文件，内容：<br />start eclipse\eclipse.exe -vm jre\bin\javaw.exe<br /><br />ok，你可以带着你的工具到处跑了，开箱急用，多方便。。。。
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/175419#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 24 Mar 2008 14:18:05 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/175419</link>
        <guid>http://bulargy.javaeye.com/blog/175419</guid>
      </item>
      <item>
        <title>JBoss部署时版本冲突一例</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/174457" style="color:red;">http://bulargy.javaeye.com/blog/174457</a>&nbsp;
          发表时间: 2008年03月21日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          自己做一些小例子玩，部署到tomcat和jetty上都能正常工作。但是部署到JBoss里的时候问题就来了，这也找不到，那也找不到。报的错也看起来找不着北，说什么自动写入失败啊，bean加载失败啊，弄了半天也没弄明白。<br />上网到处找找，由于报的错实在太普片了，所以和大海捞针一样的。但是我发现大部的JBoss问题都是由于这个包不对啊，那个包不兼容啊又或是冲突了之类。<br />于是我就对比JBoss默认的包和我例子里的包，有好多都是重复的，最后发现hibernate-annotations.jar这个包的大小不一样。我隐隐觉得这就是问题了，于是替换了JBoss默认的hibernate-annotations.jar。<br />重新部署，启动，ok~~~一切正常~~~~<br /><br />总结：<br />看来JBoss这个jar版本冲突的问题真的很严重啊，大家如果碰到JBoss的问题不妨先查查jar的问题。
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/174457#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 21 Mar 2008 12:49:12 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/174457</link>
        <guid>http://bulargy.javaeye.com/blog/174457</guid>
      </item>
      <item>
        <title>subversion keywords设置</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/174144" style="color:red;">http://bulargy.javaeye.com/blog/174144</a>&nbsp;
          发表时间: 2008年03月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          1.到C:\Documents and Settings\yourname\Application Data\Subversion目录下，找到config文件。 <br />或者：你安装了tortoiseSVN 那么就 Settings>subversion edit <br /><br />2. 配置文件改为：<br /><br />enable-auto-props = yes<br /><br />[auto-props]<br />*.java = svn:keywords=Id Reversion Date Author<br /><br />3.ok。这样就可以使用svn的keywords了.<br />特别是eclipse里就方便多了。设置一下就可以使用<br />$$Id$$、$$Reversion $$、$$Date $$、$$Author$$作为注释模板的内容，方便极了
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/174144#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 20 Mar 2008 15:40:30 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/174144</link>
        <guid>http://bulargy.javaeye.com/blog/174144</guid>
      </item>
      <item>
        <title>hibernate的各种保存方式的 区别</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/173849" style="color:red;">http://bulargy.javaeye.com/blog/173849</a>&nbsp;
          发表时间: 2008年03月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          hibernate的保存<br />hibernate对于对象的保存提供了太多的方法，他们之间有很多不同，这里细说一下，以便区别：<br /><strong>一、预备知识：</strong><br />在所有之前，说明一下，对于hibernate，它的对象有三种状态，transient、persistent、detached<br />下边是常见的翻译办法：<br />transient：瞬态或者自由态<br />persistent：持久化状态<br />detached：脱管状态或者游离态<br /><br />脱管状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。<br />持久化实例可以通过调用 delete()变成脱管状态。通过get()或load()方法得到的实例都是持久化状态的。<br />脱管状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。<br /><br />save()和persist()将会引发SQL的INSERT，delete()会引发SQLDELETE，<br />而update()或merge()会引发SQLUPDATE。对持久化（persistent）实例的修改在刷新提交的时候会被检测到，<br />它也会引起SQLUPDATE。saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE<br /><br /><strong>二、save 和update区别</strong><br />把这一对放在第一位的原因是因为这一对是最常用的。<br />save的作用是把一个新的对象保存<br />update是把一个脱管状态的对象保存<br /><br /><strong>三,update 和saveOrUpdate区别</strong><br />这个是比较好理解的，顾名思义，saveOrUpdate基本上就是合成了save和update<br />引用hibernate reference中的一段话来解释他们的使用场合和区别<br />通常下面的场景会使用update()或saveOrUpdate()：<br />程序在第一个session中加载对象<br />该对象被传递到表现层<br />对象发生了一些改动<br />该对象被返回到业务逻辑层<br />程序调用第二个session的update()方法持久这些改动<br /><br />saveOrUpdate()做下面的事:<br />如果对象已经在本session中持久化了，不做任何事<br />如果另一个与本session关联的对象拥有相同的持久化标识(identifier)，抛出一个异常<br />如果对象没有持久化标识(identifier)属性，对其调用save()<br />如果对象的持久标识(identifier)表明其是一个新实例化的对象，对其调用save()<br />如果对象是附带版本信息的（通过&lt;version>或&lt;timestamp>） 并且版本属性的值表明其是一个新实例化的对象，save()它。<br />否则update() 这个对象<br /><br /><strong>四,persist和save区别</strong><br />这个是最迷离的一对，表面上看起来使用哪个都行，在hibernate reference文档中也没有明确的区分他们.<br />这里给出一个明确的区分。（可以跟进src看一下，虽然实现步骤类似，但是还是有细微的差别）<br />这里参考http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682中的一个说明：<br />---------------------------------------------------------------------------------<br />I found that a lot of people have the same doubt. To help to solve this issue<br />I'm quoting Christian Bauer:<br />"In case anybody finds this thread...<br /><br />persist() is well defined. It makes a transient instance persistent. However,<br />it doesn't guarantee that the identifier value will be assigned to the persistent<br />instance immediately, the assignment might happen at flush time. The spec doesn't say<br />that, which is the problem I have with persist().<br /><br />persist() also guarantees that it will not execute an INSERT statement if it is<br />called outside of transaction boundaries. This is useful in long-running conversations<br />with an extended Session/persistence context.A method like persist() is required.<br /><br />save() does not guarantee the same, it returns an identifier, and if an INSERT<br />has to be executed to get the identifier (e.g. "identity" generator, not "sequence"),<br />this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context."<br /><br />---------------------------------------------------------------------------------<br />简单翻译一下上边的句子的主要内容：<br />1，persist把一个瞬态的实例持久化，但是并"不保证"标识符被立刻填入到持久化实例中，标识符的填入可能被推迟<br />到flush的时间。<br /><br />2，persist"保证"，当它在一个transaction外部被调用的时候并不触发一个Sql Insert，这个功能是很有用的，<br />当我们通过继承Session/persistence context来封装一个长会话流程的时候，一个persist这样的函数是需要的。<br /><br />3，save"不保证"第2条,它要返回标识符，所以它会立即执行Sql insert，不管是不是在transaction内部还是外部<br /><br /><br /><strong>五,saveOrUpdateCopy,merge和update区别</strong><br />首先说明merge是用来代替saveOrUpdateCopy的，这个详细见这里<br />http://www.blogjava.net/dreamstone/archive/2007/07/28/133053.html<br />然后比较update和merge<br />update的作用上边说了，这里说一下merge的<br />如果session中存在相同持久化标识(identifier)的实例，用用户给出的对象的状态覆盖旧有的持久实例<br />如果session没有相应的持久实例，则尝试从数据库中加载，或创建新的持久化实例,最后返回该持久实例<br />用户给出的这个对象没有被关联到session上，它依旧是脱管的<br />重点是最后一句：<br />当我们使用update的时候，执行完成后，我们提供的对象A的状态变成持久化状态<br />但当我们使用merge的时候，执行完成，我们提供的对象A还是脱管状态，hibernate或者new了一个B，或者检索到<br />一个持久对象B，并把我们提供的对象A的所有的值拷贝到这个B，执行完成后B是持久状态，而我们提供的A还是托管状态<br /><br /><strong>六,flush和update区别</strong><br />这两个的区别好理解<br />update操作的是在脱管状态的对象<br />而flush是操作的在持久状态的对象。<br />默认情况下，一个持久状态的对象是不需要update的，只要你更改了对象的值，等待hibernate flush就自动<br />保存到数据库了。hibernate flush发生再几种情况下：<br />1，调用某些查询的时候<br />2，transaction commit的时候<br />3，手动调用flush的时候<br /><br /><strong>七,lock和update区别</strong><br />update是把一个已经更改过的脱管状态的对象变成持久状态<br />lock是把一个没有更改过的脱管状态的对象变成持久状态<br />对应更改一个记录的内容，两个的操作不同：<br />update的操作步骤是：<br />（1）更改脱管的对象->调用update<br />lock的操作步骤是：<br />(2)调用lock把对象从脱管状态变成持久状态-->更改持久状态的对象的内容-->等待flush或者手动flush<br /><br />参考内容：<br />http://www.blogjava.net/iamtin/archive/2006/03/06/33910.aspx<br />http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682<br />http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/objectstate.html<br /><br />[转自：http://www.blogjava.net/dreamstone/archive/2007/07/29/133071.html]
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/173849#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 19 Mar 2008 17:48:42 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/173849</link>
        <guid>http://bulargy.javaeye.com/blog/173849</guid>
      </item>
      <item>
        <title>价格便宜量又足的好工具及插件</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/173687" style="color:red;">http://bulargy.javaeye.com/blog/173687</a>&nbsp;
          发表时间: 2008年03月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          避免忘记，随时更新<br /><br />firebug:<br />下载地址 http://www.getfirebug.com/<br /><br />m2eclipse:<br />更新地址 http://m2eclipse.codehaus.org/update/<br /><br />log4e：<br />更新地址 http://log4e.jayefem.de/update<br /><br />propedit:<br />更新地址 http://propedit.sourceforge.jp/eclipse/updates/ <br /><br />subclipse:<br />更新地址 http://subclipse.tigris.org/update_1.2.x<br /><br />findbugs:<br />更新地址 http://findbugs.cs.umd.edu/eclipse/<br /><br />pmd:<br />更新地址 http://pmd.sf.net/eclipse<br /><br />jutils:<br />更新地址 http://www.jutils.com/eclipse-update<br /><br />Checkstyle:<br />更新地址 http://eclipse-cs.sourceforge.net/update<br /><br />metrics:<br />更新地址 http://metrics.sourceforge.net/update
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/173687#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 19 Mar 2008 11:50:13 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/173687</link>
        <guid>http://bulargy.javaeye.com/blog/173687</guid>
      </item>
      <item>
        <title>什么是UAT测试?</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/173539" style="color:red;">http://bulargy.javaeye.com/blog/173539</a>&nbsp;
          发表时间: 2008年03月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          UAT，(user acceptance Test),用户接受度测试 <br />以下是它的一些一般步骤；仅供参考 <br />一步:用户培训手册准备（就是针对要进行UAT测试的对象，及要进行培训的用户，准备一些培训资料：一般是测试对象使用/功能手册及要培训的用户的个人资料等等：就跟教师上课进行备课差不多） <br />二步：测试脚本发放（如果你公司采用自动化测试，那么每一个功能或一个模块等都有对应的测试脚本，可以把这些测试脚本分发给特点的人员；如果采用手工测试，就要把详细描述一个功能或模块的文档分给相关人员（当然自动化测试也要分发）） <br />三步：用户补充业务测试场景和测试数据（就是：请有代表性的一些最终用户根据实际应用环境及一些常用处理的数据，来给一些补充与建议，越贴近实际应用越好） <br />四步：顾问补充测试步骤（你可以请项目专家，测试经理，或专门的测试，开发等顾问对测试步骤进行补充） <br />五步：培训资料及测试脚本文档的确定与最终输出(一般到此，各种资料都基本确定，这时可以将它们进行打印，或形成特别的电子文档） <br />六步：测试策略的制定（如嵌入测试策略等） <br />七步：测试用户的确定（大体上从培训人员中选取，因为不能每个接受培训的人员都是资格去测试的，这里你可以通过一些考核来实现人员的筛选等等） <br />八步：由专门的测试组织机构确定测试地点，并发出通知 <br />九步：测试网络环境的搭建和保障（包括网络，系统，硬软件，包括一些case工具等 <br />十步：组织进行测试 <br />十一步：评审分析提交的问题（这就进入了一般bug处理过程，形成了一个循环） <br />UAT测试的重点,我想主要体现在以下几个方面 <br />一是：培训的资料表述要准确全面，易懂等（这是理论基础） <br />二是：人员选择，要典型有代表性（用户基础） <br />三是：测试流程步骤（要周密） <br />四是：测试策略制定（确定一个适合测试对象及测试人员的测试策略） <br />五是：问题的表达与处理(因为测试者不是专业开发测试人员，对于问题的表达可能不能到位，或根本就不是那种问题，这就存在如何复现与转化问题等）
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/173539#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 18 Mar 2008 22:29:10 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/173539</link>
        <guid>http://bulargy.javaeye.com/blog/173539</guid>
      </item>
      <item>
        <title>subversion权限设置的一个奇怪问题</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/173363" style="color:red;">http://bulargy.javaeye.com/blog/173363</a>&nbsp;
          发表时间: 2008年03月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近搞搞svn来管理代码。在设置权限的时候有一个很奇怪的问题。<br />那就是不管我怎么分配权限文件里的权限，把所有的权限都打开还是不能check out代码出来。真是郁闷极了。<br />最后在网上找到一个解决方案，那位朋友说他做梦也没想到。其实我也是做梦也没想到。<br />那就是svnserve.conf里的anon-access = read改为anon-access = none就可以了。<br />真是没有想到了，没有想到啊。
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/173363#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 18 Mar 2008 13:07:52 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/173363</link>
        <guid>http://bulargy.javaeye.com/blog/173363</guid>
      </item>
      <item>
        <title>小白学Junit4测试</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/170312" style="color:red;">http://bulargy.javaeye.com/blog/170312</a>&nbsp;
          发表时间: 2008年03月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          近期写单元测试计划，公司准备把junit3.8升级到junit4以上的版本，所以研究了一下，写下学习过程和心得体会，为了巩固学习成果，所以把学习心得写下来加深印象，也供需要的朋友查阅，少走弯路。<br />   好了，废话不多说，直接开始：<br />   假设我们要写一个整数除法和乘法的类，并且给他写测试用例：<br /><strong><br />1) 建立Math类</strong><br />工具是eclipse3.3<br /><pre name="code" class="java">
/**
 * @author bulargy.j.bai
 * @mail bulargy@gmail.com
 * @创建时间：Mar 10, 2008
 * @描述：一个整数除法和乘法的工具类
 */
public class Math {
    public static int divide(int x,int y) {
        return x/y;
    }

    public static int multiple(int x,int y) {
        return x*y;
    }
}

</pre><br /><br /><strong>2) 建立测试用例</strong><br />选中需要建立测试用例的包，选择new->other->JUnit Test Case。<br />有5个方法可以选择：<br />setUp()方法在测试方法前调用，一般用来做测试准备工作。<br />tearDown()方法在测试方法后调用，一般作测试的清理工作。<br />setUpBeforeClass()方法在整个类初始化之后调用，一般用来做测试准备工作。<br />tearDownAfterClass()方法在整个类结束之前调用，一般作测试的清理工作。<br />constructor()为是否包含构造方法。<br /><br />自动生成的代码如下：<br /><pre name="code" class="java">
/**
 * @author bulargy.j.bai
 * @mail bulargy@gmail.com
 * @创建时间：Mar 11, 2008
 * @描述：
 */
public class MathTest {

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }
    
    @Test
    public void testDivide() {
        fail("Not yet implemented");
    }

    @Test
    public void testMultiple() {
        fail("Not yet implemented");
    }
}
</pre><br /><span style="color: red">说明：</span><br /><span style="color: olive">@BeforeClass标签注释的方法用于在整个类测试过程的初始化后调用一次，@AfterClass标签注释的方法则是整个测试类结束之前调用一次。这2个标签的搭配可以避免使用@Before、@After标签组合在每个测试方法前后都调用的弊端，减少系统开销，提高系统测试速度。(不过对环境独立性要求较高的测试还是应当使用@Before、@After来完成)<br />@Test标签用来标注待测试的方法，按照类中声明的顺序执行。</span><br /><br />我们在testDivide方法加入测试代码，分别测试三种情况：<br />a.	完全正确也没有可能出错的数据，如：9除3  结果必须等于3<br />b.	可能有问题的边缘数据，如：10除3 结果也必须等于3<br />c.	错误的数据，如：10除0 必须抛出异常<br /><br />忽略testMultiple方法<br /><br />代码如下：<br /><pre name="code" class="java">
    @Test(expected=ArithmeticException.class)
    public void testDivide() {
        assertEquals(3,Math.divide(9,3));
        assertEquals(3,Math.divide(10,3));
        Math.divide(10,0); //除数不能为0，会抛出异常
    }
    
    @Ignore("忽略乘法测试")
    @Test
    public void testMultiple() {
    }
</pre><br /><span style="color: red">说明:</span><br /><span style="color: olive">Junit4为测试方法增加了判断异常的方式，避免了以前还要通过try/catch块捕捉异常再抛出的复杂方式，简单的这样声明“@Test(expected=ArithmeticException.class)”Junit4就会检查此方法是否抛出ArithmeticException异常，如果抛出则测试通过，没抛出则测试不通过（@Test标签还有一些其他参数，例如超时测试@Test(timeout=1)这样，但是由于并不能准确反应实际时间，所以应用较少，经过我测试误差太大绝对不适合拿来做超时测试的）<br />@Ignore标签会告诉Junit4忽略它所标注的方法，例如数据库不可用时可以用此标注标注一些测试数据库连接的方法来避免测试失败。<br /></span><br /><strong>3) 运行测试</strong><br />系统会打开JUnit透视图，如果测试全部通过，则显示颜色条为绿色；我们将assertEquals(3,Math.divide(9,3));改成assertEquals(2,Math.divide(9,3));则显示颜色条为红色，我们可以对错误或者故障的地方进行追踪。<br /><br /><strong>4) 创建测试套件</strong><br />  测试套件可以将多个测试用例合在一起测试，将相关的测试用例合成一个测试套件，在做一个修改后，只需要运行测试套件就可以，不需要运行每一个测试用例。<br />  Junit4没有采用以前的套件测试方法，同样使用annotation的方式来进行。简单在你所要构建测试套件的包里创建一个文件，一般以包名+4Suite<br />下面我在上面的测试包中复制一下之前的测试类并且一个改名字叫做MathTestAnother，新建一个class类叫做Uitl4Suite，代码如下：<br /><pre name="code" class="java">
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
/**
 * @author bulargy.j.bai
 * @mail bulargy@gmail.com
 * @创建时间：Mar 11, 2008
 * @描述：util包的测试套件
 */
@RunWith(Suite.class)
@SuiteClasses({MathTest.class,
           MathTestAnother.class})
public class Util4Suite {
}
</pre><br /><span style="color: red">说明：</span><br /><span style="color: olive">通过@RunWith和@SuiteClasses标签来注释一个空的包含无参数构造函数的类来作为套件类，将需要组成套件运行的类加到@SuiteClasses的属性中即可。<br /></span><br />可以看到运行套件类的结果是2个测试类都进行了测试。<br /><br /><strong>5) 参数测试</strong><br />修改 testMultiple<br /><pre name="code" class="java">
    //@Ignore("忽略乘法测试")
    @Test
    public void testMultiple() {
        assertEquals(result,Math.multiple(faciend,multiplicator));
    }
</pre><br />编写参数方法：<br /><pre name="code" class="java">
@Parameters
    public static Collection multipleValues() {
        return Arrays.asList(new Object[][] {
        {3, 2, 6 },
        {4, 3, 12 },
        {21, 5, 105 },
        {11, 22, 242 },
        {8, 9, 72 }});
    }
</pre><br /><span style="color: red">说明：</span><br /><span style="color: olive">需要使用@Parameters标签注解一个静态的返回集合对象的方法<br /></span><br />增加成员变量和构造函数：<br /><pre name="code" class="java">
    int faciend;
    int multiplicator;
    int result;

    public MathTest(int faciend, int multiplicator, int result) {
        this.faciend = faciend;
        this.multiplicator = multiplicator;
        this.result = result;
    }
</pre><br />最后在给测试类增加如下注释：<br /><pre name="code" class="java">
@RunWith(Parameterized.class)
</pre><br /><br />完整的循环测试代码如下：<br /><pre name="code" class="java">
import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * @author bulargy.j.bai
 * @mail bulargy@gmail.com
 * @创建时间：Mar 11, 2008
 * @描述：
 */
@RunWith(Parameterized.class)
public class MathTest {
	int faciend;
	int multiplicator;
	int result;

	public MathTest(int faciend, int multiplicator, int result) {
		 this.faciend = faciend;
		 this.multiplicator = multiplicator;
		 this.result = result;
	}

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Test(expected=ArithmeticException.class)
	public void testDivide() {
		assertEquals(3,Math.divide(9,3));
		assertEquals(3,Math.divide(10,3));
		Math.divide(10,0);//除数不能为0，会抛出异常

	}

	//@Ignore("忽略乘法测试")
	@Test
	public void testMultiple() {
		assertEquals(result,Math.multiple(faciend,multiplicator));
	}
	
	@Parameters
	public static Collection multipleValues() {
	 return Arrays.asList(new Object[][] {
        {3, 2, 6 },
        {4, 3, 12 },
        {21, 5, 105 },
        {11, 22, 242 },
        {8, 9, 72 }});
	}

}</pre><br />OK,大功告成。测试看看吧，测试类跑了5次~~。<br /><br />大概就这么多体会了，总得来说JUnit4以后测试还是很方便的，顺便这个是仅仅是为了做例子，实际使用中由于JUnit4不再受命名的限制，所以应该划分更细粒度的测试来完成，一个方法的正确，异常，错误及边界数据完全可以分开来写测试方法。由于大部分情况资源只用加载和释放一次就足够，大大提高的测试的速度，再也不会有以前那样点开测试然后去泡咖啡的情况出现了~~呵呵~~
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/170312#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 11 Mar 2008 22:09:51 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/170312</link>
        <guid>http://bulargy.javaeye.com/blog/170312</guid>
      </item>
      <item>
        <title>Java 接口大全、面向接口编程、什么时候使用接口。选择Java接口还是抽象类</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/167618" style="color:red;">http://bulargy.javaeye.com/blog/167618</a>&nbsp;
          发表时间: 2008年03月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在一个面向对象的系统中，系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下，各个对象内部是如何实现自己的对系统设计人员来讲就不那么重要了；而各个对象之间的协作关系则成为系统设计的关键。小到不同类之间的通信，大到各模块之间的交互，在系统设计之初都是要着重考虑的，这也是系统设计的主要工作内容。面向接口编程我想就是指按照这种思想来编程吧！实际上，在日常工作中，你已经按照接口编程了，只不过如果你没有这方面的意识，那么你只是在被动的实现这一思想；表现在频繁的抱怨别人改的代码影响了你（接口没有设计到），表现在某个模块的改动引起其他模块的大规模调整（模块接口没有很好的设计）等等。<br /><br />　　Booch先生那天谈到Interaction Designer，它就是指做这类设计的人，只不过层次更高一些。我想目前我们的软件设计队伍中，这类人是最缺乏的人才之一。<br />非接口编程？是不是就是面向过程的编程思想？<br /><br />　　1.关于接口的理解。<br />　　接口从更深层次的理解，应是定义（规范，约束）与实现（名实分离的原则）的分离。<br />　　我们在一般实现一个系统的时候，通常是将定义与实现合为一体，不加分离的，我认为最为理解的系统设计规范应是所有的定义与实现分离，尽管这可能对系统中的某些情况有点繁烦。<br />　　接口的本身反映了系统设计人员对系统的抽象理解。<br />　　接口应有两类：第一类是对一个体的抽象，它可对应为一个抽象体(abstract class)；<br />　　第二类是对一个体某一方面的抽象，即形成一个抽象面（interface）；<br />　　一个体有可能有多个抽象面。<br />　　抽象体与抽象面是有区别的。<br /><br />　　2.设计接口的另一个不可忽视的因素是接口所处的环境(context,environment)，系统论的观点：环境是系统要素所处的空间与外部影响因素的总和。任何接口都是在一定的环境中产生的。因此环境的定义及环境的变化对接口的影响是不容忽视的，脱离原先的环境，所有的接口将失去原有的意义。<br /><br />　　3.按照组件的开发模型（3C），它们三者相辅相成，各司一面，浑然一体，缺一不可。<br /><br />　　面向对象是指，我们考虑问题时，以对象为单位，考虑它的属性及方法<br />　　面向过程是指，我们考虑问题时，以一个具体的流程（事务过程）为单位，考虑它的实现<br />　　接口设计与非接口设计是针对复用技术而言的，与面向对象（过程）不是一个问题<br /><br />　　我认为：UML里面所说的interface是协议的另一种说法。并不是指com的interface，CORBA的interface，Java的interface，Delphi的interface，人机界面的interface或NIC的interface。<br /><br />　　在具体实现中，是可以把UML的interface实现为语言的interface，分布式对象环境的interface或其它什么 interface，但就理解UML的interface而言，指的是系统每部分的实现和实现之间，通过interface所确定的协议来共同工作。<br /><br />　　所以我认为，面向interface编程，原意是指面向抽象协议编程，实现者在实现时要严格按协议来办。也就是BillJoy同志说的，一边翻rfc，一边写代码的意思。面向对象编程是指面向抽象和具象。抽象和具象是矛盾的统一体，不可能只有抽象没有具象。一般懂得抽象的人都明白这个道理。但有的人只知具象却不知抽象为何物。<br /><br />　　所以只有interface没有实现，或只有实现而没有interface者是没有用的，反OO的。<br /><br />　　所以还是老老实实面向对象编程，面向协议编程，或者什么都不面向，老老实实编程。<br /><br />　　但是我很讨厌讨论这样的术语，不如我们谈谈什么叫面向领导的编程？面向用户的编程？领导和用户有时都很BT，我们就面向BT编程？<br /><br /><br /><br />选择Java接口还是抽象类<br /><br />很多人有过这样的疑问：为什么有的地方必须使用接口而不是抽象类，而在另一些地方，又必须使用抽象类而不是接口呢？或者说，在考虑Java类的一般化问题时，很多人会在接口和抽象类之间犹豫不决，甚至随便选择一种。<br /><br />　　实际上接口和抽象类的选择不是随心所欲的。要理解接口和抽象类的选择原则，有两个概念很重要：对象的行为和对象的实现。如果一个实体可以有多种实现方式，则在设计实体行为的描述方式时，应当达到这样一个目标：在使用实体的时候，无需详细了解实体行为的实现方式。也就是说，要把对象的行为和对象的实现分离开来。既然Java的接口和抽象类都可以定义不提供具体实现的方法，在分离对象的行为和对象的实现时，到底应该使用接口还是使用抽象类呢？<br /><br /><br />通过抽象类建立行为模型<br /><br /><br />　　在接口和抽象类的选择上，必须遵守这样一个原则：行为模型应该总是通过接口而不是抽象类定义。为了说明其原因，下面试着通过抽象类建立行为模型，看看会出现什么问题。<br /><br />　　假设要为销售部门设计一个软件，这个软件包含一个“发动机”（Motor）实体。显然无法在发动机对象中详细地描述发动机的方方面面，只能描述某些对当前软件来说重要的特征。至于发动机的哪些特征是重要的，则要与用户（销售部门）交流才能确定。<br /><br />　　销售部门的人要求每一个发动机都有一个称为马力的参数。对于他们来说，这是惟一值得关心的参数。基于这一判断，可以把发动机的行为定义为以下行为。<br /><br />　　行为1：查询发动机的马力，发动机将返回一个表示马力的整数。<br /><br />　　虽然现在还不清楚发动机如何取得马力这个参数，但可以肯定发动机一定支持这个行为，而且这是所有发动机惟一值得关注的行为特征。这个行为特征既可以用接口定义，也可以用抽象类定义。为了说明用抽象类定义可能出现的问题，下面用抽象类建立发动机的行为模型，并用Java方法描述行为1，代码如下：<br />   <br /><pre name="code" class="java">
public abstract Motor{            
         abstract public int getHorsepower();            
      }
</pre><br /><br />　　在Motor抽象类的基础上构造出多种具体实现，例如A型发动机、B型发动机等，再加上系统的其它部分，最后得到1.0版的软件并交付使用。一段时间过去了，现在要设计2.0版的软件。在评估2.0版软件需求的过程中，发现一小部分发动机是电池驱动的，而电池需要一定的充电时间。销售部门的人希望能够通过计算机查阅充电时间。根据这一要求定义一个新的行为，如图1所示。<br /><br />　　行为2：查询电驱动发动机的充电时间，发动机将返回一个表示充电时间的整数。<br /><br />　　用Java方法来描述这个行为，代码如下：<br /><pre name="code" class="java">
public abstract BatteryPoweredMotor extends Motor{           
        abstract public int getTimeToRecharge();          
      }
</pre> <br /><br />　　在销售部门的软件中，电驱动发动机也以类的形式实现，但这些类从BatteryPoweredMotor而不是Motor派生。这些改动加入到2.0版软件之后，销售部门很满意。随着业务的不断发展，不久之后光驱动的发动机出现了。销售部门要求光驱动发动机需要一定光能才能运转，光能以流明（Lumen）度量。这个信息对客户很重要，因为下雨或多云的天气里，某些光驱动发动机可能无法运转。销售部门要求为软件增加对光驱动发动机的支持，所以要定义一个新的行为。<br /><br />　　行为3：查询光驱动发动机能够正常运转所需要的最小流明数，发动机返回一个整数。<br /><br />　　再定义一个抽象类并把行为3转换成Java方法，代码如下：<br /><br /><pre name="code" class="java">
public abstract SolarPoweredMotor extends Motor{            
         abstract public int getLumensToOperate();          
      }
</pre><br /><br />　　如图1所示，SolarPoweredMotor和BatteryPoweredMotor都从Motor抽象类派生。在整个软件中，90％以上的代码以相同的方式对待所有的发动机。偶尔需要检查一下发动机是光驱动还是电驱动，使用instanceof实现，代码如下：<br /><br /><pre name="code" class="java">
if (instanceof SolarPoweredMotor){...}       
         if (instanceof BatteryPoweredMotor){...}
</pre><br /><br />　　无论是哪种发动机，马力这个参数都很重要，所以在所有派生的抽象类（SolarPoweredMotor和BatteryPoweredMotor）中，getHorsepower()方法都有效。<br /><br />　　现在销售部门又有了一种新的发动机，它是一种既有电驱动又有光驱动的双重驱动发动机。光驱动和电驱动的行为本身没有变化，但新的发动机同时支持两种行为。在考虑如何定义新型的光电驱动发动机时，接口和抽象类的差别开始显示出来了。新的目标是在增加新型发动机的前提下尽量少改动代码。因为与光驱动发动机、电驱动发动机有关的代码已经过全面的测试，不存在已知的Bug。为了增加光电驱动发动机，要定义一个新的 SolarBatteryPowered抽象类。如果让SolarBatteryPowered从Motor抽象类派生， SolarBatteryPowered将不支持针对光驱动发动机和电驱动发动机的instanceof操作。也就是说，如果查询一个光电驱动的发动机是光驱动的，还是电驱动的，得到的答案是：都不是。<br /><br />　　如果让SolarBatteryPowered从SolarPoweredMotor（或BatteryPoweredMotor）抽象类派生，类似的问题也会出现，SolarBatteryPowered将不支持针对BatteryPoweredMotor（或 SolarPoweredMotor）的instanceof操作。从行为上看，光电驱动的发动机必须同时从两个抽象类派生，但Java语言不允许多重继承。之所以会出现这个问题，根本的原因在于使用抽象类不仅意味着定义特定的行为，而且意味着定义实现的模式。也就是说，应该定义一个发动机如何获得行为的模型，而不仅仅是声明发动机具有某一个行为。<br /><br /><br />通过接口建立行为模型<br /><br /><br />　　如果用接口来建立行为模型，就可以避免隐含地规定实现模式。例如，前面的几个行为改用接口定义如下。<br /><br />　　行为1：<br /><pre name="code" class="java">
public interface Motor(){          
        public int getHorsepower();          
      }
</pre> <br /><br />行为2：<br /><pre name="code" class="java">
public interface BatteryPoweredMotor extends Motor(){           
  public int getTimeToRecharge();          
}
</pre><br /><br />行为3：<br /><pre name="code" class="java">
public interface SolarPoweredMotor extends Motor{           
  abstract public int getLumensToOperate();          
}
</pre><br /><br />　　现在光电驱动的发动机可以描述为：<br /><br /><pre name="code" class="java">
public DualPoweredMotor implements SolarPoweredMotor, BatteryPoweredMotor{}
</pre><br /><br />　　DualPoweredMotor只继承行为定义，而不是行为的实现模式，如图2所示。<br /><br />　　在使用接口的同时仍旧可以使用抽象类，不过这时抽象类的作用是实现行为，而不是定义行为。只要实现行为的类遵从接口定义，即使它改变了父抽象类，也不用改变其它代码与之交互的方式。特别是对于公用的实现代码，抽象类有它的优点。抽象类能够保证实现的层次关系，避免代码重复。然而，即使在使用抽象类的场合，也不要忽视通过接口定义行为模型的原则。从实践的角度来看，如果依赖于抽象类来定义行为，往往导致过于复杂的继承关系，而通过接口定义行为能够更有效地分离行为与实现，为代码的维护和修改带来方便。<br /><br /><br /><br />Java接口特性学习<br />在Java中看到接口，第一个想到的可能就是C++中的多重继承和Java中的另外一个关键字abstract。从另外一个角度实现多重继承是接口的功能之一，接口的存在可以使Java中的对象可以向上转型为多个基类型，并且和抽象类一样可以防止他人创建该类的对象，因为接口不允许创建对象。<br /><br />interface关键字用来声明一个接口，它可以产生一个完全抽象的类，并且不提供任何具体实现。interface的特性整理如下：<br /><br />1. 接口中的方法可以有参数列表和返回类型，但不能有任何方法体。<br /><br />2. 接口中可以包含字段，但是会被隐式的声明为static和final。<br /><br />3. 接口中的字段只是被存储在该接口的静态存储区域内，而不属于该接口。<br /><br />4. 接口中的方法可以被声明为public或不声明，但结果都会按照public类型处理。<br /><br />5. 当实现一个接口时，需要将被定义的方法声明为public类型的，否则为默认访问类型，Java编译器不允许这种情况。<br /><br />6. 如果没有实现接口中所有方法，那么创建的仍然是一个接口。<br /><br />7. 扩展一个接口来生成新的接口应使用关键字extends，实现一个接口使用implements。<br /><br /><br /><br />interface在某些地方和abstract有相似的地方，但是采用哪种方式来声明类主要参照以下两点：<br /><br />1. 如果要创建不带任何方法定义和成员变量的基类，那么就应该选择接口而不是抽象类。<br /><br />2. 如果知道某个类应该是基类，那么第一个选择的应该是让它成为一个接口，只有在必须要有方法定义和成员变量的时候，才应该选择抽象类。因为抽象类中允许存在一个或多个被具体实现的方法，只要方法没有被全部实现该类就仍是抽象类。<br /><br /><br />以上就是接口的基本特性和应用的领域，但是接口绝不仅仅如此，在Java语法结构中，接口可以被嵌套，既可以被某个类嵌套，也可以被接口嵌套。这在实际开发中可能应用的不多，但也是它的特性之一。需要注意的是，在实现某个接口时，并不需要实现嵌套在其内部的任何接口，而且，private接口不能在定义它的类之外被实现。 <br /><br /><br />转帖http://tb.blog.csdn.net/TrackBack.aspx?PostId=540947
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/167618#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 04 Mar 2008 10:00:45 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/167618</link>
        <guid>http://bulargy.javaeye.com/blog/167618</guid>
      </item>
      <item>
        <title>7种设计坏味道和11种原则</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/167616" style="color:red;">http://bulargy.javaeye.com/blog/167616</a>&nbsp;
          发表时间: 2008年03月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          转的文章，出处太多了，也不知道到底哪个才是真的出处。<br /><br />  7种设计坏味道<br />1.僵化性： 很难对系统进行改动，因为每个改动都会迫使许多对系统其他部分的其它改动。<br /><br />2.脆弱性： 对系统的改动会导致系统中和改动的地方在概念上无关的许多地方出现问题。<br /><br />3.牢固性： 很难解开系统的纠结，使之成为一些可在其他系统中重用的组件。<br /><br />4.粘滞性： 做正确的事情比做错误的事情要困难。<br /><br />5.复杂性(不必要的)： 设计中包含有不具任何直接好处的基础结构。<br /><br />6.重复性(不必要的)： 设计中包含有重复的结构，而该重复的结构本可以使用单一的抽象进行统一。<br />  7.晦涩性： 很难阅读、理解。没有很好地表现出意图。<br /><br />11种原则 - Principle<br /><br />----类原则<br /><br />1.单一职责原则 - Single Responsibility Principle(SRP)<br /><br />就一个类而言，应该仅有一个引起它变化的原因。<br /><br />(职责即为“变化的原因”。)<br /><br />2.开放-封闭原则 - Open Close Principle(OCP)<br /><br />软件实体（类、模块、函数等）应该是可以扩展的，但是不可修改。<br /><br />(对于扩展是开放的,对于更改是封闭的.<br /><br />关键是抽象.将一个功能的通用部分和实现细节部分清晰的分离开来.<br /><br />开发人员应该仅仅对程序中呈现出频繁变化的那些部分作出抽象.<br /><br />拒绝不成熟的抽象和抽象本身一样重要. )<br /><br />3.里氏替换原则 - Liskov Substitution Principle(LSP)<br /><br />子类型(subclass)必须能够替换掉它们的基类型(superclass)。<br /><br />4.依赖倒置原则(IoCP) 或 依赖注入原则 - Dependence Inversion Principle(DIP)<br /><br />抽象不应该依赖于细节。细节应该依赖于抽象。<br /><br />(Hollywood原则: "Don't call us, we'll call you".<br /><br />程序中所有的依赖关系都应该终止于抽象类和接口。<br /><br />针对接口而非实现编程。<br /><br />任何变量都不应该持有一个指向具体类的指针或引用。<br /><br />任何类都不应该从具体类派生。<br /><br />任何方法都不应该覆写他的任何基类中的已经实现了的方法。)<br /><br />5.接口隔离原则(ISP)<br /><br />不应该强迫客户依赖于它们不用的方法。<br /><br />接口属于客户，不属于它所在的类层次结构。<br /><br />(多个面向特定用户的接口胜于一个通用接口。)<br /><br />----包内聚原则<br /><br />6.重用发布等价原则(REP)<br /><br />重用的粒度就是发布的粒度。<br /><br />7.共同封闭原则(CCP)<br /><br />包中的所有类对于同一类性质的变化应该是共同封闭的。<br /><br />一个变化若对一个包产生影响，<br /><br />则将对该包中的所有类产生影响，<br /><br />而对于其他的包不造成任何影响。<br /><br />8.共同重用原则(CRP)<br /><br />一个包中的所有类应该是共同重用的。<br /><br />如果重用了包中的一个类，<br /><br />那么就要重用包中的所有类。<br /><br />(相互之间没有紧密联系的类不应该在同一个包中。)<br /><br />----包耦合原则<br /><br />9.无环依赖原则(ADP)<br /><br />在包的依赖关系图中不允许存在环。<br /><br />10.稳定依赖原则(SDP)<br /><br />朝着稳定的方向进行依赖。<br /><br />应该把封装系统高层设计的软件（比如抽象类）放进稳定的包中，<br /><br />不稳定的包中应该只包含那些很可能会改变的软件（比如具体类）。<br /><br />11.稳定抽象原则(SAP)<br /><br />包的抽象程度应该和其稳定程度一致。<br /><br />(一个稳定的包应该也是抽象的，一个不稳定的包应该是抽象的. )<br /><br />----其它扩展原则----<br /><br />12.BBP(Black Box Principle)黑盒原则<br /><br />多用类的聚合，少用类的继承。<br /><br />13.DAP(Default Abstraction Principle)缺省抽象原则<br /><br />在接口和实现接口的类之间引入一个抽象类,这个类实现了接口的大部分操作.<br /><br />14.IDP(Interface Design Principle)接口设计原则<br /><br />规划一个接口而不是实现一个接口。<br /><br />15.DCSP(Don't Concrete Supperclass Principle)不要构造具体的超类原则<br /><br />避免维护具体的超类。<br /><br />16.迪米特法则<br />一个类只依赖其触手可得的类。
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/167616#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 04 Mar 2008 09:51:18 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/167616</link>
        <guid>http://bulargy.javaeye.com/blog/167616</guid>
      </item>
      <item>
        <title>61条面向对象设计的经验原则</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/167119" style="color:red;">http://bulargy.javaeye.com/blog/167119</a>&nbsp;
          发表时间: 2008年03月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          摘抄自《OOD 启示录》--Arthur J.Riel <br /><br />(1)所有数据都应该隐藏在所在的类的内部。p13<br /><br />(2)类的使用者必须依赖类的共有接口，但类不能依赖它的使用者。p15<br /><br />(3)尽量减少类的协议中的消息。p16<br /><br />(4)实现所有类都理解的最基本公有接口[例如，拷贝操作(深拷贝和浅拷贝)、相等性判断、正确输出内容、从ASCII描述解析等等]。 p16<br /><br />(5)不要把实现细节(例如放置共用代码的私有函数)放到类的公有接口中。p17<br />如果类的两个方法有一段公共代码，那么就可以创建一个防止这些公共代码的私有函数。<br /><br />(6)不要以用户无法使用或不感兴趣的东西扰乱类的公有接口。p17<br /><br />(7)类之间应该零耦合，或者只有导出耦合关系。也即，一个类要么同另一个类毫无关系，要么只使用另一个类的公有接口中的操作。 p18<br /><br />(8)类应该只表示一个关键抽象。p19<br />包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包影响，则将对包中的所有类产生影响，而对其他的包不造成任何影响 .<br /><br />(9)把相关的数据和行为集中放置。p19<br />设计者应当留意那些通过get之类操作从别的对象中获取数据的对象。这种类型的行为暗示着这条经验原则被违反了。<br /><br />(10)把不相关的信息放在另一个类中(也即：互不沟通的行为)。p19<br />朝着稳定的方向进行依赖.<br /><br />(11)确保你为之建模的抽象概念是类，而不只是对象扮演的角色。p23<br /><br />(12)在水平方向上尽可能统一地分布系统功能，也即：按照设计，顶层类应当统一地共享工作。p30<br /><br />(13)在你的系统中不要创建全能类/对象。对名字包含Driver、Manager、System、Susystem的类要特别多加小心。p30<br />规划一个接口而不是实现一个接口。<br /><br />(14)对公共接口中定义了大量访问方法的类多加小心。大量访问方法意味着相关数据和行为没有集中存放。p30<br /><br />(15)对包含太多互不沟通的行为的类多加小心。p31<br />这个问题的另一表现是在你的应用程序中的类的公有接口中创建了很多的get和set函数。<br /><br />(16)在由同用户界面交互的面向对象模型构成的应用程序中，模型不应该依赖于界面，界面则应当依赖于模型。p33<br /><br />(17)尽可能地按照现实世界建模(我们常常为了遵守系统功能分布原则、避免全能类原则以及集中放置相关数据和行为的原则而违背这条原则) 。p36<br /><br />(18)从你的设计中去除不需要的类。p38<br />一般来说，我们会把这个类降级成一个属性。<br /><br />(19)去除系统外的类。p39<br />系统外的类的特点是，抽象地看它们只往系统领域发送消息但并不接受系统领域内其他类发出的消息。<br /><br />(20)不要把操作变成类。质疑任何名字是动词或者派生自动词的类，特别是只有一个有意义行为的类。考虑一下那个有意义的行为是否应当迁移到已经存在或者尚未发现的某个类中。p40<br /><br />(21)我们在创建应用程序的分析模型时常常引入代理类。在设计阶段，我们常会发现很多代理没有用的，应当去除。p43<br /><br />(22)尽量减少类的协作者的数量。p52<br />一个类用到的其他类的数目应当尽量少。<br /><br />(23)尽量减少类和协作者之间传递的消息的数量。p55<br /><br />(24)尽量减少类和协作者之间的协作量，也即：减少类和协作者之间传递的不同消息的数量。p55<br /><br />(25)尽量减少类的扇出，也即：减少类定义的消息数和发送的消息数的乘积。p55<br /><br />(26)如果类包含另一个类的对象，那么包含类应当给被包含的对象发送消息。也即：包含关系总是意味着使用关系。p55<br /><br />(27)类中定义的大多数方法都应当在大多数时间里使用大多数数据成员。p57<br /><br />(28)类包含的对象数目不应当超过开发者短期记忆的容量。这个数目常常是6。p57<br />当类包含多于6个数据成员时，可以把逻辑相关的数据成员划分为一组，然后用一个新的包含类去包含这一组成员。<br /><br />(29)让系统功能在窄而深的继承体系中垂直分布。p58<br /><br />(30)在实现语义约束时，最好根据类定义来实现。这常常会导致类泛滥成灾，在这种情况下，约束应当在类的行为中实现，通常是在构造函数中实现，但不是必须如此。p60<br /><br />(31)在类的构造函数中实现语义约束时，把约束测试放在构造函数领域所允许的尽量深的包含层次中。p60<br /><br />(32)约束所依赖的语义信息如果经常改变，那么最好放在一个集中式的第3方对象中。p60<br /><br />(33)约束所依赖的语义信息如果很少改变，那么最好分布在约束所涉及的各个类中。p60<br /><br />(34)类必须知道它包含什么，但是不能知道谁包含它。p61<br /><br />(35)共享字面范围(也就是被同一个类所包含)的对象相互之间不应当有使用关系。p61<br /><br />(36)继承只应被用来为特化层次结构建模。p74<br /><br />(37)派生类必须知道基类，基类不应该知道关于它们的派生类的任何信息。p74<br /><br />(38)基类中的所有数据都应当是私有的，不要使用保护数据。p75<br />类的设计者永远都不应该把类的使用者不需要的东西放在公有接口中。<br /><br />(39)在理论上，继承层次体系应当深一点，越深越好。p77<br /><br />(40)在实践中，继承层次体系的深度不应当超出一个普通人的短期记忆能力。一个广为接受的深度值是6。p77<br /><br />(41)所有的抽象类都应当是基类。p81<br /><br />(42)所有的基类都应当是抽象类。p82<br /><br />(43)把数据、行为和/或接口的共性尽可能地放到继承层次体系的高端。p85<br /><br />(44)如果两个或更多个类共享公共数据(但没有公共行为)，那么应当把公共数据放在一个类中，每个共享这个数据的类都包含这个类。 p88<br /><br />(45)如果两个或更多个类有共同的数据和行为(就是方法)，那么这些类的每一个都应当从一个表示了这些数据和方法的公共基类继承。 p89<br /><br />(46)如果两个或更多个类共享公共接口(指的是消息，而不是方法)，那么只有他们需要被多态地使用时，他们才应当从一个公共基类继承。 p89<br /><br />(47)对对象类型的显示的分情况分析一般是错误的。在大多数这样的情况下，设计者应当使用多态。p89<br /><br />(48)对属性值的显示的分情况分析常常是错误的。类应当解耦合成一个继承层次结构，每个属性值都被变换成一个派生类。 p96<br /><br />(49)不要通过继承关系来为类的动态语义建模。试图用静态语义关系来为动态语义建模会导致在运行时切换类型。p97<br /><br />(50)不要把类的对象变成派生类。对任何只有一个实例的派生类都要多加小心。p99<br /><br />(51)如果你觉得需要在运行时刻创建新的类，那么退后一步以认清你要创建的是对象。现在，把这些对象概括成一个类。 p103<br /><br />(52)在派生类中用空方法(也就是什么也不做的方法)来覆写基类中的方法应当是非法的。p103<br /><br />(53)不要把可选包含同对继承的需要相混淆。把可选包含建模成继承会带来泛滥成灾的类。p108<br /><br />(54)在创建继承层次时，试着创建可复用的框架，而不是可复用的组件。p112<br /><br />(55)如果你在设计中使用了多重继承，先假设你犯了错误。如果没犯错误，你需要设法证明。p120<br /><br />(56)只要在面向对象设计中用到了继承，问自己两个问题：(1)派生类是否是它继承的那个东西的一个特殊类型？(2)基类是不是派生类的一部分？p121<br /><br />(57)如果你在一个面向对象设计中发现了多重继承关系，确保没有哪个基类实际上是另一个基类的派生类。p122<br /><br />(58)在面向对象设计中如果你需要在包含关系和关联关系间作出选择，请选择包含关系。p123<br /><br />(59)不要把全局数据或全局函数用于类的对象的薄记工作。应当使用类变量或类方法。p140<br /><br />(60)面向对象设计者不应当让物理设计准则来破坏他们的逻辑设计。但是，在对逻辑设计作出决策的过程中我们经常用到物理设计准则。 p149<br /><br />(61)不要绕开公共接口去修改对象的状态。p164
          <br/>
          <span style="color:red;">
            <a href="http://bulargy.javaeye.com/blog/167119#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 04 Mar 2008 00:18:18 +0800</pubDate>
        <link>http://bulargy.javaeye.com/blog/167119</link>
        <guid>http://bulargy.javaeye.com/blog/167119</guid>
      </item>
      <item>
        <title>equals和==的一些测试！</title>
        <author>bulargy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bulargy.javaeye.com">bulargy</a>&nbsp;
          链接：<a href="http://bulargy.javaeye.com/blog/96983" style="color:red;">http://bulargy.javaeye.com/blog/96983</a>&nbsp;
          发表时间: 2007年02月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div>前几天去一公司笔试，题目都很基础，但是都很让人郁闷，总觉得会又不是十分透彻的感觉，特别是equals和==的一些题目，回来自己测试了一些，和大家分享！<br />首先是几个基本类型的用法：</div><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><div><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000">&nbsp;com.bulagy;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_21_49_Open_Image" onclick="this.style.display='none'; document.getElementById('_21_49_Open_Text').style.display='none'; document.getElementById('_21_49_Closed_Image').style.display='inline'; document.getElementById('_21_49_Closed_Text').style.display='inline';" align="top" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_21_49_Closed_Image" onclick="this.style.display='none'; document.getElementById('_21_49_Closed_Text').style.display='none'; document.getElementById('_21_49_Open_Image').style.display='inline'; document.getElementById('_21_49_Open_Text').style.display='inline';" align="top" alt="" style="DISPLAY: none" /></span><span id="_21_49_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**&nbsp;*/</span><span id="_21_49_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;*&nbsp;</span><span style="COLOR: #808080">@author</span><span style="COLOR: #008000">&nbsp;bulargy<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;*<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" id="_75_2715_Open_Image" onclick="this.style.display='none'; document.getElementById('_75_2715_Open_Text').style.display='none'; document.getElementById('_75_2715_Closed_Image').style.display='inline'; document.getElementById('_75_2715_Closed_Text').style.display='inline';" align="top" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" id="_75_2715_Closed_Image" onclick="this.style.display='none'; document.getElementById('_75_2715_Closed_Text').style.display='none'; document.getElementById('_75_2715_Open_Image').style.display='inline'; document.getElementById('_75_2715_Open_Text').style.display='inline';" align="top" alt="" style="DISPLAY: none" /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;EqualsDemo&nbsp;</span><span id="_75_2715_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id="_75_2715_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" id="_79_102_Open_Image" onclick="this.style.display='none'; document.getElementById('_79_102_Open_Text').style.display='none'; document.getElementById('_79_102_Closed_Image').style.display='inline'; document.getElementById('_79_102_Closed_Text').style.display='inline';" align="top" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" id="_79_102_Closed_Image" onclick="this.style.display='none'; document.getElementById('_79_102_Closed_Text').style.display='none'; document.getElementById('_79_102_Open_Image').style.display='inline'; document.getElementById('_79_102_Open_Text').style.display='inline';" align="top" alt="" style="DISPLAY: none" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="_79_102_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/**&nbsp;*/</span><span id="_79_102_Open_Text"><span style="COLOR: #008000">/**</span><span style="COLOR: #008000"><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="COLOR: #808080">@param</span><span style="COLOR: #008000">&nbsp;args<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">*/</span></span><span style="COLOR: #000000"><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" id="_144_2712_Open_Image" onclick="this.style.display='none'; document.getElementById('_144_2712_Open_Text').style.display='none'; document.getElementById('_144_2712_Closed_Image').style.display='inline'; document.getElementById('_144_2712_Closed_Text').style.display='inline';" align="top" alt="" /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" id="_144_2712_Closed_Image" onclick="this.style.display='none'; document.getElementById('_144_2712_Closed_Text').style.display='none'; document.getElementById('_144_2712_Open_Image').style.display='inline'; document.getElementById('_144_2712_Open_Text').style.display='inline';" align="top" alt="" style="DISPLAY: none" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id="_144_2712_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span><span id="_144_2712_Open_Text"><span style="COLOR: #000000">{<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000">&nbsp;boo1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000">&nbsp;boo2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000">&nbsp;boo3&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000">&nbsp;boo4&nbsp;;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000">&nbsp;boo5&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;boo1;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">boolean&nbsp;boo5&nbsp;=&nbsp;new&nbsp;boolean();</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">不合法的定义</span><span style="COLOR: #008000"><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">boo1==boo2&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">(boo1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">boo2));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">boo1==boo3&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">(boo1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">boo3));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">System.out.println(&quot;boo1==boo2&nbsp;?&nbsp;&quot;+(boo1.equals(boo2)));</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">没有equals方法</span><span style="COLOR: #008000"><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">boo1==boo5&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">(boo1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">boo5));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">System.out.println(&quot;boo3==boo4&nbsp;?&nbsp;&quot;+(boo3==boo4));</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">boo4未初始化</span><span style="COLOR: #008000"><br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" /></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println();<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">abcd</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;String(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">abcd</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">);<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s3&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">abcd</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s4&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;String(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">abcd</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">);<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s5&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;s1;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s6&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;s2;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s7;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s8&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;String();<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s9&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;&quot;</span><span style="COLOR: #000000">;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">s1==s2&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">(s1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">s2));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">s1.equals(s2)&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">s1.equals(s2));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">s1==s3&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">(s1</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">s3));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">s1.equals(s3)&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">s1.equals(s3));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">s2==s4&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">(s2</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">s4));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">s2.equals(s4)&nbsp;?&nbsp;</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">s2.equals(s4));<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000