﻿<?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>IT博客网-korezu Inc-随笔分类-技术专题</title><link>http://www.cnitblog.com/tilan/category/4337.html</link><description>软件开发 软件配置 项目管理 软件工程</description><language>zh-cn</language><lastBuildDate>Thu, 06 Mar 2008 15:10:55 GMT</lastBuildDate><pubDate>Thu, 06 Mar 2008 15:10:55 GMT</pubDate><ttl>60</ttl><item><title>一个老工程师给年轻工程师的十大忠告</title><link>http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Sun, 09 Dec 2007 09:24:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/37526.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/37526.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/37526.html</trackback:ping><description><![CDATA[<div id=postmessage_1235418 style="FONT-SIZE: 10pt">[1]好好规划自己的路，不要跟着感觉走！根据个人的理想决策安排，绝大部分人并不指望成为什么院士或教授，而是希望活得滋润一些，爽一些。那么，就需要慎重安排自己的轨迹。从哪个行业入手，逐渐对该行业深入了解，不要频繁跳槽，特别是不要为了一点工资而转移阵地，从长远看，这点钱根本不算什么，当你对一个行业有那么几年的体会，以后钱根本不是问题。频繁地动荡不是上策，最后你对哪个行业都没有摸透，永远是新手！<br>[2]可以做技术，切不可沉湎于技术。千万不可一门心思钻研技术！给自己很大压力，如果你的心思全部放在这上面，那么注定你将成为孔乙己一类的人物！适可而止为之，因为技术只不过是你今后前途的支柱之一，而且还不是最大的支柱，除非你只愿意到老还是个工程师！<br>[3]不要去做技术高手，只去做综合素质高手！在企业里混，我们时常瞧不起某人，说他&#8220;什么都不懂，凭啥拿那么多钱，凭啥升官！&#8221;这是普遍的典型的工程师的迂腐之言。8051很牛吗？人家能上去必然有他的本事，而且是你没有的本事。你想想，老板搞经营那么多年，难道见识不如你这个新兵？人家或许善于管理，善于领会老板意图，善于部门协调等等。因此务必培养自己多方面的能力，包括管理，亲和力，察言观色能力，攻关能力等，要成为综合素质的高手，则前途无量，否则只能躲在角落看示波器！技术以外的技能才是更重要的本事！！从古到今，美国*本，一律如此！<br>[4]多交社会三教九流的朋友！不要只和工程师交往，认为有共同语言，其实更重要的是和<a onclick="javascript:tagshow(event, '%C6%E4%CB%FB');" href="javascript:;" target=_self>其他</a>类人物交往，如果你希望有朝一*当老板或高层管理，那么你整*面对的就是这些人。了解他们的经历，思维习惯，爱好，<a onclick="javascript:tagshow(event, '%D1%A7%CF%B0');" href="javascript:;" target=_self>学习</a>他们处理问题的模式，了解社会各个角落的现象和问题，这是以后发展的巨大的本钱，没有这些以后就会笨手笨脚，跌跌撞撞，遇到重重困难，交不少学费，成功的概率大大降低！<br>[5]知识涉猎不一定专，但一定要广！多看看其他方面的书，金融，财会，进出口，税务，法律等等，为以后做一些积累，以后的用处会更大！会少交许多学费！！<br>[6]抓住时机向技术管理或市场销售方面的转变！要想有前途就不能一直搞<a onclick="javascript:tagshow(event, '%BF%AA%B7%A2');" href="javascript:;" target=_self>开发</a>，适当时候要转变为管理或销售，前途会更大，以前搞技术也没有白搞，以后还用得着。搞管理可以培养自己的领导能力，搞销售可以培养自己的市场概念和思维，同时为自己以后发展积累庞大的人脉！应该说这才是前途的真正支柱！！！<br>[7]逐渐克服自己的心里弱点和性格缺陷！多疑，敏感，天真（贬义，并不可爱），犹豫不决，胆怯，多虑，脸皮太薄，心不够黑，教条式思维。。。这些工程师普遍存在的性格弱点必须改变！很难吗？只在床上想一想当然不可能，去帮朋友守一个月地摊，包准有效果，去实践，而不要只想！不克服这些缺点，一切不可能，甚至连项目经理都当不好--尽管你可能技术不错！<br>[8]工作的同时要为以后做准备！建立自己的工作环境！及早为自己配置一个工作环境，装备电脑，示波器（可以买个二手的），仿真器，编程器等，业余可以接点活，一方面接触市场，培养市场感觉，同时也积累资金，更重要的是准备自己的产品，咱搞技术的没有钱，只有技术，技术的代表不是学历和证书，而是产品，拿出象样的产品，就可技术转让或与人合作搞企业！先把东西准备好，等待机会，否则，有了机会也抓不住！<br>[9]要学会善于推销自己！不仅要能干，还要能说，能写，善于利用一切机会推销自己，树立自己的品牌形象，很必要！要创造条件让别人了解自己，不然老板怎么知道你能干？外面的投资人怎么相信你？提早把自己推销出去，机会自然会来找你！搞个个人主页是个好注意！！特别是培养自己在行业的名气，有了名气，高薪机会自不在话下，更重要的是有合作的机会...<br>[10]该出手时便出手！永远不可能有100%把握！！！条件差不多就要大胆去干，去闯出自己的事业，不要犹豫，不要彷徨，干了不一定成功，但至少为下一次冲击积累了经验，不干永远没出息，而且要干成必然要经历失败。不经历风雨，怎么见彩虹，没有人能随随便便成功！</div>
<br><img src ="http://www.cnitblog.com/tilan/aggbug/37526.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-12-09 17:24 <a href="http://www.cnitblog.com/tilan/archive/2007/12/09/37526.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>初步搭建yui-ext开发环境</title><link>http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Wed, 07 Nov 2007 06:09:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/35975.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/35975.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/35975.html</trackback:ping><description><![CDATA[<p>如果看过yui-ext的例子，相信大家很想把它用在实际项目中去，我这两个星期都在研究它，国内几乎没有资料，只能从http://www.jackslocum.com的论坛找，我现在简单介绍一下我的实际开发环境：</p>
<p>我的项目原来的开发环境是Struts+Spring1.2.8+Hibernate3.1.2，现在要把页面的jsp+jstl，和Struts的Action转换成yui-ext的Ajax页面，简单实现数据列表、翻页和添加、修改、删除等功能。</p>
<p>1. 数据交换，要从Struts环境的Action通过request对象传递数据给jsp页面，如果用Ajax，比较常用的是XML转换和Json转换，我选择了Json，因为用json-lib包可以在java端用很方便的把对象转换成Json格式，在页面可以调用脚本eval()转换成javascript的数组对象。</p>
<p>1) json-lib转换java对象(下载json-lib:http://json-lib.sourceforge.net) <br>Action例子：(example.do)代码中加入： <br>response.setContentType("text/xml;charset=utf-8"); <br>JSONArray jsonArray = JSONArray.fromObject(list); <br>response.getWriter().print("{datalist:" + jsonArray + "}"); <br>return null; <br>简单说明：把action的return mapping改成null,因为现在使用response对象进行数据传递，fromObject(list)中的list包括就是页面需要调用显示的数据，可以是其他java对象，String、bean或Map。</p>
<p>2) JSONDataModel调用Action(example.do) <br>yui-ext通过JSONDataModel.js把json格式转换成javascript的数组对象 <br>js例子： <br>var schema = { <br>root: 'datalist', <br>id: 'nothing', <br>fields: ['a','b', 'c', 'd']</p>
<p>dataModel= new YAHOO.ext.grid.JSONDataModel(schema); <br>dataModel.load('http://xxx/example.do');</p>
<p>说明：schema的root参数要和action传递的json数据头list对应，这里new JSONDataModel后，JSONDataModel会把example.do返回的json数据转换成dataModel的数组，JSONDataModel继承于LoadableDataModel，JSONDataModel只复杂转换json数据，其他由继承的类实现，这是yui-ext的特点，你可以自己写DataModel继承父类，转换自己的数据格式，yui-ext提供了JSONDataModel和XMLDataModel两种数据格式转换。</p>
<p>3) 使用grid显示dataModel数据 <br>js例子： <br>var grid = new YAHOO.ext.grid.Grid('example-grid', dataModel, colModel); <br>grid.render(); <br>jsp页面例子： <br>&lt;div id="example-grid" style="border: 1px solid #cccccc; overflow: hidden; width: 535px; height: 225px;"&gt;&lt;/div&gt; <br>说明：colModel的使用看example，grid绑定dataModel后，在页面的&lt;Div&gt;显示grid。 <br></p><img src ="http://www.cnitblog.com/tilan/aggbug/35975.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-11-07 14:09 <a href="http://www.cnitblog.com/tilan/archive/2007/11/07/35975.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用maven的感想 </title><link>http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Mon, 29 Oct 2007 08:28:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/35541.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/35541.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/35541.html</trackback:ping><description><![CDATA[使用maven2一段时间了，我基本把我自己能够迁移的project都转换为maven2 project，以下是我的一点感想。<br><br>（原作者温少，转载请注明）<br>
<h2>乱世盼英雄</h2>
<br>现在的软件开发，比过去的软件开发要复杂得多。包括在参与开发的人数、代码规模、复杂的需求、依赖包的复杂性、使用到更多的技术、多个项目之间的复杂依赖关系。<br><br>现在的开发人员，要掌握的技术要比过去的开发人员要多，不是现在的开发人员比以前的开发人员本身更优秀，而是拥有更多的资料、更多的学习机会、更多更大规模的时间，同时软件行业也在发展。说一句题外话，老程序员，如果不与时俱进，靠老本，是无法和新一代程序员竞争的，当然，老程序员，拥有更多的经验，掌握新技术的速度更快，这又是另外一回事。<br><br>开发人员掌握的技术更复杂了，项目用得的技术自然也是更复杂，例如一个web项目，可能使用到很多技术，面向对象、泛型、or-mapping、依赖注入（spring-framework）、全文检索（lucene）、数据库、集群、工作流、web service等等。<br><br>由于使用了多种技术，这些技术可能是JDK提供的，也可能是第三方开源组织提供的，或者不同的商业公司提供的。<br><br>于是出现了一个新的难题，就是包依赖复杂性。以前，你很难想象你的代码依赖数十个不同开源组织、商业公司提供的库。例如，我们经常使用的log4j、junit、easymock、ibatis、springframework，每个组件都有悠久的历史，存在不同的版本，他们之间版本还有依赖关系。<br><br>项目依赖的复杂性，经常的，一个较大部门有10-30个项目是常事，项目之间有不同版本的依赖关系，部门与部门之间的项目也存在复杂的版本依赖关系。<br><br>Eclipse本身提供Project的依赖，但是简单的依赖显然解决不了问题。例如Project B依赖Project A，Project A依赖第三方的jar包abc-1.0.jar，那么需要在两个项目的lib下都存放abc-1.0.jar，这产生冗余，当Project数量多起来，这个冗余就产生了管理问题，如果需要将abc-1.0.jar升级为abc-1.1.jar，则需要在两个Project中同时修改，如果Project数量达到10个以上，而且是不同项目组维护的项目，这个就是非常麻烦的事情。而且Project A修改依赖，为啥需要Project B也作相应的修改呢？<br><br>需要解决此问题，就需要在Project A的包中描述其依赖库的信息，例如在META-INFO记录所以来的abc-1.0.jar等。Eclipse的plug-in拥有类似的方案，但是这样一来，就使得开发Project B的项目组，需要把Project A的代码从源代码库中check out出来。在依赖链末端的项目组是很惨的。<br><br>由于Project数量众多，关系复杂，dailybuild的ant脚本编写成了很麻烦的事情，使用Project依赖的方式，更加使得编写dailybuild ant script是非常痛苦的事情。<br><br>当然也可以不使用project依赖的方式，而使用artifact lib的依赖方式，但是artifact lib的依赖方式，就是同时修改多个project，互相调试时带来了痛苦。<br><br>在以前，我们面临这些问题时，唯一的感觉就是，这事情TMD的太麻烦，几乎是失控了。<br><br>maven的出现，解决这种问题看到了希望。maven出现的原因就是，现在的开发管理复杂度达到了一定程序，需要专门的开发管理工具，这样的工具需要涵盖开发的各个阶段，包括工程建立、配置依赖管理、编译、测试、产生分析报告、部署、产生制品等阶段。目前，各个阶段的工具都存在，但是不是集成的，对使用带来了很大麻烦。maven集成了这些工具，提高了统一的环境，使得使用更简单。<br><br>现在maven非常流行了，apache上所有java project都已经build by maven，其他跟进的开源项目非常多，例如mule、hibernat等等，商业公司也很多在采用，sun公司提供有maven2 repository。<br><br>现在，2007年，如果你还没采用maven project，你可能需要思考一下，是否你使用了不恰当的方式管理的代码，或者你落伍了？<br>
<h2>maven的一些常用任务</h2>
compile 编译代码<br>test 运行单元测试<br>package 打包代码<br>site 产生报告，例如java doc、junit的通过率报告和覆盖率报告、findbugs的分析报告等等。<br>assembly 使用需求产生assembly，例如把生成一个程序目录，包括bin、config、lib、logs，把依赖包放在lib中。<br>deploy 部署制品到repository中。<br><br>这些都是常用的任务，在以前编写脚本很麻烦，现在在maven中，一切都是很简单，需要仔细设置时功能又强大到令人惊叹，例如site的fml，assembly。<br><br>
<h2>maven资源库</h2>
maven官方提供了一个常用lib的资源库，包括apache的所有java项目，开源常用的基本都能够找到，例如mule、c3p0、easymock、hibernate、springframework、json等等，版本齐全，任你挑选。<br><br>可以部署本地资源库代理提高下载速度。使用maven proxy。<br><br>
<h2>maven体系结构</h2>
<br>maven使用plug-in的体系，使用很好的自动更新策略，本身用到的jar都是lazy download的，可以指定download的repository。这样，初始下载的maven是一个很小的程序，使用的时候从本地的资源库或者本地代理资源库高速下载lib。maven的插件体系，充分利用了internet的资源丰富和局域网的高速带宽，使用本地repository时，可以享受到每秒钟数M的下载速度，感觉就是，人生真是美妙！<br><br>elcipse的plug-in体系，就不是那么好用了，我们使用eclipse的find and install功能下载或者更新插件时，慢如蜗牛，依赖缺失时的烦恼，更新一个plug-in，可能耗费你数个小时，第三方的plug-in的下载服务器可能更慢，例如subversive的plugin-in，有一次我花了两天还没下载好，只好使用下载工具下载好，copy到plug-in目录下。此时，我们总是感叹，人生总是有很多烦恼事啊！<br><br>相比之下，高下立判！在此我不是说eclipse的plug-in体系结构设计不好，eclipse的插件体系非常优秀，但是还有很大改进空间！<br><img src ="http://www.cnitblog.com/tilan/aggbug/35541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-10-29 16:28 <a href="http://www.cnitblog.com/tilan/archive/2007/10/29/35541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IBM WebSphere Application Server 诊断和调优(一)续 </title><link>http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Mon, 20 Aug 2007 06:25:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/32112.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/32112.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/32112.html</trackback:ping><description><![CDATA[<p>个人体会： <br>IBM的WAS服务器使用难度上，也许比BEA的WLS服务器难10倍，学习成本很高，我05年末几乎花了两个月时间在它上面，天天研究那几本红皮书，测试。IBM的红皮书质量真的非常不错，但太多了。</p>
<p>WAS是定位在大型企业应用，集群系统。它的cell--&gt;node--&gt;server，profiles架构以及server上的cluster做得还挺强大的。但是，也许99%的用户都用不到，而且它的cell--&gt;node--&gt;server架构在WLS的domain--&gt;server类似，但WLS非常易用。不过对于大型网站的前端http server，IBM自己加工的那个apache，和WAS配合还是挺好的。</p>
<p>在部署方面，WAS比WLS烦琐得多，虽然也支持命令行和自动部署，但比WLS难，因为发布一个app，大概要更新18个xml配置文件，n个步骤，手动更改配置文件几乎不现实，而WLS只需要把package丢过去就ok了，production环境下也只要控制台选择一下就ok了。在WAS下，我碰到一次是，集群同步时出错，下次几个server都启动不起来，手动修改serverindex.xml等相关文件才搞定，幸好那只是测试环境。</p>
<p>我用JProfiler监测WAS和WLS，WAS运行一段时间后，当时我那个环境启动了300多个thread，而WLS只启动50多个，而且WAS启动一般三分钟，而WLS可能半分钟。</p>
<p>另外，一般IBM的WAS运行在AIX、小型机环境下，而小型机的内存可能有个8G，这时候，最好是把WAS做成纵向分布式，也就是说，一个AIX上安装两个WAS。这个我当初也不明白，现在有体会了，因为这样比较好利用内存，因为JVM的heap设置过大并不好，很影响GC性能。还有，可能你的实际的应用怎么都不可能超过2G的heap。</p>
<p>给大家推荐几本WAS部分用到的IBM红皮书吧，他对我摆平我们这个大项目的WAS问题非常有帮助，我只推荐我仔细读过的、认为最值得看的，它们都可以在ibm红皮书网站下载： <br>《WebSphere Application Server V6 System Management &amp; Configuration.pdf》：WAS教材 <br>《WebSphere Application Server V6 Planning and Design WebSphere Handbook Series.pdf》：WAS教材高级版本，怎么去规划WAS。 <br>《WebSphere Version 6 Web Services Handbook Development and Deployment.pdf》：Web Services教材，对Web Services本身讲解也很深入浅出。 <br>《WebSphere Application Server V6 Security Handbook.pdf》：WAS安全必备书籍 <br>《WebSphere Application Server V6 Problem Determination for Distributed Platforms.pdf》：WAS出问题了，看它吧。不过，这本书太初级，恐怕出了问题，它70％都不能帮你解决，还是去找IBM技术支持吧。</p>
<p>建议：WAS出问题了，一定要耐心研读红皮书，了解WAS的原理，盲目尝试往往都得不偿失，因为你做点改动，启动重启一次都要5分钟，重启20多次，一般一天时间就过去了，也就是说你只能知道有20个不行的尝试，但也许还有100个不行的尝试等着你，呵呵。总之，尝试你永远都不知道真正为什么会出错。</p>
<p>忘了，一定深入了解WAS里面的Classloader原理，这对你部署过程中出问题非常有帮助，譬如xml找不到，log打印不出来呀，我曾经也是饱受折磨。用好它，必须有深厚的理论基础，它不是给普通开发人员用的，反正我认为他的易用性是很失败的。</p><img src ="http://www.cnitblog.com/tilan/aggbug/32112.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-08-20 14:25 <a href="http://www.cnitblog.com/tilan/archive/2007/08/20/32112.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IBM WebSphere Application Server 诊断和调优(一) </title><link>http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Mon, 20 Aug 2007 05:48:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/32110.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/32110.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/32110.html</trackback:ping><description><![CDATA[<p>近段时间，我们项目中用到的WebSphere应用服务器(WAS)，但在客户的production环境下极不稳定，经常宕机。给客户造成非常不好的影响，同时，也给项目组很大压力。为此，我们花了近一个月时间对其诊断，现在基本上稳定了，需要继续观察一段时间。现在我主要将工作做一个阶段性的总结。 <br>我们的产品环境是：WAS6.0＋DB2 8.1＋AIX5.3＋RS/6000。在该产品环境下，出现的问题非常多，现象如下： <br>WAS经常不稳定、宕机几乎一天一次，经常报告OutOfMemory(内存泄漏吗？NO)。 <br>DB2连接数过大，有时把DB2撑死，有时也把AIX撑死。 <br>AIX虚拟内存报错、分页报错、IO也报错、还有很多其它莫名奇妙的错。</p>
<p>总是，每次问题发生的现象和理论上的总是不一致，导致我们不知道从何入手，也无从检测自己的优化参数。咨询过多次IBM技术支持，只解决了某些局部问题。 <br>虽然问题依然存在，但我想，解决问题的思路、特别是理论基础，还是有一些规律和原则。</p>
<p>对于WAS这块，我近段时间的主要时间集中在以下几个方面(时间顺序)： <br>1、Java性能监测工具：Jprofiler，也用到Jprobe。后来发现Jprofiler在AIX下几乎不可用。 <br>2、IBM Java虚拟机和WAS技术细节，特别是IBM JVM的GC原理，我发现它和sun、bea的差别很大。 <br>3、IBM的heap分析器Heap Analyzer、GCCollector。这两个事后监测工具非常实用，特别是我们的产品运行环境，非测试环境。 <br>4、某些Application的怀疑和诊断。 <br>5、AIX诊断，我几乎没有这个能力，只能常规监测一下，需另请高人。</p>
<p>我打算将本文分成以下几个部分总结： <br>JVM原理、IBM JVM的GC策略和调优。 <br>Jprofiler和IBM工具的实际体会 <br>WAS的诊断体会和AIX调优</p>
<p>下面开始主题吧，可能比较零碎，另外，开始的理论篇基本上看书都可以，我只是总结一下，再添加一些自己的理解。</p>
<p>以下是我参考的最重要的两本电子书和一些网站： <br>《Inside Java Vrtual Machine》:半部分有约四章我认为非常棒，其它章节可能意义不大。 <br>《The Java Virtual Machine Specification, 2nd》：前半部分有两三章很不错，不过可以对照上一本书看。 <br>sun的hotspot虚拟机技术：<a href="http://java.sun.com/javase/technologies/hotspot/" target=blank><u><font color=#0000ff>http://java.sun.com/javase/technologies/hotspot/ </font></u></a><br>BEA的JRockit虚拟机技术：<a href="http://edocs.bea.com/jrockit/geninfo/genintro/index.html" target=blank><u><font color=#0000ff>http://edocs.bea.com/jrockit/geninfo/genintro/index.html </font></u></a>JVM技术文档入口，虚拟机理论，内存泄漏诊断等的索引页。 <br>IBM诊断资料：<a href="http://www-128.ibm.com/developerworks/java/jdk/diagnosis/" target=blank><u><font color=#0000ff>http://www-128.ibm.com/developerworks/java/jdk/diagnosis/</font></u></a> 上面有一个500多页的pdf文档，对IBM JVM技术和诊断讲解很深入。</p>
<p>我不得不提的是，在查资料这块，BEA和Sun都有很好的官方文档和论坛支持，并且官方文档导航非常好。虽然IBM的诊断资料也不少，但需要搜索，其搜索是很痛苦的。而且，IBM官方论坛很差。如果用IBM的产品出问题，切记：找IBM技术支持，千万不要蒙着头搞！反正它们的产品很少免费。说实话，它们的技术支持还是挺负责的，一般会为你推荐很多support资料，而该资料往往都在developerworks网站上，属于support那个频道，但你就是搜不着。</p>
<p><strong>Java虚拟机规范概要</strong> <br>研究Java虚拟机，首先要了解Sun的Java虚拟机规范。现在，该实现版本很多，如比较有名的Sun、IBM、BEA、Apple、HP、MS、Apache Harmony。它们都实现了JVM规范，但有各自扩展。譬如，针对IBM虚拟机的堆碎片导致OutOfMemory（OOM），在Sun的虚拟机上就不会发生。Sun的JVM有maxPermSize的概念，IBM就没有，如果你设置这个参数，虚拟机根本就启动不了。 <br>比较有意思的是，学Java，就一定要了解各种规范，这和MS的风格很不一样。Sun总是在定义一些规范，实现都留给各厂商。我们除了理解规范本身外，一定要理解规范和实现之间的关系，譬如JDBC规范和JDBC驱动的关系，它们是怎么组合到一起的。要是你用过php的xml解析库，或db函数，就会体会深刻，它们可没有什么规范可言，所以每个数据库厂商的db函数用法都不一样。我推荐大家研读一下HSQLDB的jdbc和Tomcat的servlet相关实现，因为我认为它们还是比较好懂的。 <br>JVM规范只是定义一个虚拟机该做什么，但它并没有要求你该怎么做。例如我们最常见的Servlet规范，在该规范中，有HttpServletRequest、HttpServletResponse，HttpSession等接口，但它们的实现都留给了各个容器厂商。遗憾的是，规范留下的空白，会把我们这些开发人员给整惨了：容器间移植有时候就是恶梦。譬如J2EE并没有SSO规范，但它很重要，我以前专门针对它做过WebSphere AppServer和Weblogic AppServer的SSO项目，差别还是不小，不过还是有点共通，那就是都遵循JAAS规范。</p>
<p><strong>JVM的结构</strong> <br>从功能上分，Java虚拟机主要由六个部分组成，可以分成三类： <br>第一类：JVM API：就是我们最常用的Java API，它是开发人员和Java交互的入口，它主要是JAVA_HOME/jre/lib下的运行时类库rt.jar和编译相关的tools.jar</p>
<p>第二类：JVM内部组件 <br><strong>类装载器</strong>(ClassLoader)：将Byte Array的 .class文件装载、链接和初始化。 <br><strong>内存管理</strong>(Memory Managent)：为对象分配内存，以及释放内存。后者就是垃圾回收Garbage Collector（GC）。由于JVM最复杂的、最影响性能的就是GC，所以内存管理一般就指垃圾回收。 <br><strong>诊断接口</strong>(Diagostics Interface)：这主要体现在JVMTI(jdk1.4下的JVMPI和JVMDI)，它主要用来诊断程序的问题和性能，一般提供给工具厂商实现。如eclispe IDE下的debug功能，Jprofiler性能调优工具。 <br><strong>类解释器</strong>(Interpreter)：解释装载进虚拟机的class对象，包括JIT等特性相关。</p>
<p>第三类：平台相关接口(Platform Interface)：主要为了跨操作系统平台重用JVM代码，不过，它和我们开发人员关系不大。</p>
<p>在以上六个组件中，我们开发人员最关心的是<strong>ClassLoader</strong>和<strong>GC</strong>，用Java做系统框架、容器和它们密切相关。做业务系统时一些基础代码也和它们打交道，譬如最常用的Class.forName(),Thread.currentThread.getContextClassLoader()。我们仔细想想，为什么是上面两个问题？因为，它和我们class的整个生命周期最为相关：怎么将一个class和相关class加载进来，class实例什么时候创建，什么时候被销毁？ <br>所以，下面的部分我们要专门讨论这些问题。</p>
<p><strong>ClassLoader</strong> <br>JVM主要有三类ClassLoader：Bootstrap、Extention、Application，该三类ClassLoader从上到下是分级(hierarchy)结构，遵循代理模型(Delegation Model)。 <br>Tip：大家可以看看sun.misc.Launcher的源码，Bootstrap和Extention就在该文件里。该src可以在sun的网站上下载该压缩包，约60M(jdk-1_5_0-src-scsl.zip)，它不在jdk自带的那个src.zip里。</p>
<p>Bootstrap ClassLoader：也称为primordial(root) class loader。主要是负责装载jre/lib下的jar文件，当然，你也可以通过-Xbootclasspath参数定义。该ClassLoader不能被Java代码实例化，因为它是JVM本身的一部分。</p>
<p>Extention ClassLoader：该ClassLoader是Bootstrap classLoader的子class loader。它主要负责加载jre/lib/ext/下的所有jar文件。只要jar包放置这个位置，就会被虚拟机加载。一个常见的、类似的问题是，你将mysql的低版本驱动不小心放置在这儿，但你的Web应用程序的lib下有一个新的jdbc驱动，但怎么都报错，譬如不支持JDBC2.0的DataSource，这时你就要当心你的新jdbc可能并没有被加载。这就是ClassLoader的delegate现象。常见的有log4j、common-log、dbcp会出现问题，因为它们很容易被人塞到这个ext目录，或是Tomcat下的common/lib目录。</p>
<p>Application ClassLoader：也称为System ClassLoaer。它负责加载CLASSPATH环境变量下的classes。缺省情况下，它是用户创建的任何ClassLoader的父ClassLoader，我们创建的standalone应用的main class缺省情况下也是由它加载(通过Thread.currentThread().getContextClassLoader()查看)。 <br>我们实际开发中，用ClassLoader更多时候是用其加载classpath下的资源，特别是配置文件，如ClassLoader.getResource()，比FileInputStream直接。</p>
<p>ClassLoader是一种分级(<strong>hierarchy</strong>)的代理(<strong>delegation</strong>)模型。 <br>Delegation：其实是Parent Delegation，当需要加载一个class时，当前线程的ClassLoader首先会将请求代理到其父classLoader，递归向上，如果该class已经被父classLoader加载，那么直接拿来用，譬如典型的ArrayList，它最终由Bootstrap ClassLoader加载。并且，每个ClassLoader只有一个父ClassLoader。 <br>Class查找的位置和顺序依次是：Cache、parent、self。 <br>Hierarchy：上面的delegation已经暗示了一种分级结构，同时它也说明：一个ClassLoader只能看到被它自己加载的classes，或是看到其父(parent) ClassLoader或祖先(ancestor) ClassLoader加载的Classes。 <br>在一个单虚拟机环境下，标识一个类有两个因素：class的全路径名、该类的ClassLoader。</p>
<p>我碰到的一个典型的例子是：在做WAS的SSO开发时，由于我们的类是由WAS在启动时加载，该ClassLoader比下面的部署的Applicaton的ClassLoader的级别高。所以，在我们自己的类中没法用到应用程序的连接池，必须自建。 <br>代理模型是Java安全模型的保证。譬如，我们自己写一个String.java，并且编译、package到自己的java.lang包下。按照代理模型，当前线程的ClassLoader会将其代理到父ClassLoader，父ClassLoader(最终会是Bootstrap)会找到rt.jar下的String.class，也就是说我们的String.class不会捣乱。</p>
<p><strong>自定义ClassLoader</strong> <br>我们前面说过，自定义ClassLoader的缺省父ClassLoader是Application ClassLoader。一般的应用开发用不到它，但我们最好理解。因为在内存泄漏查找、应用程序部署出问题时，很多都和它有关。 <br>譬如，内存泄漏是怎么产生的？这就涉及到ClassLoader和Class的生命周期。我曾经碰到这样一个问题：我们的程序用到了Webwork和Spring框架，当部署到Tomcat下时没有任何问题，但部署到WAS下，报告找不到Webwork的xml的DTD文件，而且Spring的日志也总是失效。Why？因为解析xml dtd时，用的是IBM的Xerces，不是我们的。而Spring日志问题是因为应用程序用的是WAS的Common-log.jar，而不是我们的。将应用的ClassLoader从默认的Parent-First，改成Parent-Last就可以解决，不过我们项目中用到其它库，又发生了其它问题。</p>
<p>一般来说，用到自定义ClassLoader有三种情况： <br>1、应用框架可以自己控制Classes的目录，并且自动部署。 <br>我读过Jive公司的Wildfire(著名的即时通讯服务器)，它自己有一套应用框架，非常灵活，遵循该框架插件规范的的第三方的plug-in放置在指定目录可以自动部署，实现某些扩展功能，如文件传输、语音聊天。 <br>2、区分用户代码 <br>这被广泛应用在Servlet容器和类似容器，譬如EJB Container设计中，大家看到Tomcat下有common、server、share三个目录吧(ClassLoader顺序从左到有)，另外也有用户应用的WEB-INF目录，它是我们自己开发的。 <br>3、允许Classes卸载 <br>如果没有自定义的ClassLoader，那么我们自己应用中的classes永远都不能被卸载，因为这些类被Application ClassLoader加载后cache起来了，我们的classes一直对该ClassLoader有引用，而该系统级的ClassLoader永远都不会被卸载，除非JVM shutdown了。JSP和Servlet的动态部署就用到这个特性。</p>
<p>待续.......</p>
<p>Note: 还有JVM运行时(Runtime)架构，ClassLoader加载class过程没有总结，这两部分我觉得太重要了，但内容太多，写不完啊。 <br>这部分内容，《Inside Java Virtual Machine》讲解非常清楚，BEA的官方网站这部分也非常不错，要理解深刻，我建议结合JProfiler工具，非常直观。</p><img src ="http://www.cnitblog.com/tilan/aggbug/32110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-08-20 13:48 <a href="http://www.cnitblog.com/tilan/archive/2007/08/20/32110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java开发者论坛--sqlsoft.com.cn</title><link>http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Sat, 11 Aug 2007 16:01:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/31654.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/31654.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/31654.html</trackback:ping><description><![CDATA[<a  href="http://www.sqlsoft.com.cn/">http://www.SQLSoft.com.cn</a> 成立上线，欢迎IT人士加入<br><br><a  href="http://www.sqlsoft.com.cn/">http://www.SQLSoft.com.cn</a>&nbsp;  <br>开源框架下载站<br><br><a  href="http://bbs.sqlsoft.com.cn/">http://bbs.SQLSoft.com.cn</a><br>java开发者论坛<br><br><a  href="http://www.sqlsoft.com.cn/">SQLSoft.com.cn</a> 寻求资源合作<br>详细请联系：<br>msn:j.joy@msn.com&nbsp; <br>qq:269309672<br><br><br><img src ="http://www.cnitblog.com/tilan/aggbug/31654.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-08-12 00:01 <a href="http://www.cnitblog.com/tilan/archive/2007/08/12/31654.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jquery是继prototype之后又一个优秀的Javascrīpt框架</title><link>http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Fri, 03 Aug 2007 06:07:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/31186.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/31186.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/31186.html</trackback:ping><description><![CDATA[<p>Jquery是继prototype之后又一个优秀的Javascrīpt框架。对prototype我使用不多，简单了解过。但使用上jquery之后，马上被她的优雅吸引住了。有人使用这样的一比喻来比较prototype和jquery：prototype就像Java，而jquery就像ruby.实际上我比较喜欢java（少接触Ruby&nbsp;罢了）但是jquery的简单的实用的确有相当大的吸引力啊！在项目里我把jquery作为自已唯一的框架类包。使用其间也有一点点心得，其实这些心得，在jquery的文档上面也可能有讲，不过还是记下来，以备忘罢。</p>
<p><br>&nbsp;<br><strong>一，找到你了！</strong>&nbsp;<br>还记得$()这个东西吧？prototype还是DWR都使用了这个函数代替document.getElementById()。没错，jquery也跟风了。为达到document.getElementById()的目的，jquery是这样写的：&nbsp;<br><br><br>代码<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">var&nbsp;someElement&nbsp;=&nbsp;$("#myId");&nbsp;&nbsp;</div>
<br>看起来比其他两个框架的要多了一个#，好，看看下面的用法：&nbsp;<br>代码
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$("div&nbsp;p");(1)&nbsp;&nbsp;&nbsp;<br>$("div.container")(2)&nbsp;&nbsp;&nbsp;<br>$("div&nbsp;#msg");(3)&nbsp;&nbsp;&nbsp;<br>$("table&nbsp;a",context);(4)&nbsp;</div>
&nbsp;<br><br>在prototype里看过这样的写法吗？第一行代码得到所有&lt;div&gt;标签下的&lt;p&gt;元素。第二行代码得到class&nbsp;为container的&lt;div&gt;元素,第三行代码得到&lt;div&gt;标签下面id为msg的元素。第四行代码得到context为上下文的table里面所有的连接元素。&nbsp;<br>如果你熟悉CSS，Xpath，你会觉得这些写法很眼熟！对了。正是。看出奥妙了吧。jquery就是通过这样的方式来找到Dom对象里面的元素。跟CSS的选择器相类似。&nbsp;<br><br><strong>二，Jquery对象？</strong>&nbsp;<br>jquery提供了很多便利的函数，如each(fn)，但是使用这些函数的前提是：你使用的对象是Jquer对象。使一个Dom对象成为一个Jquery对象很简单，通过下面一些方式（只是一部分）：&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">var&nbsp;a&nbsp;=&nbsp;$("#cid");(1)&nbsp;&nbsp;&nbsp;<br>var&nbsp;b&nbsp;=&nbsp;$("&lt;p&gt;hello&lt;/p&gt;");(2)&nbsp;&nbsp;&nbsp;<br>var&nbsp;c&nbsp;=&nbsp;document.createElement("table");&nbsp;var&nbsp;tb&nbsp;=&nbsp;$(c);&nbsp;&nbsp;</div>
<br><br><strong>三，代替body标签的onload</strong>&nbsp;<br>这个惯例，也许是除了$()之外，用得最多的地方了。下面一段代码：&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$(document).ready(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;alert("hello");&nbsp;&nbsp;&nbsp;<br>});(1)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&lt;body&nbsp;onload="alert('hello');"&gt;（2）&nbsp;</div>
&nbsp;<br><br>上面两段代码是等价的。但代码1的好处是做到表现和逻辑分离。并且可以在不同的js文件中做相同的操作，即$(document).ready&nbsp;(fn)可以在一个页面中重复出现，而不会冲突。基本上Jqeury的很多plugin都是利用这个特性，正因为这个特性，多个plugin共同使用起来，在初始化时不会发生冲突。&nbsp;<br>不管怎么说，这个惯例可以分离javascrīpt与HTML。推荐使用。&nbsp;<br><br><strong>四，事件机制</strong>&nbsp;<br>我大量使用的事件可能就是button的onclick了。以前习惯在input&nbsp;元素上写onclick&nbsp;=&nbsp;"fn()",使用jquery可以使javascrīpt代码与html代码分离，保持HTML的清洁，还可以很轻松地绑定事件，甚至你可以不知道&#8220;事件&#8221;这个名词。&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$(document).ready(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;$("#clear").click(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert("i&nbsp;am&nbsp;about&nbsp;to&nbsp;clear&nbsp;the&nbsp;table");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;});&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;$("form[0]").submit(validate);&nbsp;&nbsp;&nbsp;<br>});&nbsp;&nbsp;&nbsp;<br>function&nbsp;validate(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;//do&nbsp;some&nbsp;form&nbsp;validation&nbsp;&nbsp;&nbsp;<br>}</div>
&nbsp;&nbsp;<br><br><strong>五，同一函数实现set&amp;get</strong>&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">$("#msg").html();&nbsp;&nbsp;&nbsp;<br>$("#msg").html("hello");&nbsp;&nbsp;</div>
<br><br>上面两行代码，调用了同样的函数。但结果却差别很大。&nbsp;<br>第一行是返回指定元素的HTML值，第二行则是将hello这串字符设置到指定元素中。jquery的函数大部分有这样的特性。<br>&nbsp;<br><strong>六，ajax</strong>&nbsp;<br>这是一个ajax横行的时代。多少人，了不了解ajax的都跟着用上一把。呵。使用jquery实现ajax同样简单异常&nbsp;<br><br>代码<br>
<p class=code>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">
<p class=code>$.get("search.do",{id:1},rend);&nbsp;&nbsp;&nbsp;<br>function&nbsp;rend(xml){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;alert(xml);&nbsp;&nbsp;&nbsp;<br>}&nbsp;(1)&nbsp;&nbsp;&nbsp;<br>$.post("search.do",{id:1},rend);&nbsp;&nbsp;&nbsp;<br>function&nbsp;rend(xml){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;alert(xml);&nbsp;&nbsp;&nbsp;<br>}&nbsp;(2)&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>$("#msg").ajaxStart(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;this.html("正在加载。。。。");&nbsp;&nbsp;&nbsp;<br>});(3)&nbsp;&nbsp;&nbsp;<br>$("#msg").ajaxSuccess(function(){&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;this.html("加载完成！");&nbsp;&nbsp;&nbsp;<br>});(4)&nbsp;&nbsp;</p>
</div>
<p class=code><br><br>这些都是较常用的方法，get和post用法一样。第一个参数是异步请求的url，第二个为参数，第三个回调方法。&nbsp;<br>3，4的方法会在指定的Dom对象上绑定响应ajax执行的事件。当然，jquery的AJAX相关的函数不仅是这些，有兴趣可以去研究再多。<br>&nbsp;<br><strong>七，渐入淡出</strong>&nbsp;<br><br>代码<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 5px; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 5px; MARGIN: 5px 20px; BORDER-LEFT: #cccccc 1px solid; PADDING-TOP: 5px; BORDER-BOTTOM: #cccccc 1px solid">
<p class=code>$("#msg").fadeIn("fast");&nbsp;&nbsp;&nbsp;<br>$("#msg").fadeOut("slow");&nbsp;&nbsp;</p>
</div>
<p class=code><br><br>没错，上面两行代码已经分别实现了一个id为Msg的jquery对象的渐入和淡出。做一个像Gmail一样的动态加载通知条，用jquery就那么简单。两个函数接受的参数除了快慢等，还可以接收整型，作为渐入或淡出的完成时间，单位为MS。<br>&nbsp;<br><strong>八，plugin</strong>&nbsp;<br>这也是一个插件的时代。&nbsp;<br>jquery插件给我的感觉清一色的清洁，简单。如Jtip，要使用它的功能，只需要在你的元素的class上加上Jtip,并引入jtip.js及其样式即可以了。其他事情插件全包。我喜欢jquery的一个重要原因是发现她已经有了很多很好，很精彩的插件。&nbsp;<br>写得很烂。可能大家看不出jquery的好处。嗯，光听是没用的，试用一下吧。你会发觉很有趣。&nbsp;<br>暂时告一段落吧。待有新的发现再来分享。<br><br><strong>加一些Jquery的资源：</strong>&nbsp;<br>http://www.visualjquery.com/index.xml&nbsp;很好的API查询站点&nbsp;<br>http://jquery.com/demo/thickbox/&nbsp;知道lightBox吧，看看Jquery是怎样实现相同的东西&nbsp;<br>http://www.codylindley.com/blogstuff/js/jtip/&nbsp;Jtip，实用的提示工具&nbsp;<br>http://jquery.com/plugins/&nbsp;很多牛的插件。&nbsp;<br>http://15daysofjquery.com/jquery&nbsp;的15天教程<br></p><img src ="http://www.cnitblog.com/tilan/aggbug/31186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-08-03 14:07 <a href="http://www.cnitblog.com/tilan/archive/2007/08/03/31186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>八大原因让Linux远离普通用户</title><link>http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Thu, 31 May 2007 02:38:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/27851.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/27851.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/27851.html</trackback:ping><description><![CDATA[<p><span>【</span><strong><span>CSDN 2007.5.29 </span></strong><strong><span>译文】</span></strong><span>本文来自于<span>Linux Community</span>，</span><span>作者试图解答下面的问题</span><strong><span>：</span></strong>
<p align=left><strong><span>&nbsp;&nbsp; </span></strong><strong><span>&#8220;有如此多的</span></strong><strong><span>Linux</span></strong><strong><span>版本可供下载、安装并完全免费使用的替换方案，为什么普通电脑用户仍然会选择花费几百美金去购买</span></strong><strong><span>Windows</span></strong><strong><span>或</span></strong><strong><span>Mac</span></strong><strong><span>操作系统呢&#8221;？</span></strong></p>
<p align=left><span>总的来说，并不是所有人都讨厌</span><span>Windows</span><span>的：普通用户每天在使用他们的</span><span>Windows</span><span>电脑时并没有遇到很多麻烦。</span></p>
<p align=left><span>版本型号过多：</span> <span>人们在面对</span><span>Vista</span><span>时只需考虑是选择家用基本版还是升级版，但普通的用户该如何在</span><span>36</span><span>种不同口味的</span><span>Linux</span><span>中做出选择呢？人们说&#8220;选择一个合适</span><span>Linux</span><span>版本的感觉，有点象一个没有经验的人来到了星巴克咖啡馆，你期望能够点一杯普通咖啡</span><span>---</span><span>但你会马上意识到生活并不是那么简单，你需要跑出长队并做大量的研究，然后再一次走到柜台前。&#8221;</span></p>
<p align=left><span>人们需要确定的是硬件和软件都能很好的工作：&#8220;所有人在从</span><span>Windows</span><span>转到</span><span>Linux</span><span>时都需要从头开始考虑应用程序的问题</span><span>... ...</span><span>考虑每一个你所用应用程序的替代方案是一件很繁重的工作。&#8221;</span></p>
<p align=left><span>至于大多数人所关心的，（</span><span>Linux</span><span>）命令行又走了恐龙式的复杂路线：它提供的功能更强大了，就象是</span><span>Windows </span><span>的</span><span>PowerShell</span><span>（一种脚本技术），但是你确定普通用户也需要如此强大的功能吗？也许这对于系统管理员在维护服务器运行环境时会很有效，但普通用户甚至不需要知道它（命令行）的存在。</span></p>
<p align=left><span>&nbsp;Linux</span><span>桌面仍然很令人讨厌：但我认为这方面他们正在改进，</span><span>Ubuntu</span><span>桌面就比几年前的</span><span>KDE</span><span>或</span><span>Gnome</span><span>更加友好，再看</span><span>Bery1</span><span>桌面</span><span>... ...</span><span>确实令人惊讶！！但是我自己并非普通用户，我不认为我的律师朋友在写合同或文件的时候会发现它是实用的。</span></p>
<p align=left><span>由于</span><span>Mac</span><span>的影响：想要追求与众不同的人会选用</span><span>Mac</span><span>，它建立在</span><span>Unix</span><span>之上，但是所有的复杂性都隐藏在性感的</span><span>GUI</span><span>和围绕它建立的封闭</span><span>hw Apple</span><span>背后。</span></p>
<p align=left><span>谁来提供免费的技术支持？：大家会知道，周围人中&#8220;谁熟悉</span><span>Windows</span><span>系统&#8221;。在</span><span>Mac</span><span>系统下，这个问题更需要谨慎对待。但对于</span><span>Linux</span><span>，我真的怀疑象一个普通会计</span><span>Jane</span><span>，在她的朋友圈中是否会有人擅长</span><span>Linux</span><span>。</span></p>
<p align=left><span>冷静下来，这仅仅是一个操作系统！：在</span><span>Linux</span><span>社区里充满了新潮的男孩，他们把这个开源操作系统看得太严肃了，这让人觉得充满了攻击性，并且有太多</span><span>RTFM</span><span>（指只要查阅文件就可以解决，拿出来提问只是浪费别人时间的问题）问题。这让人们远离了</span><span>Linux</span><span>。</span></p>
<p align=left><span>　　我热爱</span><span>Linux</span><span>，我认为</span><span>Beryl</span><span>的桌面很好，强大的命令行功能很好，能够自由选择哪一个应用程序运行也很好，但是，就象我之前说的，我并不是一个普通用户，就象</span><span>98%</span><span>阅读我文章的读者（大多为</span><span>Linux</span><span>爱好者）一样。　</span></p>
<p align=left><span>　　　普通用户可不愿意花费整晚的时间对着电脑研究它们（</span><span>Linux</span><span>），仅仅为了让它们能够正常运行。</span><span>【<strong>翻译　付江】</strong></span></p><img src ="http://www.cnitblog.com/tilan/aggbug/27851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-05-31 10:38 <a href="http://www.cnitblog.com/tilan/archive/2007/05/31/27851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaFX Script将终结AJAX？还是另一种选择？</title><link>http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Thu, 31 May 2007 01:54:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/27843.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/27843.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/27843.html</trackback:ping><description><![CDATA[<h5>在JavaOne会议上，Sun负责软件业务的执行副总裁格林公布了JavaFX Script:一种用于编写能够在支持Java的PC和手机上运行的应用软件的更简单的脚本语言。理查德表示，通过JavaFX Script和JavaFX Mobile，Sun和其它Java</h5>
<div class=newscon>
<div><script type=text/javascript>show_ads_zone(13);</script><script language=JavaScript src="http://z.csdn.net/adjs.php?n=502871846&amp;what=zone:13&amp;charset=utf-8&amp;exclude=,&amp;referer=http%3A//www.google.com/search%3Fq%3Djavafx%26hl%3Dzh-CN%26lr%3D%26nxpt%3D20.0117770325710396876090" type=text/javascript></script>
<p>
<p>　　在JavaOne会议上，Sun负责软件业务的执行副总裁格林公布了JavaFX Script:一种用于编写能够在支持Java的PC和手机上运行的应用软件的更简单的脚本语言。</p>
<p><img alt="" src="http://images.csdn.net/20070509/490880355_2d1198a262.jpg"></p>
<p>　　<strong>JavaFX script构架图</strong></p>
<p>　　为了解决手机的兼容性问题，格林详细阐述了JavaFX Mobile:一种面向手机厂商、提高Java应用软件在不同手机间兼容性的软件包。</p>
<p>　　Sun官员还计划发布最后一部分的开放源代码的Java，并阐述与Java相关的开放源代码项目的管理规则。</p>
<p>　　Sun计划通过JavaFX Script复兴Java在小型设备和浏览器上的使用。格林说，Java不仅仅面向企业，还面向消费者。我们即将发布的脚本语言将极大地增加能够为这一平台开发内容的人的数量。</p>
<p>　　JavaFX Script是一种在生产效率和易用性方面好于Java的脚本语言，能够与Java紧密集成。开发人员可以利用JavaFX Script编写能够在支持Java的PC和手机上运行的应用软件。</p>
<p>　　Sun希望扩大编写与Java兼容的应用软件的开发人员数量，并利用对所谓富互联网应用软件日益增长的兴趣赚钱。</p>
<p>　　格林说，Sun还在反对这一想法：即它在富互联网应用软件领域已经落后。RedMonk分析师斯蒂芬说，微软、Adobe、许多小公司都在挺进这一领域。</p>
<p>　　Sun计划发布JavaFX Script的源代码，让其它公司利用它开发Web创作工具。格林表示，Sun还计划开发用于内容创作的脚本工具。</p>
<p>　　随着Web开发人员开发包括从媒体发布站点到桌面风格应用软件在内的更复杂的网络应用，富互联网应用已经成为软件开发方面最热门的领域之一。</p>
<p>　　Burton Group分析师理查德说，Java有着庞大的产品和厂商产业链，但它在前端设计方面的应用受到了兼容性和性能问题的影响。JavaFX Script可能会解决这一问题。</p>
<p>　　据Sun称，利用Java平台开发在桌面系统上运行软件的编程人员已经达到了500万。格林说，全球已经有20亿部手机预装有名为Java ME的Java软件。</p>
<p>　　理查德表示，通过JavaFX Script和JavaFX Mobile，Sun和其它Java许可客户将拥有更有吸引力的富互联网应用软件开发工具。</p>
<p>　　在过去两年中，脚本语言在主流应用开发方面越来越流行了。许多Web网站开发者和企业开发人员已经选择脚本语言作为Java或.Net的轻量级替代者。</p>
<p>　　与Ruby、PHP、Python等相比，与Java有关的脚本语言的优势是，Java编程人员能够很方便地利用既有的编程技能。</p>
<p>　　利用JavaFX Script编写的应用软件能够在Java Runtime Environment上运行。格林说，与Adobe的Apollo一样，开发人员可以利用完全相同的工具编写基于Web浏览器的应用软件或跨平台的桌面软件。</p>
<p>　　尽管安装量非常大，不同Java ME实现之间的差异引起了兼容性问题。JavaFX Mobile面向手机运营商和厂商，能够减少这些差异，提供一系列用于完成常见任务的手机应用软件。</p>
<p>　　斯蒂芬表示，推出与Java有关的脚本语言不一定会让人们放弃Ruby、Python、PHP，JavaFX Script主要对已经在使用Java的开发人员有吸引力。</p>
<p>　　新闻链接：</p>
<p>　　<a href="http://www.sun.com/software/javafx/"><font color=#3f87d7>JavaFX官方站点</font></a></p>
<p>　　<a href="http://了解javafx%20mobile/"><font color=#3f87d7>了解JavaFX mobile</font></a></p>
<p>　　<a href="http://www.sun.com/aboutsun/pr/2007-05/sunflash.20070508.2.xml"><font color=#3f87d7>Sun Radically Simplifies Content Authoring - Previews JavaFX Script</font></a></p>
</div>
</div><img src ="http://www.cnitblog.com/tilan/aggbug/27843.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-05-31 09:54 <a href="http://www.cnitblog.com/tilan/archive/2007/05/31/27843.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中static、this、super、final用法(转载)</title><link>http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Sat, 31 Mar 2007 15:13:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24991.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24991.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24991.html</trackback:ping><description><![CDATA[<p>一、static </p>
		<p>　　请先看下面这段程序：</p>
		<p>
				<br />public class Hello{<br />public static void main(String[] args){ //(1)<br />System.out.println("Hello,world!"); //(2)<br />}<br />}</p>
		<p>
				<br />　　看过这段程序，对于大多数学过Java 的从来说，都不陌生。即使没有学过Java，而学过其它的高级语言，例如C，那你也应该能看懂这段代码的意思。它只是简单的输出“Hello,world”，一点别的用处都没有，然而，它却展示了static关键字的主要用法。 </p>
		<p>
				<br />　　在1处，我们定义了一个静态的方法名为main，这就意味着告诉Java编译器，我这个方法不需要创建一个此类的对象即可使用。你还得你是怎么运行这个程序吗？一般，我们都是在命令行下，打入如下的命令(加下划线为手动输入)：</p>
		<p>javac Hello.java<br />java Hello<br />Hello,world!</p>
		<p>　　这就是你运行的过程，第一行用来编译Hello.java这个文件，执行完后，如果你查看当前，会发现多了一个Hello.class文件，那就是第一行产生的Java二进制字节码。第二行就是执行一个Java程序的最普遍做法。执行结果如你所料。在2中，你可能会想，为什么要这样才能输出。好，我们来分解一下这条语句。（如果没有安装Java文档，请到Sun的官方网站浏览J2SE API）首先，System是位于java.lang包中的一个核心类，如果你查看它的定义，你会发现有这样一行：public static final PrintStream out;接着在进一步，点击PrintStream这个超链接，在METHOD页面，你会看到大量定义的方法，查找println，会有这样一行：</p>
		<p>public void println(String x)。</p>
		<p>　　好了，现在你应该明白为什么我们要那样调用了，out是System的一个静态变量，所以可以直接使用，而out所属的类有一个println方法。</p>
		<p>静态方法</p>
		<p>　　通常，在一个类中定义一个方法为static，那就是说，无需本类的对象即可调用此方法。如下所示：</p>
		<p>
				<br />class Simple{<br />static void go(){<br />System.out.println("Go...");<br />}<br />}<br />public class Cal{<br />public static void main(String[] args){<br />Simple.go();<br />}<br />}</p>
		<p>
				<br />　　调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说，静态方法常常为应用程序中的其它类提供一些实用工具所用，在Java的类库中大量的静态方法正是出于此目的而定义的。 </p>
		<p>
				<br />静态变量</p>
		<p>　　静态变量与静态方法类似。所有此类实例共享此静态变量，也就是说在类装载时，只分配一块存储空间，所有此类的对象都可以操控此块存储空间，当然对于final则另当别论了。看下面这段代码：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />public static void main(String[] args){<br />Value v1,v2;<br />v1=new Value();<br />v2=new Value();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c); <br />}<br />}</p>
		<p>
				<br />　　结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=1 v2.c=1</p>
		<p>　　由此可以证明它们共享一块存储区。static变量有点类似于C中的全局变量的概念。值得探讨的是静态变量的初始化问题。我们修改上面的程序：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />Value(){<br />c=15;<br />}<br />Value(int i){<br />c=i;<br />}<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Value v=new Value(10);<br />static Value v1,v2;<br />static{<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1=new Value(27);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v2=new Value(15);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />}<br />public static void main(String[] args){<br />Count ct=new Count();<br />prt("ct.c="+ct.v.c);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />prt("ct.c="+ct.v.c);<br />}<br />}</p>
		<p>
				<br />运行结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=27 v2.c=27<br />v1.c=15 v2.c=15<br />ct.c=10<br />v1.c=10 v2.c=10<br />v1.c=11 v2.c=11<br />ct.c=11</p>
		<p>　　这个程序展示了静态初始化的各种特性。如果你初次接触Java，结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是，static定义的变量会优先于任何其它非static变量，不论其出现的顺序如何。正如在程序中所表现的，虽然v出现在v1和v2的前面，但是结果却是v1和v2的初始化在v的前面。在static{后面跟着一段代码，这是用来进行显式的静态变量初始化，这段代码只会初始化一次，且在类被第一次装载时。如果你能读懂并理解这段代码，会帮助你对static关键字的认识。在涉及到继承的时候，会先初始化父类的static变量，然后是子类的，依次类推。非静态变量不是本文的主题，在此不做详细讨论，请参考Think in Java中的讲解。</p>
		<p>静态类</p>
		<p>　　通常一个普通类不允许声明为静态的，只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用，而不需实例一个外部类。如下代码所示：</p>
		<p>
				<br />public class StaticCls{<br />public static void main(String[] args){<br />OuterCls.InnerCls oi=new OuterCls.InnerCls();<br />}<br />}<br />class OuterCls{<br />public static class InnerCls{<br />InnerCls(){<br />System.out.println("InnerCls");<br />}<br />}<br />}</p>
		<p>
				<br />　　输出结果会如你所料： </p>
		<p>
				<br />InnerCls</p>
		<p>　　和普通类一样。内部类的其它用法请参阅Think in Java中的相关章节，此处不作详解。</p>
		<p>二、this &amp; super</p>
		<p>　　在上一篇拙作中，我们讨论了static的种种用法，通过用static来定义方法或成员，为我们编程提供了某种便利，从某种程度上可以说它类似于C语言中的全局函数和全局变量。但是，并不是说有了这种便利，你便可以随处使用，如果那样的话，你便需要认真考虑一下自己是否在用面向对象的思想编程，自己的程序是否是面向对象的。好了，现在开始讨论this&amp;super这两个关键字的意义和用法。</p>
		<p>　　在Java中，this通常指当前对象，super则指父类的。当你想要引用当前对象的某种东西，比如当前对象的某个方法，或当前对象的某个成员，你便可以利用this来实现这个目的，当然，this的另一个用途是调用当前对象的另一个构造函数，这些马上就要讨论。如果你想引用父类的某种东西，则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某种关系，所以我们在这一块儿来讨论，希望能帮助你区分和掌握它们两个。</p>
		<p>在一般方法中</p>
		<p>　　最普遍的情况就是，在你的方法中的某个形参名与当前对象的某个成员有相同的名字，这时为了不至于混淆，你便需要明确使用this关键字来指明你要使用某个成员，使用方法是“this.成员名”，而不带this的那个便是形参。另外，还可以用“this.方法名”来引用当前对象的某个方法，但这时this就不是必须的了，你可以直接用方法名来访问那个方法，编译器会知道你要调用的是那一个。下面的代码演示了上面的用法：</p>
		<p>
				<br />public class DemoThis{<br />private String name;<br />private int age;<br />DemoThis(String name,int age){<br />setName(name); //你可以加上this来调用方法，像这样：this.setName(name);但这并不是必须的<br />setAge(age);<br />this.print();<br />} <br />public void setName(String name){<br />this.name=name;//此处必须指明你要引用成员变量<br />}<br />public void setAge(int age){<br />this.age=age;<br />}<br />public void print(){<br />System.out.println("Name="+name+" Age="+age);//在此行中并不需要用this，因为没有会导致混淆的东西<br />}<br />public static void main(String[] args){<br />DemoThis dt=new DemoThis("Kevin","22");<br />}<br />}</p>
		<p>
				<br />　　这段代码很简单，不用解释你也应该能看明白。在构造函数中你看到用this.print(),你完全可以用print()来代替它，两者效果一样。下面我们修改这个程序，来演示super的用法。</p>
		<p>class Person{<br />public int c;<br />private String name;<br />private int age;<br />protected void setName(String name){<br />this.name=name;<br />}<br />protected void setAge(int age){<br />this.age=age;<br />}<br />protected void print(){<br />System.out.println("Name="+name+" Age="+age);<br />}<br />}<br />public class DemoSuper extends Person{<br />public void print(){<br />System.out.println("DemoSuper:");<br />super.print();<br />}<br />public static void main(String[] args){<br />DemoSuper ds=new DemoSuper();<br />ds.setName("kevin");<br />ds.setAge(22);<br />ds.print();<br />}<br />}</p>
		<p>
				<br />　　在DemoSuper中，重新定义的print方法覆写了父类的print方法，它首先做一些自己的事情，然后调用父类的那个被覆写了的方法。输出结果说明了这一点： </p>
		<p>
				<br />DemoSuper:<br />Name=kevin Age=22</p>
		<p>　　这样的使用方法是比较常用的。另外如果父类的成员可以被子类访问，那你可以像使用this一样使用它，用“super.父类中的成员名”的方式，但常常你并不是这样来访问父类中的成员名的。</p>
		<p>在构造函数中</p>
		<p>　　构造函数是一种特殊的方法，在对象初始化的时候自动调用。在构造函数中，this和super也有上面说的种种使用方式，并且它还有特殊的地方，请看下面的例子：</p>
		<p>
				<br />class Person{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Person(){<br />prt("A Person.");<br />}<br />Person(String name){<br />prt("A person name is:"+name);<br />}<br />}<br />public class Chinese extends Person{<br />Chinese(){<br />super(); //调用父类构造函数（1）<br />prt("A chinese.");//(4)<br />}<br />Chinese(String name){<br />super(name);//调用父类具有相同形参的构造函数（2）<br />prt("his name is:"+name);<br />}<br />Chinese(String name,int age){<br />this(name);//调用当前具有相同形参的构造函数（3）<br />prt("his age is:"+age);<br />}<br />public static void main(String[] args){<br />Chinese cn=new Chinese();<br />cn=new Chinese("kevin");<br />cn=new Chinese("kevin",22);<br />}<br />}</p>
		<p>
				<br />　　在这段程序中，this和super不再是像以前那样用“.”连接一个方法或成员，而是直接在其后跟上适当的参数，因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同形式的构造函数，如1和2处。this后加参数则调用的是当前具有相同参数的构造函数，如3处。当然，在Chinese的各个重载构造函数中，this和super在一般方法中的各种用法也仍可使用，比如4处，你可以将它替换为“this.prt”(因为它继承了父类中的那个方法）或者是“super.prt”（因为它是父类中的方法且可被子类访问），它照样可以正确运行。但这样似乎就有点画蛇添足的味道了。 </p>
		<p>
				<br />　　最后，写了这么多，如果你能对“this通常指代当前对象，super通常指代父类”这句话牢记在心，那么本篇便达到了目的，其它的你自会在以后的编程实践当中慢慢体会、掌握。另外关于本篇中提到的继承，请参阅相关Java教程。</p>
		<p>三、final</p>
		<p>　　final在Java中并不常用，然而它却为我们提供了诸如在C语言中定义常量的功能，不仅如此，final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能，这些特点使final在Java中拥有了一个不可或缺的地位，也是学习Java时必须要知道和掌握的关键字之一。</p>
		<p>final成员</p>
		<p>　　当你在类中定义变量时，在其前面加上final关键字，那便是说，这个变量一旦被初始化便不可改变，这里不可改变的意思对基本类型来说是其值不可变，而对于对象变量来说其引用不可再变。其初始化可以在两个地方，一是其定义处，也就是说在final变量定义时直接给其赋值，二是在构造函数中。这两个地方只能选其一，要么在定义时给值，要么在构造函数中给值，不能同时既在定义时给了值，又在构造函数中给另外的值。下面这段代码演示了这一点：</p>
		<p>
				<br />import java.util.List;<br />import java.util.ArrayList;<br />import java.util.LinkedList;<br />public class Bat{<br />final PI=3.14; //在定义时便给址值<br />final int i; //因为要在构造函数中进行初始化，所以此处便不可再给值<br />final List list; //此变量也与上面的一样<br />Bat(){<br />i=100;<br />list=new LinkedList();<br />}<br />Bat(int ii,List l){<br />i=ii;<br />list=l;<br />}<br />public static void main(String[] args){<br />Bat b=new Bat();<br />b.list.add(new Bat());<br />//b.i=25;<br />//b.list=new ArrayList();<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />b=new Bat(23,new ArrayList());<br />b.list.add(new Bat());<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />}<br />}</p>
		<p>
				<br />　　此程序很简单的演示了final的常规用法。在这里使用在构造函数中进行初始化的方法，这使你有了一点灵活性。如Bat的两个重载构造函数所示，第一个缺省构造函数会为你提供默认的值，重载的那个构造函数会根据你所提供的值或类型为final变量初始化。然而有时你并不需要这种灵活性，你只需要在定义时便给定其值并永不变化，这时就不要再用这种方法。在main方法中有两行语句注释掉了，如果你去掉注释，程序便无法通过编译，这便是说，不论是i的值或是list的类型，一旦初始化，确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型，输出结果中显示了这一点： </p>
		<p>
				<br />I=100 List Type:class java.util.LinkedList<br />I=23 List Type:class java.util.ArrayList</p>
		<p>　　还有一种用法是定义方法中的参数为final，对于基本类型的变量，这样做并没有什么实际意义，因为基本类型的变量在调用方法时是传值的，也就是说你可以在方法中更改这个参数变量而不会影响到调用语句，然而对于对象变量，却显得很实用，因为对象变量在传递时是传递其引用，这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量，当你在方法中不需要改变作为参数的对象变量时，明确使用final进行声明，会防止你无意的修改而影响到调用方法。<br />另外方法中的内部类在用到方法中的参变量时，此参变也必须声明为final才可使用，如下代码所示：</p>
		<p>
				<br />public class INClass{<br />void innerClass(final String str){<br />class IClass{<br />IClass(){<br />System.out.println(str);<br />}<br />}<br />IClass ic=new IClass();<br />}<br />public static void main(String[] args){<br />INClass inc=new INClass();<br />inc.innerClass("Hello");<br />}<br />}</p>
		<p>
				<br />final方法 </p>
		<p>
				<br />　　将方法声明为final，那就说明你已经知道这个方法提供的功能已经满足你要求，不需要进行扩展，并且也不允许任何从此类继承的类来覆写这个方法，但是继承仍然可以继承这个方法，也就是说可以直接使用。另外有一种被称为inline的机制，它会使你在调用final方法时，直接将方法主体插入到调用处，而不是进行例行的方法调用，例如保存断点，压栈等，这样可能会使你的程序效率有所提高，然而当你的方法主体非常庞大时，或你在多处调用此方法，那么你的调用主体代码便会迅速膨胀，可能反而会影响效率，所以你要慎用final进行方法定义。</p>
		<p>final类</p>
		<p>　　当你将final用于类身上时，你就需要仔细考虑，因为一个final类是无法被任何人继承的，那也就意味着此类在一个继承树中是一个叶子类，并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员，你可以定义其为final，也可以不是final。而对于方法，由于所属类为final的关系，自然也就成了final型的。你也可以明确的给final类中的方法加上一个final，但这显然没有意义。</p>
		<p>　　下面的程序演示了final方法和final类的用法：</p>
		<p>
				<br />final class final{<br />final String str="final Data";<br />public String str1="non final data";<br />final public void print(){<br />System.out.println("final method.");<br />}<br />public void what(){<br />System.out.println(str+"<br />"+str1);<br />}<br />}<br />public class FinalDemo { //extends final 无法继承 <br />public static void main(String[] args){<br />final f=new final();<br />f.what();<br />f.print();<br />}<br />}</p>
		<p>
				<br />　　从程序中可以看出，final类与普通类的使用几乎没有差别，只是它失去了被继承的特性。final方法与非final方法的区别也很难从程序行看出，只是记住慎用。 </p>
		<p>
				<br />final在设计模式中的应用</p>
		<p>　　在设计模式中有一种模式叫做不变模式，在Java中通过final关键字可以很容易的实现这个模式，在讲解final成员时用到的程序Bat.java就是一个不变模式的例子。如果你对此感兴趣，可以参考阎宏博士编写的《Java与模式》一书中的讲解。</p>
		<p>　　到此为止，this,static,supert和final的使用已经说完了，如果你对这四个关键字已经能够大致说出它们的区别与用法，那便说明你基本已经掌握。然而，世界上的任何东西都不是完美无缺的，Java提供这四个关键字，给程序员的编程带来了很大的便利，但并不是说要让你到处使用，一旦达到滥用的程序，便适得其反，所以在使用时请一定要认真考虑。</p>
		<p>
				<br />　　请先看下面这段程序：</p>
		<p>
				<br />public class Hello{<br />public static void main(String[] args){ //(1)<br />System.out.println("Hello,world!"); //(2)<br />}<br />}</p>
		<p>
				<br />　　看过这段程序，对于大多数学过Java 的从来说，都不陌生。即使没有学过Java，而学过其它的高级语言，例如C，那你也应该能看懂这段代码的意思。它只是简单的输出“Hello,world”，一点别的用处都没有，然而，它却展示了static关键字的主要用法。 </p>
		<p>
				<br />　　在1处，我们定义了一个静态的方法名为main，这就意味着告诉Java编译器，我这个方法不需要创建一个此类的对象即可使用。你还得你是怎么运行这个程序吗？一般，我们都是在命令行下，打入如下的命令(加下划线为手动输入)：</p>
		<p>javac Hello.java<br />java Hello<br />Hello,world!</p>
		<p>　　这就是你运行的过程，第一行用来编译Hello.java这个文件，执行完后，如果你查看当前，会发现多了一个Hello.class文件，那就是第一行产生的Java二进制字节码。第二行就是执行一个Java程序的最普遍做法。执行结果如你所料。在2中，你可能会想，为什么要这样才能输出。好，我们来分解一下这条语句。（如果没有安装Java文档，请到Sun的官方网站浏览J2SE API）首先，System是位于java.lang包中的一个核心类，如果你查看它的定义，你会发现有这样一行：public static final PrintStream out;接着在进一步，点击PrintStream这个超链接，在METHOD页面，你会看到大量定义的方法，查找println，会有这样一行：</p>
		<p>public void println(String x)。</p>
		<p>　　好了，现在你应该明白为什么我们要那样调用了，out是System的一个静态变量，所以可以直接使用，而out所属的类有一个println方法。</p>
		<p>静态方法</p>
		<p>　　通常，在一个类中定义一个方法为static，那就是说，无需本类的对象即可调用此方法。如下所示：</p>
		<p>
				<br />class Simple{<br />static void go(){<br />System.out.println("Go...");<br />}<br />}<br />public class Cal{<br />public static void main(String[] args){<br />Simple.go();<br />}<br />}</p>
		<p>
				<br />　　调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说，静态方法常常为应用程序中的其它类提供一些实用工具所用，在Java的类库中大量的静态方法正是出于此目的而定义的。 </p>
		<p>
				<br />静态变量</p>
		<p>　　静态变量与静态方法类似。所有此类实例共享此静态变量，也就是说在类装载时，只分配一块存储空间，所有此类的对象都可以操控此块存储空间，当然对于final则另当别论了。看下面这段代码：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />public static void main(String[] args){<br />Value v1,v2;<br />v1=new Value();<br />v2=new Value();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c); <br />}<br />}</p>
		<p>
				<br />　　结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=1 v2.c=1</p>
		<p>　　由此可以证明它们共享一块存储区。static变量有点类似于C中的全局变量的概念。值得探讨的是静态变量的初始化问题。我们修改上面的程序：</p>
		<p>
				<br />class Value{<br />static int c=0;<br />Value(){<br />c=15;<br />}<br />Value(int i){<br />c=i;<br />}<br />static void inc(){<br />c++;<br />}<br />}<br />class Count{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Value v=new Value(10);<br />static Value v1,v2;<br />static{<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1=new Value(27);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v2=new Value(15);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />}<br />public static void main(String[] args){<br />Count ct=new Count();<br />prt("ct.c="+ct.v.c);<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />v1.inc();<br />prt("v1.c="+v1.c+" v2.c="+v2.c);<br />prt("ct.c="+ct.v.c);<br />}<br />}</p>
		<p>
				<br />运行结果如下： </p>
		<p>
				<br />v1.c=0 v2.c=0<br />v1.c=27 v2.c=27<br />v1.c=15 v2.c=15<br />ct.c=10<br />v1.c=10 v2.c=10<br />v1.c=11 v2.c=11<br />ct.c=11</p>
		<p>　　这个程序展示了静态初始化的各种特性。如果你初次接触Java，结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是，static定义的变量会优先于任何其它非static变量，不论其出现的顺序如何。正如在程序中所表现的，虽然v出现在v1和v2的前面，但是结果却是v1和v2的初始化在v的前面。在static{后面跟着一段代码，这是用来进行显式的静态变量初始化，这段代码只会初始化一次，且在类被第一次装载时。如果你能读懂并理解这段代码，会帮助你对static关键字的认识。在涉及到继承的时候，会先初始化父类的static变量，然后是子类的，依次类推。非静态变量不是本文的主题，在此不做详细讨论，请参考Think in Java中的讲解。</p>
		<p>静态类</p>
		<p>　　通常一个普通类不允许声明为静态的，只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用，而不需实例一个外部类。如下代码所示：</p>
		<p>
				<br />public class StaticCls{<br />public static void main(String[] args){<br />OuterCls.InnerCls oi=new OuterCls.InnerCls();<br />}<br />}<br />class OuterCls{<br />public static class InnerCls{<br />InnerCls(){<br />System.out.println("InnerCls");<br />}<br />}<br />}</p>
		<p>
				<br />　　输出结果会如你所料： </p>
		<p>
				<br />InnerCls</p>
		<p>　　和普通类一样。内部类的其它用法请参阅Think in Java中的相关章节，此处不作详解。</p>
		<p>二、this &amp; super</p>
		<p>　　在上一篇拙作中，我们讨论了static的种种用法，通过用static来定义方法或成员，为我们编程提供了某种便利，从某种程度上可以说它类似于C语言中的全局函数和全局变量。但是，并不是说有了这种便利，你便可以随处使用，如果那样的话，你便需要认真考虑一下自己是否在用面向对象的思想编程，自己的程序是否是面向对象的。好了，现在开始讨论this&amp;super这两个关键字的意义和用法。</p>
		<p>　　在Java中，this通常指当前对象，super则指父类的。当你想要引用当前对象的某种东西，比如当前对象的某个方法，或当前对象的某个成员，你便可以利用this来实现这个目的，当然，this的另一个用途是调用当前对象的另一个构造函数，这些马上就要讨论。如果你想引用父类的某种东西，则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某种关系，所以我们在这一块儿来讨论，希望能帮助你区分和掌握它们两个。</p>
		<p>在一般方法中</p>
		<p>　　最普遍的情况就是，在你的方法中的某个形参名与当前对象的某个成员有相同的名字，这时为了不至于混淆，你便需要明确使用this关键字来指明你要使用某个成员，使用方法是“this.成员名”，而不带this的那个便是形参。另外，还可以用“this.方法名”来引用当前对象的某个方法，但这时this就不是必须的了，你可以直接用方法名来访问那个方法，编译器会知道你要调用的是那一个。下面的代码演示了上面的用法：</p>
		<p>
				<br />public class DemoThis{<br />private String name;<br />private int age;<br />DemoThis(String name,int age){<br />setName(name); //你可以加上this来调用方法，像这样：this.setName(name);但这并不是必须的<br />setAge(age);<br />this.print();<br />} <br />public void setName(String name){<br />this.name=name;//此处必须指明你要引用成员变量<br />}<br />public void setAge(int age){<br />this.age=age;<br />}<br />public void print(){<br />System.out.println("Name="+name+" Age="+age);//在此行中并不需要用this，因为没有会导致混淆的东西<br />}<br />public static void main(String[] args){<br />DemoThis dt=new DemoThis("Kevin","22");<br />}<br />}</p>
		<p>
				<br />　　这段代码很简单，不用解释你也应该能看明白。在构造函数中你看到用this.print(),你完全可以用print()来代替它，两者效果一样。下面我们修改这个程序，来演示super的用法。</p>
		<p>class Person{<br />public int c;<br />private String name;<br />private int age;<br />protected void setName(String name){<br />this.name=name;<br />}<br />protected void setAge(int age){<br />this.age=age;<br />}<br />protected void print(){<br />System.out.println("Name="+name+" Age="+age);<br />}<br />}<br />public class DemoSuper extends Person{<br />public void print(){<br />System.out.println("DemoSuper:");<br />super.print();<br />}<br />public static void main(String[] args){<br />DemoSuper ds=new DemoSuper();<br />ds.setName("kevin");<br />ds.setAge(22);<br />ds.print();<br />}<br />}</p>
		<p>
				<br />　　在DemoSuper中，重新定义的print方法覆写了父类的print方法，它首先做一些自己的事情，然后调用父类的那个被覆写了的方法。输出结果说明了这一点： </p>
		<p>
				<br />DemoSuper:<br />Name=kevin Age=22</p>
		<p>　　这样的使用方法是比较常用的。另外如果父类的成员可以被子类访问，那你可以像使用this一样使用它，用“super.父类中的成员名”的方式，但常常你并不是这样来访问父类中的成员名的。</p>
		<p>在构造函数中</p>
		<p>　　构造函数是一种特殊的方法，在对象初始化的时候自动调用。在构造函数中，this和super也有上面说的种种使用方式，并且它还有特殊的地方，请看下面的例子：</p>
		<p>
				<br />class Person{<br />public static void prt(String s){<br />System.out.println(s);<br />}<br />Person(){<br />prt("A Person.");<br />}<br />Person(String name){<br />prt("A person name is:"+name);<br />}<br />}<br />public class Chinese extends Person{<br />Chinese(){<br />super(); //调用父类构造函数（1）<br />prt("A chinese.");//(4)<br />}<br />Chinese(String name){<br />super(name);//调用父类具有相同形参的构造函数（2）<br />prt("his name is:"+name);<br />}<br />Chinese(String name,int age){<br />this(name);//调用当前具有相同形参的构造函数（3）<br />prt("his age is:"+age);<br />}<br />public static void main(String[] args){<br />Chinese cn=new Chinese();<br />cn=new Chinese("kevin");<br />cn=new Chinese("kevin",22);<br />}<br />}</p>
		<p>
				<br />　　在这段程序中，this和super不再是像以前那样用“.”连接一个方法或成员，而是直接在其后跟上适当的参数，因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同形式的构造函数，如1和2处。this后加参数则调用的是当前具有相同参数的构造函数，如3处。当然，在Chinese的各个重载构造函数中，this和super在一般方法中的各种用法也仍可使用，比如4处，你可以将它替换为“this.prt”(因为它继承了父类中的那个方法）或者是“super.prt”（因为它是父类中的方法且可被子类访问），它照样可以正确运行。但这样似乎就有点画蛇添足的味道了。 </p>
		<p>
				<br />　　最后，写了这么多，如果你能对“this通常指代当前对象，super通常指代父类”这句话牢记在心，那么本篇便达到了目的，其它的你自会在以后的编程实践当中慢慢体会、掌握。另外关于本篇中提到的继承，请参阅相关Java教程。</p>
		<p>三、final</p>
		<p>　　final在Java中并不常用，然而它却为我们提供了诸如在C语言中定义常量的功能，不仅如此，final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能，这些特点使final在Java中拥有了一个不可或缺的地位，也是学习Java时必须要知道和掌握的关键字之一。</p>
		<p>final成员</p>
		<p>　　当你在类中定义变量时，在其前面加上final关键字，那便是说，这个变量一旦被初始化便不可改变，这里不可改变的意思对基本类型来说是其值不可变，而对于对象变量来说其引用不可再变。其初始化可以在两个地方，一是其定义处，也就是说在final变量定义时直接给其赋值，二是在构造函数中。这两个地方只能选其一，要么在定义时给值，要么在构造函数中给值，不能同时既在定义时给了值，又在构造函数中给另外的值。下面这段代码演示了这一点：</p>
		<p>
				<br />import java.util.List;<br />import java.util.ArrayList;<br />import java.util.LinkedList;<br />public class Bat{<br />final PI=3.14; //在定义时便给址值<br />final int i; //因为要在构造函数中进行初始化，所以此处便不可再给值<br />final List list; //此变量也与上面的一样<br />Bat(){<br />i=100;<br />list=new LinkedList();<br />}<br />Bat(int ii,List l){<br />i=ii;<br />list=l;<br />}<br />public static void main(String[] args){<br />Bat b=new Bat();<br />b.list.add(new Bat());<br />//b.i=25;<br />//b.list=new ArrayList();<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />b=new Bat(23,new ArrayList());<br />b.list.add(new Bat());<br />System.out.println("I="+b.i+" List Type:"+b.list.getClass());<br />}<br />}</p>
		<p>
				<br />　　此程序很简单的演示了final的常规用法。在这里使用在构造函数中进行初始化的方法，这使你有了一点灵活性。如Bat的两个重载构造函数所示，第一个缺省构造函数会为你提供默认的值，重载的那个构造函数会根据你所提供的值或类型为final变量初始化。然而有时你并不需要这种灵活性，你只需要在定义时便给定其值并永不变化，这时就不要再用这种方法。在main方法中有两行语句注释掉了，如果你去掉注释，程序便无法通过编译，这便是说，不论是i的值或是list的类型，一旦初始化，确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型，输出结果中显示了这一点： </p>
		<p>
				<br />I=100 List Type:class java.util.LinkedList<br />I=23 List Type:class java.util.ArrayList</p>
		<p>　　还有一种用法是定义方法中的参数为final，对于基本类型的变量，这样做并没有什么实际意义，因为基本类型的变量在调用方法时是传值的，也就是说你可以在方法中更改这个参数变量而不会影响到调用语句，然而对于对象变量，却显得很实用，因为对象变量在传递时是传递其引用，这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量，当你在方法中不需要改变作为参数的对象变量时，明确使用final进行声明，会防止你无意的修改而影响到调用方法。<br />另外方法中的内部类在用到方法中的参变量时，此参变也必须声明为final才可使用，如下代码所示：</p>
		<p>
				<br />public class INClass{<br />void innerClass(final String str){<br />class IClass{<br />IClass(){<br />System.out.println(str);<br />}<br />}<br />IClass ic=new IClass();<br />}<br />public static void main(String[] args){<br />INClass inc=new INClass();<br />inc.innerClass("Hello");<br />}<br />}</p>
		<p>
				<br />final方法 </p>
		<p>
				<br />　　将方法声明为final，那就说明你已经知道这个方法提供的功能已经满足你要求，不需要进行扩展，并且也不允许任何从此类继承的类来覆写这个方法，但是继承仍然可以继承这个方法，也就是说可以直接使用。另外有一种被称为inline的机制，它会使你在调用final方法时，直接将方法主体插入到调用处，而不是进行例行的方法调用，例如保存断点，压栈等，这样可能会使你的程序效率有所提高，然而当你的方法主体非常庞大时，或你在多处调用此方法，那么你的调用主体代码便会迅速膨胀，可能反而会影响效率，所以你要慎用final进行方法定义。</p>
		<p>final类</p>
		<p>　　当你将final用于类身上时，你就需要仔细考虑，因为一个final类是无法被任何人继承的，那也就意味着此类在一个继承树中是一个叶子类，并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员，你可以定义其为final，也可以不是final。而对于方法，由于所属类为final的关系，自然也就成了final型的。你也可以明确的给final类中的方法加上一个final，但这显然没有意义。</p>
		<p>　　下面的程序演示了final方法和final类的用法：</p>
		<p>
				<br />final class final{<br />final String str="final Data";<br />public String str1="non final data";<br />final public void print(){<br />System.out.println("final method.");<br />}<br />public void what(){<br />System.out.println(str+"<br />"+str1);<br />}<br />}<br />public class FinalDemo { //extends final 无法继承 <br />public static void main(String[] args){<br />final f=new final();<br />f.what();<br />f.print();<br />}<br />}</p>
		<p>
				<br />　　从程序中可以看出，final类与普通类的使用几乎没有差别，只是它失去了被继承的特性。final方法与非final方法的区别也很难从程序行看出，只是记住慎用。 </p>
		<p>
				<br />final在设计模式中的应用</p>
		<p>　　在设计模式中有一种模式叫做不变模式，在Java中通过final关键字可以很容易的实现这个模式，在讲解final成员时用到的程序Bat.java就是一个不变模式的例子。如果你对此感兴趣，可以参考阎宏博士编写的《Java与模式》一书中的讲解。</p>
		<p>　　到此为止，this,static,supert和final的使用已经说完了，如果你对这四个关键字已经能够大致说出它们的区别与用法，那便说明你基本已经掌握。然而，世界上的任何东西都不是完美无缺的，Java提供这四个关键字，给程序员的编程带来了很大的便利，但并不是说要让你到处使用，一旦达到滥用的程序，便适得其反，所以在使用时请一定要认真考虑。</p>
		<p> </p>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "image";
google_ad_channel = "";
//-->
		</script>
		<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-03-31 23:13 <a href="http://www.cnitblog.com/tilan/archive/2007/03/31/24991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java学习的30个目标</title><link>http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Sat, 31 Mar 2007 15:08:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24990.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24990.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24990.html</trackback:ping><description><![CDATA[本文将告诉你学习Java需要达到的30个目标，希望能够对你的学习有所帮助。对比一下自己，你已经掌握了这30条中的多少条了呢？ <br />　　1.你需要精通面向对象分析与设计(OOA/OOD)、涉及模式(GOF，J2EEDP)以及综合模式。你应该十分了解UML，尤其是class，object，interaction以及statediagrams。<br />　　2.你需要学习JAVA语言的基础知识以及它的核心类库(collections，serialization，streams，networking， multithreading，reflection，event，handling，NIO，localization，以及其他)。<br />　　3.你应该了解JVM，classloaders，classreflect，以及垃圾回收的基本工作机制等。你应该有能力反编译一个类文件并且明白一些基本的汇编指令。<br />　　4.如果你将要写客户端程序，你需要学习WEB的小应用程序(applet)，必需掌握GUI设计的思想和方法，以及桌面程序的SWING，AWT， SWT。你还应该对UI部件的JAVABEAN组件模式有所了解。JAVABEANS也被应用在JSP中以把业务逻辑从表现层中分离出来。<br />　　5.你需要学习java数据库技术，如JDBCAPI并且会使用至少一种persistence/ORM构架，例如Hibernate，JDO， CocoBase，TopLink，InsideLiberator(国产JDO红工厂软件)或者iBatis。<br />　　6.你还应该了解对象关系的阻抗失配的含义，以及它是如何影响业务对象的与关系型数据库的交互，和它的运行结果，还需要掌握不同的数据库产品运用，比如:oracle，mysql，mssqlserver。<br />　　7.你需要学习JAVA的沙盒安全模式(classloaders，bytecodeverification，managers，policyandpermissions，<br />codesigning， digitalsignatures，cryptography，certification，Kerberos，以及其他)还有不同的安全/认证 API，例如JAAS(JavaAuthenticationandAuthorizationService)，JCE (JavaCryptographyExtension)，JSSE(JavaSecureSocketExtension)，以及JGSS (JavaGeneralSecurityService)。<br />　　8.你需要学习Servlets，JSP，以及JSTL(StandardTagLibraries)和可以选择的第三方TagLibraries。<br />　　9.你需要熟悉主流的网页框架，例如JSF，Struts，Tapestry，Cocoon，WebWork，以及他们下面的涉及模式，如MVC/MODEL2。<br />　　10.你需要学习如何使用及管理WEB服务器，例如tomcat，resin，Jrun，并且知道如何在其基础上扩展和维护WEB程序。<br />11.你需要学习分布式对象以及远程API，例如RMI和RMI/IIOP。<br />　　12.你需要掌握各种流行中间件技术标准和与java结合实现，比如Tuxedo、CROBA，当然也包括javaEE本身。<br />　　13.你需要学习最少一种的XMLAPI，例如JAXP(JavaAPIforXMLProcessing)，JDOM(JavaforXMLDocumentObjectModel)，DOM4J，或JAXR(JavaAPIforXMLRegistries)。<br />　　14.你应该学习如何利用JAVAAPI和工具来构建WebService。例如JAX-RPC(JavaAPIforXML/RPC)，SAAJ (SOAPwithAttachmentsAPIforJava)，JAXB(JavaArchitectureforXMLBinding)，JAXM(JavaAPIforXMLMessaging)， JAXR(JavaAPIforXMLRegistries)，或者JWSDP(JavaWebServicesDeveloperPack)。<br />　　15.你需要学习一门轻量级应用程序框架，例如Spring，PicoContainer，Avalon，以及它们的IoC/DI风格(setter，constructor，interfaceinjection)。<br />　　16.你需要熟悉不同的J2EE技术，例如JNDI(JavaNamingandDirectoryInterface)，JMS (JavaMessageService)，JTA/JTS(JavaTransactionAPI/JavaTransactionService)，JMX (JavaManagementeXtensions)，以及JavaMail。<br />　　17.你需要学习企业级JavaBeans(EJB)以及它们的不同组件模式：Stateless/StatefulSessionBeans，EntityBeans(包含Bean- ManagedPersistence[BMP]或者Container-ManagedPersistence[CMP]和它的EJB-QL)，或者 Message-DrivenBeans(MDB)。<br />　　18.你需要学习如何管理与配置一个J2EE应用程序服务器，如WebLogic，JBoss等，并且利用它的附加服务，例如簇类，连接池以及分布式处理支援。你还需要了解如何在它上面封装和配置应用程序并且能够监控、调整它的性能。<br />　　19.你需要熟悉面向方面的程序设计以及面向属性的程序设计(这两个都被很容易混淆的缩写为AOP)，以及他们的主流JAVA规格和执行。例如AspectJ和AspectWerkz。<br />　　20.你需要熟悉对不同有用的API和frame work等来为你服务。例如Log4J(logging/tracing)，Quartz (scheduling)，JGroups(networkgroupcommunication)，JCache(distributedcaching)， Lucene(full-textsearch)，JakartaCommons等等。<br />21.如果你将要对接或者正和旧的系统或者本地平台，你需要学习JNI (JavaNativeInterface) and JCA (JavaConnectorArchitecture)。<br />　　22.你需要熟悉JINI技术以及与它相关的分布式系统，比如掌握CROBA。<br />　　23.你需要JavaCommunityProcess(JCP)以及他的不同JavaSpecificationRequests(JSRs)，例如Portlets(168)，JOLAP(69)，DataMiningAPI(73)，等等。<br />　　24.你应该熟练掌握一种JAVAIDE例如sunOne，netBeans，IntelliJIDEA或者Eclipse。(有些人更喜欢VI或EMACS来编写文件。随便你用什么了：)<br />　　25.JAVA(精确的说是有些配置)是冗长的，它需要很多的人工代码(例如EJB)，所以你需要熟悉代码生成工具，例如XDoclet。<br />　　26.你需要熟悉一种单元测试体系(JNunit)，并且学习不同的生成、部署工具(Ant，Maven)。<br />　　27.你需要熟悉一些在JAVA开发中经常用到的软件工程过程。例如RUP(RationalUnifiedProcess)andAgilemethodologies。<br />　　28.你需要能够深入了解加熟练操作和配置不同的操作系统，比如GNU/linux，sunsolaris，macOS等，做为跨平台软件的开发者。<br />　　29.你还需要紧跟java发展的步伐，比如现在可以深入的学习javaME，以及各种java新规范，技术的运用，如新起的web富客户端技术。<br />　　30.你必需要对opensource有所了解，因为至少java的很多技术直接是靠开源来驱动发展的，如java3D技术。<br /><script type="text/javascript"><!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "image";
google_ad_channel = "";
//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script><img src ="http://www.cnitblog.com/tilan/aggbug/24990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-03-31 23:08 <a href="http://www.cnitblog.com/tilan/archive/2007/03/31/24990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse 3.3 M6 发布 基于WPF平台</title><link>http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Tue, 27 Mar 2007 01:28:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24721.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24721.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24721.html</trackback:ping><description><![CDATA[<h5>昨天, Eclipse官方发布了Eclipse 3.3 M6版本.新版本基于Windows Presentation Foundation平台, 同时增加了Vista的本地化特性, 支持JavaXPCOM, 更好支持OLE等等.+WPF (Windows Presentation Foundation)+Native features on Vista (win32)+JavaXPCOM support.</h5>
		<div id="csdn_tag_adstyle">
		</div>
		<div class="newscon">
				<div>
						<script type="text/javascript"><![CDATA[how_ads_zone(13);]]&gt;</script>
						<script language="JavaScript" src="http://z.csdn.net/adjs.php?n=131711817&amp;what=zone:13&amp;charset=utf-8&amp;exclude=," type="text/javascript">
						</script>
						<p>
						</p>
						<p>昨天, Eclipse官方发布了Eclipse 3.3 M6版本.<br /><br />新版本基于Windows Presentation Foundation平台, 同时增加了Vista的本地化特性, 支持JavaXPCOM, 更好支持OLE等等.<br /><br />新版本的特性包括:<br /><br />+WPF (Windows Presentation Foundation)<br />+Native features on Vista (win32)<br />+JavaXPCOM support<br /><img alt="" src="http://images.csdn.net/20070326/javaxpcom.png" /><br /><br />+OLEExample and OLE improvements<br /><img alt="" src="http://images.csdn.net/20070326/oleexample.png" /><br /><br />+Reparenting support on Mac OSX<br />+Display.post() supports more mouse events<br />+Advanced graphics supports mirroring<br />......<br />等等<br /><br />更多特性参考官方站点<br /><br />Eclipse 3.3 M6官方下载:<br /><a href="http://download.eclipse.org/eclipse/downloads/drops/S-3.3M6-200703231616/index.php" target="_new"><font color="#3f87d7">http://download.eclipse.org/eclipse/downloads/drops/S-3.3M6-200703231616/index.php</font></a></p>
						<p>原文链接：<font face="Arial" color="#3f87d7"><a href="http://www.matrix.org.cn/resource/news/Eclipse3.3+M6_abe8355e-db2b-11db-9bed-29012b8c745e.html">http://www.matrix.org.cn/resource/news/Eclipse3.3+M6_abe8355e-db2b-11db-9bed-29012b8c745e.html</a></font></p>
				</div>
		</div>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24721.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-03-27 09:28 <a href="http://www.cnitblog.com/tilan/archive/2007/03/27/24721.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>FireFox</title><link>http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Mon, 19 Mar 2007 13:22:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24302.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24302.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24302.html</trackback:ping><description><![CDATA[<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 468;
google_ad_height = 60;
google_ad_format = "468x60_as_rimg";
google_cpa_choice = "CAAQycb8zwEaCNrmdvgKt1bFKJnA93M";
google_ad_channel = "";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-03-19 21:22 <a href="http://www.cnitblog.com/tilan/archive/2007/03/19/24302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google</title><link>http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Mon, 19 Mar 2007 12:55:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24298.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24298.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24298.html</trackback:ping><description><![CDATA[<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-03-19 20:55 <a href="http://www.cnitblog.com/tilan/archive/2007/03/19/24298.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>站内文章导读</title><link>http://www.cnitblog.com/tilan/archive/2007/03/19/24262.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Mon, 19 Mar 2007 02:55:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/19/24262.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24262.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/19/24262.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24262.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24262.html</trackback:ping><description><![CDATA[<p><font color=#ff6699><strong>.NTE 开发(1)</strong> </font>&nbsp;&nbsp; ( <a href="http://www.cnitblog.com/tilan/category/4250.html">http://www.cnitblog.com/tilan/category/4250.html</a>)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 软件工程&nbsp;</p>
<p>JAVA开发(27)&nbsp;&nbsp; (<a href="http://www.cnitblog.com/tilan/category/4249.html?Show=All">http://www.cnitblog.com/tilan/category/4249.html?Show=All</a>)<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Struts+Spring+Hibernate快速入门 </p>
<ol>
    <li>Hibernate+Spring+Struts扩展Struts
    <li>使用 Spring 更好地处理 Struts 动作
    <li>在ant中使用cvs功能自动完成每日构建
    <li>软件工程
    <li>如何使用 SQL JSP 标准库
    <li>对企业级Java应用程序及其部署进行建模
    <li>解决MVC下分页显示的问题
    <li>Apache与JBOSS的整合,并支持SSL,整理
    <li>**你如何使用javaBean操作数据库？**高效Bean封装
    <li>如何成为一个成功的Jsp程序员？
    <li>jsp设计模式
    <li>Struts 中 Html 标签库 的用法(第二组标签,与Form相关的标签 )
    <li>Struts原理与实践（2）
    <li>Struts原理与实践（1）
    <li>用 WebSphere Studio V5 编写一个简单的 Struts 应用程序&nbsp;
    <li>建筑和软件中模式之异同
    <li>你还在用if else吗？
    <li>学习GoF设计模式的重要性
    <li>Eclipse下使用Subversion （补）
    <li>ANT安装、配置
    <li>ANT十五大最佳实践&nbsp;
    <li>利用 Ant 和 JUnit 进行增量开发
    <li>Eclipse快速上手指南之使用Ant
    <li>JAVA开发环境配置
    <li>Java开源JMS框架
    <li>开发工具--==Eclipse </li>
</ol>
<p><br><font color=#ff6633><strong>数据库技术(3) </strong></font></p>
<p><font color=#ff6633><strong>桌面系统(2) </strong></font></p>
<p><font color=#ff6633><strong>软件测试(9)</strong> </font><br></p>
<p><font color=#ff6666><strong>配置管理(19)&nbsp;&nbsp; (<a href="http://www.cnitblog.com/tilan/category/4238.html?Show=All">http://www.cnitblog.com/tilan/category/4238.html?Show=All</a>)<br></strong></font><br><br>&nbsp;&nbsp;&nbsp;&nbsp; 基于Trac的项目管理系统构建(Windows篇) </p>
<ol>
    <li>每日构建采用软件的评估报告
    <li>在ant中使用cvs功能自动完成每日构建
    <li>Linux 的版本控制-------关于体系结构、模型和示例的概述
    <li>软件工程&nbsp;
    <li>windows上安装apache2.0.59 + svn1.4.0 + 自动邮件通知
    <li>Subversion 服务器mailer指南
    <li>Subversion的其他属性
    <li>subversion 管理员的工具箱
    <li>subversion 分支维护
    <li>subversion 标签
    <li>subversion 常见用例 并一条分支到另一支
    <li>Subversion__钩子脚本
    <li>Linux为例安装cvs
    <li>CVS使用手册
    <li>Apache与JBOSS的整合,并支持SSL,整理
    <li>Eclipse下使用Subversion （补）
    <li>使用SUBCLIPSE——针对ECLIPSE的SUBVERSION插件
    <li>windows安装基于Apache的Subversion服务器(包括SSL配置) <br></li>
</ol>
<script type="text/javascript">
				<!--
google_ad_client = "pub-3874079075380071";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
//2007-03-19: 3G-move, 三星, 摩托罗拉, 索爱, 诺基亚
google_ad_channel = "1730597762+1709572468+0778807001+6838187825+8377398382";
//-->
		</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script><img src ="http://www.cnitblog.com/tilan/aggbug/24262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/tilan/" target="_blank">korezu Inc</a> 2007-03-19 10:55 <a href="http://www.cnitblog.com/tilan/archive/2007/03/19/24262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 SVK 构建分布式版本控制环境</title><link>http://www.cnitblog.com/tilan/archive/2007/03/16/24149.html</link><dc:creator>korezu Inc</dc:creator><author>korezu Inc</author><pubDate>Fri, 16 Mar 2007 15:05:00 GMT</pubDate><guid>http://www.cnitblog.com/tilan/archive/2007/03/16/24149.html</guid><wfw:comment>http://www.cnitblog.com/tilan/comments/24149.html</wfw:comment><comments>http://www.cnitblog.com/tilan/archive/2007/03/16/24149.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/tilan/comments/commentRss/24149.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/tilan/services/trackbacks/24149.html</trackback:ping><description><![CDATA[<p>2007 年 2 月 28 日</p>
		<blockquote>SVK 是一个基于 Subversion 构造的分布式的版本控制系统。通常的集中式管理系统，如 CVS，Subversion 已经得到广泛应用，但是集中式的管理存在相应的缺陷，例如对唯一的版本库过分依赖：一旦不能正常连接到集中式的版本库，整个系统陷入瘫痪。SVK 最大的能力就在于可以维护分布式的版本库，分散的开发人员可以通过 SVK 建立远程的 CVS，Subversion，P4 协议的版本库镜像，选择工作在自己合适的镜像版本库，这个镜像甚至可以是本地的，整个工作可以离线进行，然后在需要的时候同步镜像版本库到主版本库。</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="N10056">
						<span class="atitle">前言</span>
				</a>
		</p>
		<p>SVK 在大部分的操作与设计思想上都与 Subversion 相似，本文假定读者对 Subversion 有一定的了解，将着重介绍 SVK 新增特性与功能，与 Subversion 重叠的部分就不再赘述。读者可以参考作者的另外一篇 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#resources"><font color="#996699">关于 Subversion 的文章</font></a>。</p>
		<p>
				<a name="N10064">
						<span class="atitle">历史</span>
				</a>
		</p>
		<p>版本管理工具的历史由来已久，CVS 作为标准的版本管理控制工具已经得到了广泛应用。为改善 CVS 天生的缺陷，CollabNet 开发了 Subversion。Subversion 在目录版本化、原子提交、元数据、分支和标签等方面有了极大的改进，但遗憾的是它仍然是集中式的版本管理工具。不过幸运的是，由于 Subversion 灵活的设计，重用 Subversion 已有组件并扩展其功能成为了现实，SVK 就是这样一个基于 Subversion 的扩展实现。高嘉良先生一年时间的全职工作使 SVK 顺利诞生了。目前 SVK 项目已经被 Bestpractical 收录，读者可以访问其官方主页（请参阅 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#resources"><font color="#996699">参考资源</font></a>）。</p>
		<p>
				<a name="N10072">
						<span class="atitle">License</span>
				</a>
		</p>
		<p>SVK 是基于 Artistic License 发布的。Artistic License 目前基本被用于标准 Perl，CPAN 组件以及 Parrot 软件上。详细信息请参阅 <a href="http://www.ibm.com/developerworks/cn/java/j-lo-svk/#resources"><font color="#996699">参考资源</font></a>。 </p>
		<p>
				<a name="N10080">
						<span class="smalltitle">
								<strong>
										<font face="Arial">安装</font>
								</strong>
						</span>
				</a>
		</p>
		<p>SVK 由一组基于 SVN 的 Perl 绑定的 Perl5 的模块构成。Subversion 本身是构建于 Apache APR 之上，因此 SVK 可以在任何支持 Apache Http Server 的操作系统上运行，包括 Windows、Linux、Mac OS、Free BSD 以及 Netware。</p>
		<p>最简单的安装方式是直接下载对应操作系统的的二进制版本。Windows 版本可以在 <a href="http://svk.bestpractical.com/view/SVKWin32"><font color="#5c81a7">这里</font></a> 找到，Linux 系统上也可以使用 deb 或者 rpm 的安装方式。目前 Cpan 已经提供有 2.0 版本的安装，通过 cpan 的安装方式如下：</p>
		<p>首先需要安装 Subversion 的 Perl 绑定，cpan 没有提供这一模块，如果安装 Subversion 的时候没有选择安装 Perl 绑定则需要重新配置及安装 Subversion。</p>
		<p>安装 Subversion 的 Perl 绑定需要 swig 的支持，swig 是 C/C++ 软件与其他高级语言的连接器，关于 swig 请参考<a href="http://www.swig.org/"><font color="#5c81a7">http://www.swig.org/</font></a>。</p>
		<p>
				<b>安装 swig</b>
		</p>
		<p>下载 swig1.3.24 以上版本（需要 Perl 5.8.0 以上版本支持），解压后在 SWIG-1.3.xx 目录下运行如下命令，其中 /path/to/correct/perl/binary 应当指向 Perl 的可执行文件：</p>
		<table cellspacing="0" cellpadding="0" width="40%" 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="N100A7">
																				<b>验证安装</b>
																		</a>
																		<br />可以用 swig --version 来验证安装是否成功。 </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" width="50%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">./configure --with-perl5=/path/to/correct/perl/binary
make
make install
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>配置 Subversion</b>
		</p>
		<p>成功安装了 swig 后便可以安装 subverion 的 perl 绑定了，在 Subversion 源代码目录下运行如下命令：</p>
		<table cellspacing="0" cellpadding="0" width="40%" 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="N100BE">
																				<b>验证安装</b>
																		</a>
																		<br />如果 Subversion 的 configure 找到了合适的 swig，将会生成名为 libsvn_swig_perl.so 的库文件。 </td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" width="50%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">./configure PERL=/path/to/correct/perl/binary
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>安装 Subversion 的 perl 绑定</b>
		</p>
		<table cellspacing="0" cellpadding="0" width="50%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">make
make swig-pl
make check-swig-pl
make install
make install-swig-pl
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>
				<b>通过 cpan 安装 SVK</b>
		</p>
		<p>通过如下命令，cpan 会自动寻找并提示安装所有相关模块。</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">&gt;cpan
cpan&gt; install SVK
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果全部安装成功。在命令行敲入 svk 便会得到如下的 SVK 帮助信息：</p>
		<table cellspacing="0" cellpadding="0" width="30%" 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="N100E8">
																				<b>获取帮助</b>
																		</a>
																		<br />
																		<p>svk help commands 将会列出所有 SVK 支持的子命令。</p>
																		<p>对于某个特定的命令如 update，svk help update 将会得到关于 update 的说明。</p>
																		<p>svk help environment 将会列出所有与 SVK 相关的环境变量。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">SVK Documentation - Main index:

If this is your first time using SVK, you should start by reading a
brief tutorial. When you're ready, type:

    svk help intro

Once you've done that, more in-depth help is available:

    svk help environment    Environment variables that alter svk's behavior
    svk help commands       A list of all available commands
    svk help view           svk view support
    svk help &lt;command-name&gt; Help for a specific command

For commercial support, contact sales@bestpractical.com. For up to date
information about SVK, visit http://svk.bestpractical.com/.
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<p>如果想要体验最新的版本，可以直接从 SVK 的版本库取出最新的源代码进行编译安装：</p>
		<p>Perl 绑定安装部分同前述。</p>
		<table cellspacing="0" cellpadding="0" width="60%" border="0">
				<tbody>
						<tr>
								<td class="code-outline">
										<pre class="displaycode">svn co http://code.bestpractical.com/svk/trunk/
cd trunk/
perl Makefile.PL
make
make test
make install
svk
</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td>
										<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
										<br />
										<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<table class="no-print" cellspacing="0" cellpadding="0" align="right">
				<tbody>
						<tr align="right">
								<td>
										<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
										<br />
										<table cellspacing="0" cellpadding="0" border="0">
												<tbody>
														<tr>
																<td valign="center">
																		<br />
																</td>
																<td valign="top" align="right">
																		<b>
																				<font color="#996699">
																				</font>
																		</b>
																</td>
														</tr>
												</tbody>
										</table>
	