﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-大鱼-随笔分类-j2se</title><link>http://www.blogjava.net/luluyanglu/category/38267.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 24 May 2011 21:59:33 GMT</lastBuildDate><pubDate>Tue, 24 May 2011 21:59:33 GMT</pubDate><ttl>60</ttl><item><title>排序算法java版，速度排行：冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序</title><link>http://www.blogjava.net/luluyanglu/archive/2011/05/24/350956.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Tue, 24 May 2011 15:58:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2011/05/24/350956.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/350956.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2011/05/24/350956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/350956.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/350956.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 先推荐一篇关于排序算法的文章：http://www.cppblog.com/guogangj/archive/2009/11/13/100876.html本文思路部分来源于上篇文章，但测得的结果似乎不大相同，不知是因为java的缘故还是因为我算法的缘故，欢迎拍砖。&nbsp;复习排序，顺便比下各种算法的速度，榜单如下：1、冒泡排序2、简单选择排序3、直接插入排序4、折半...&nbsp;&nbsp;<a href='http://www.blogjava.net/luluyanglu/archive/2011/05/24/350956.html'>阅读全文</a><img src ="http://www.blogjava.net/luluyanglu/aggbug/350956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2011-05-24 23:58 <a href="http://www.blogjava.net/luluyanglu/archive/2011/05/24/350956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Java读取Properties文件的六种方法</title><link>http://www.blogjava.net/luluyanglu/archive/2010/10/08/333999.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Fri, 08 Oct 2010 12:56:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2010/10/08/333999.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/333999.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2010/10/08/333999.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/333999.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/333999.html</trackback:ping><description><![CDATA[使用J2SE API读取Properties文件的六种方法
<p>　　1。使用java.util.Properties类的load()方法</p>
<p>　　示例：</p>
<p>　　InputStream in = lnew BufferedInputStream(new FileInputStream(name));</p>
<p>　　Properties p = new Properties();</p>
<p>　　p.load(in);</p>
<p>　　2。使用java.util.ResourceBundle类的getBundle()方法</p>
<p>　　示例：</p>
<p>　　ResourceBundle rb = ResourceBundle.getBundle(name, Locale.getDefault());</p>
<p>　　3。使用java.util.PropertyResourceBundle类的构造函数</p>
<p>　　示例：</p>
<p>　　InputStream in = new BufferedInputStream(new FileInputStream(name));</p>
<p>　　ResourceBundle rb = new PropertyResourceBundle(in);</p>
<p>　　4。使用class变量的getResourceAsStream()方法</p>
<p>　　示例：</p>
<p>　　InputStream in = JProperties.class.getResourceAsStream(name);</p>
<p>　　Properties p = new Properties();</p>
<p>　　p.load(in);</p>
<p>　　5。使用class.getClassLoader()所得到的java.lang.ClassLoader的getResourceAsStream()方法</p>
<p>　　示例：</p>
<p>　　InputStream in = JProperties.class.getClassLoader().getResourceAsStream(name);</p>
<p>　　Properties p = new Properties();</p>
<p>　　p.load(in);</p>
<p>　　6。使用java.lang.ClassLoader类的getSystemResourceAsStream()静态方法</p>
<p>　　示例：</p>
<p>　　InputStream in = ClassLoader.getSystemResourceAsStream(name);</p>
<p>　　Properties p = new Properties();</p>
<p>　　p.load(in);</p>
<p>　　补充</p>
<p>　　Servlet中可以使用javax.servlet.ServletContext的getResourceAsStream()方法</p>
<p>　　示例：</p>
<p>　　InputStream in = context.getResourceAsStream(path);</p>
<p>　　Properties p = new Properties();</p>
<p>　　p.load(in);</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/333999.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2010-10-08 20:56 <a href="http://www.blogjava.net/luluyanglu/archive/2010/10/08/333999.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java实现四则运算的解析收藏</title><link>http://www.blogjava.net/luluyanglu/archive/2010/04/21/318964.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Wed, 21 Apr 2010 06:01:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2010/04/21/318964.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/318964.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2010/04/21/318964.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/318964.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/318964.html</trackback:ping><description><![CDATA[<div class="blog_content">
<div>前些天，在项目里面在做OLAP模块，其中一个自定义配置部分，里面需要用到根据配置的四则运算公式（字符串型），计算公式的结果。</div>
<div>于是在网上搜索了一番，终于有所启发。但是也感慨网上很多的例子并不完整，让我冒着访问恶意网页的风险，四处浏览。遂将我自己的实现写在这里，供大家参考讨论。</div>
<div>此实现方法主要是参考了机械工业出版社出版的《数据结构、算法与应用——C++语言描述》（2000年1月出版）当中，第5章——堆栈，第169页，5.5应用——5.5.1括号匹配的例子，使用Java编写完成。</div>
<div>JVM版本为JDK6 Update1.</div>
<div>因为在处理四则运算的时候最麻烦的逻辑主要是对括号内预算的处理，特别是括号的嵌套。</div>
<div>因此该算法主要的逻辑是，通过对括号位置的观察，得出：从左至右的扫描一个字符串，那么每一个右括号将与最近遇到的那个未匹配的左括号相匹配。这和堆栈的后进先出的规则是一样的。因此得到在扫描的过程当中，将每一个遇到的左括号进行压栈，在出现右括号的时候，出栈。</div>
<div>该解法相对于通过递归实现的解法，在时间复杂性上略好，并且实现出来的代码更加清晰。</div>
<div>以下为具体实现的代码：</div>
<div>package azurecube.common;</div>
<div>import java.util.LinkedList;<br />
import java.util.ArrayList;</div>
<div>public class FormulaCalculator {<br />
&nbsp;private boolean isRightFormat = true;<br />
&nbsp;<br />
&nbsp;public double getResult(String formula){<br />
&nbsp;&nbsp;double returnValue = 0;<br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp;returnValue = doAnalysis(formula);<br />
&nbsp;&nbsp;}catch(NumberFormatException nfe){<br />
&nbsp;&nbsp;&nbsp;System.out.println("公式格式有误，请检查:" + formula);<br />
&nbsp;&nbsp;}catch(Exception e){<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if(!isRightFormat){<br />
&nbsp;&nbsp;&nbsp;System.out.println("公式格式有误，请检查:" + formula);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return returnValue;<br />
&nbsp;}</div>
<div>&nbsp;private double doAnalysis(String formula){<br />
&nbsp;&nbsp;double returnValue = 0;<br />
&nbsp;&nbsp;LinkedList&lt;Integer&gt; stack = new LinkedList&lt;Integer&gt;();<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;int curPos = 0;<br />
&nbsp;&nbsp;String beforePart = "";<br />
&nbsp;&nbsp;String afterPart = "";<br />
&nbsp;&nbsp;String calculator = "";<br />
&nbsp;&nbsp;isRightFormat = true;<br />
&nbsp;&nbsp;while(isRightFormat&amp;&amp;(formula.indexOf('(') &gt;= 0||formula.indexOf(')') &gt;= 0)){<br />
&nbsp;&nbsp;&nbsp;curPos = 0;<br />
&nbsp;&nbsp;&nbsp;for(char s : formula.toCharArray()){<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(s == '('){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.add(curPos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}else if(s == ')'){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(stack.size() &gt; 0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;beforePart = formula.substring(0, stack.getLast());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;afterPart = formula.substring(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculator = formula.substring(stack.getLast() + 1, curPos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formula = beforePart + doCalculation(calculator) + afterPart;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("有未关闭的右括号！");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;isRightFormat = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;curPos++;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;if(stack.size() &gt; 0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("有未关闭的左括号！");<br />
&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;if(isRightFormat){<br />
&nbsp;&nbsp;&nbsp;returnValue = doCalculation(formula);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return returnValue;<br />
&nbsp;}</div>
<div>&nbsp;private double doCalculation(String formula) {<br />
&nbsp;&nbsp;ArrayList&lt;Double&gt; values = new ArrayList&lt;Double&gt;();<br />
&nbsp;&nbsp;ArrayList&lt;String&gt; operators = new ArrayList&lt;String&gt;();</div>
<div>&nbsp;&nbsp;int curPos = 0;<br />
&nbsp;&nbsp;int prePos = 0;<br />
&nbsp;&nbsp;for (char s : formula.toCharArray()) {<br />
&nbsp;&nbsp;&nbsp;if (s == '+' || s == '-' || s == '*' || s == '/') {<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.add(Double.parseDouble(formula.substring(prePos, curPos)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.trim()));<br />
&nbsp;&nbsp;&nbsp;&nbsp;operators.add("" + s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;prePos = curPos + 1;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;curPos++;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;values.add(Double.parseDouble(formula.substring(prePos).trim()));</div>
<div>&nbsp;&nbsp;char op;<br />
&nbsp;&nbsp;for (curPos = operators.size() - 1; curPos &gt;= 0; curPos--) {<br />
&nbsp;&nbsp;&nbsp;op = operators.get(curPos).charAt(0);<br />
&nbsp;&nbsp;&nbsp;switch (op) {<br />
&nbsp;&nbsp;&nbsp;case '*':<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.add(curPos, values.get(curPos) * values.get(curPos + 1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;operators.remove(curPos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;case '/':<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.add(curPos, values.get(curPos) / values.get(curPos + 1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;operators.remove(curPos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;for (curPos = operators.size() - 1; curPos &gt;= 0; curPos--) {<br />
&nbsp;&nbsp;&nbsp;op = operators.get(curPos).charAt(0);<br />
&nbsp;&nbsp;&nbsp;switch (op) {<br />
&nbsp;&nbsp;&nbsp;case '+':<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.add(curPos, values.get(curPos) + values.get(curPos + 1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;operators.remove(curPos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;case '-':<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.add(curPos, values.get(curPos) - values.get(curPos + 1));<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;values.remove(curPos + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;operators.remove(curPos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}</div>
<div>&nbsp;&nbsp;return values.get(0).doubleValue();<br />
&nbsp;}<br />
}<br />
</div>
</div>
<script type="text/javascript"><!-- google_ad_client="pub-4348265167276910" ;
/* 468x60, 个人博客 */ google_ad_slot="2046406163" ; google_ad_width="468;
google_ad_height" = 60;
//-->
</script><script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
</script><script src="http://pagead2.googlesyndication.com/pagead/expansion_embed.js"></script><script src="http://googleads.g.doubleclick.net/pagead/test_domain.js"></script><script src="http://pagead2.googlesyndication.com/pagead/render_ads.js"></script><script>google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);</script>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/318964.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2010-04-21 14:01 <a href="http://www.blogjava.net/luluyanglu/archive/2010/04/21/318964.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>23种设计模式 有趣的介绍</title><link>http://www.blogjava.net/luluyanglu/archive/2010/04/19/318723.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Mon, 19 Apr 2010 04:51:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2010/04/19/318723.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/318723.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2010/04/19/318723.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/318723.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/318723.html</trackback:ping><description><![CDATA[<p>1、FACTORY—追MM少不了请吃饭了，麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西，虽然口味有所不同，但不管你带MM去麦当劳或肯德基，只管向服务员说&#8220;来四个鸡翅&#8221;就行了。麦当劳和肯德基就是生产鸡翅的Factory </p>
<p><br />
工厂模式：客户类和工厂类分开。消费者任何时候需要某种产品，只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时，工厂类也要做相应的修改。如：如何创建及如何向客户端提供。 </p>
<p>2、BUILDER—MM最爱听的就是&#8220;我爱你&#8221;这句话了，见到不同地方的MM,要能够用她们的方言跟她说这句话哦，我有一个多种语言翻译机，上面每种语言都有一个按键，见到MM我只要按对应的键，它就能够用相应的语言说出&#8220;我爱你&#8221;这句话了，国外的MM也可以轻松搞掂，这就是我的&#8220;我爱你&#8221;builder。（这一定比美军在伊拉克用的翻译机好卖） </p>
<p>建造模式：将产品的内部表象和产品的生成过程分割开来，从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化，客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。 </p>
<p>3、FACTORY METHOD—请MM去麦当劳吃汉堡，不同的MM有不同的口味，要每个都记住是一件烦人的事情，我一般采用Factory Method模式，带着MM到服务员那儿，说&#8220;要一个汉堡&#8221;，具体要什么样的汉堡呢，让MM直接跟服务员说就行了。 </p>
<p>工厂方法模式：核心工厂类不再负责所有产品的创建，而是将具体创建的工作交给子类去做，成为一个抽象工厂角色，仅负责给出具体工厂类必须实现的接口，而不接触哪一个产品类应当被实例化这种细节。 </p>
<p>4、PROTOTYPE—跟MM用QQ聊天，一定要说些深情的话语了，我搜集了好多肉麻的情话，需要时只要copy出来放到QQ里面就行了，这就是我的情话prototype了。（100块钱一份，你要不要） </p>
<p>原始模型模式：通过给出一个原型对象来指明所要创建的对象的类型，然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类，产品类不需要非得有任何事先确定的等级结构，原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。 </p>
<p>5、SINGLETON—俺有6个漂亮的老婆，她们的老公都是我，我就是我们家里的老公Sigleton，她们只要说道&#8220;老公&#8221;，都是指的同一个人，那就是我(刚才做了个梦啦，哪有这么好的事) </p>
<p>单例模式：单例模式确保某一个类只有一个实例，而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的&#8220;单一实例&#8221;的需求时才可使用。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结构型模式 </p>
<p>6、ADAPTER—在朋友聚会上碰到了一个美女Sarah，从香港来的，可我不会说粤语，她不会说普通话，只好求助于我的朋友kent了，他作为我和Sarah之间的Adapter，让我和Sarah可以相互交谈了(也不知道他会不会耍我) </p>
<p>适配器（变压器）模式：把一个类的接口变换成客户端所期待的另一种接口，从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。 </p>
<p>7、BRIDGE—早上碰到MM，要说早上好，晚上碰到MM，要说晚上好；碰到MM穿了件新衣服，要说你的衣服好漂亮哦，碰到MM新做的发型，要说你的头发好漂亮哦。不要问我&#8220;早上碰到MM新做了个发型怎么说&#8221;这种问题，自己用BRIDGE组合一下不就行了 </p>
<p>桥梁模式：将抽象化与实现化脱耦，使得二者可以独立的变化，也就是说将他们之间的强关联变成弱关联，也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系，从而使两者可以独立的变化。 </p>
<p>8、COMPOSITE—Mary今天过生日。&#8220;我过生日，你要送我一件礼物。&#8221;&#8220;嗯，好吧，去商店，你自己挑。&#8221;&#8220;这件T恤挺漂亮，买，这条裙子好看，买，这个包也不错，买。&#8221;&#8220;喂，买了三件了呀，我只答应送一件礼物的哦。&#8221;&#8220;什么呀，T恤加裙子加包包，正好配成一套呀，小姐，麻烦你包起来。&#8221;&#8220;&#8230;&#8230;&#8221;，MM都会用Composite模式了，你会了没有？ </p>
<p>合成模式：合成模式将对象组织到树结构中，可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待。 </p>
<p>9、DECORATOR—Mary过完轮到Sarly过生日，还是不要叫她自己挑了，不然这个月伙食费肯定玩完，拿出我去年在华山顶上照的照片，在背面写上&#8220;最好的的礼物，就是爱你的Fita&#8221;，再到街上礼品店买了个像框（卖礼品的MM也很漂亮哦），再找隔壁搞美术设计的Mike设计了一个漂亮的盒子装起来&#8230;&#8230;，我们都是Decorator，最终都在修饰我这个人呀，怎么样，看懂了吗？ </p>
<p>装饰模式：装饰模式以对客户端透明的方式扩展对象的功能，是继承关系的一个替代方案，提供比继承更多的灵活性。动态给一个对象增加功能，这些功能可以再动态的撤消。增加由一些基本功能的排列组合而产生的非常大量的功能。 </p>
<p>10、FACADE—我有一个专业的Nikon相机，我就喜欢自己手动调光圈、快门，这样照出来的照片才专业，但MM可不懂这些，教了半天也不会。幸好相机有Facade设计模式，把相机调整到自动档，只要对准目标按快门就行了，一切由相机自动调整，这样MM也可以用这个相机给我拍张照片了。 </p>
<p>门面模式：外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口，使得子系统更易于使用。每一个子系统只有一个门面类，而且此门面类只有一个实例，也就是说它是一个单例模式。但整个系统可以有多个门面类。 </p>
<p>11、FLYWEIGHT—每天跟MM发短信，手指都累死了，最近买了个新手机，可以把一些常用的句子存在手机里，要用的时候，直接拿出来，在前面加上MM的名字就可以发送了，再不用一个字一个字敲了。共享的句子就是Flyweight，MM的名字就是提取出来的外部特征，根据上下文情况使用。 </p>
<p>享元模式：FLYWEIGHT在拳击比赛中指最轻量级。享元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部，不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态，它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来，将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象，而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。 </p>
<p>12、PROXY—跟MM在网上聊天，一开头总是&#8220;hi,你好&#8221;,&#8220;你从哪儿来呀？&#8221;&#8220;你多大了？&#8221;&#8220;身高多少呀？&#8221;这些话，真烦人，写个程序做为我的Proxy吧，凡是接收到这些话都设置好了自动的回答，接收到其他的话时再通知我回答，怎么样，酷吧。 </p>
<p>代理模式：代理模式给某一个对象提供一个代理对象，并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下，客户不想或者不能够直接引用一个对象，代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象，而仅仅持有一个被代理对象的接口，这时候代理对象不能够创建被代理对象，被代理对象必须有系统的其他角色代为创建并传入。 </p>
<p>&nbsp;&nbsp;&nbsp; 行为模式 </p>
<p>13、CHAIN OF RESPONSIBLEITY—晚上去上英语课，为了好开溜坐到了最后一排，哇，前面坐了好几个漂亮的MM哎，找张纸条，写上&#8220;Hi,可以做我的女朋友吗？如果不愿意请向前传&#8221;，纸条就一个接一个的传上去了，糟糕，传到第一排的MM把纸条传给老师了，听说是个老处女呀，快跑! </p>
<p>责任链模式：在责任链模式中，很多对象由每一个对象对其下家的引用而接 </p>
<p>起来形成一条链。请求在这个链上传递，直到链上的某一个对象决定处理此请求。客户并不知道链上的哪一个对象最终处理这个请求，系统可以在不影响客户端的情况下动态的重新组织链和分配责任。处理者有两个选择：承担责任或者把责任推给下家。一个请求可以最终不被任何接收端对象所接受。 </p>
<p>14、COMMAND—俺有一个MM家里管得特别严，没法见面，只好借助于她弟弟在我们俩之间传送信息，她对我有什么指示，就写一张纸条让她弟弟带给我。这不，她弟弟又传送过来一个COMMAND，为了感谢他，我请他吃了碗杂酱面，哪知道他说：&#8220;我同时给我姐姐三个男朋友送COMMAND，就数你最小气，才请我吃面。&#8221;， </p>
<p>命令模式：命令模式把一个请求或者操作封装到一个对象中。命令模式把发出命令的责任和执行命令的责任分割开，委派给不同的对象。命令模式允许请求的一方和发送的一方独立开来，使得请求的一方不必知道接收请求的一方的接口，更不必知道请求是怎么被接收，以及操作是否执行，何时被执行以及是怎么被执行的。系统支持命令的撤消。 </p>
<p>15、INTERPRETER—俺有一个《泡MM真经》，上面有各种泡MM的攻略，比如说去吃西餐的步骤、去看电影的方法等等，跟MM约会时，只要做一个Interpreter，照着上面的脚本执行就可以了。 </p>
<p>解释器模式：给定一个语言后，解释器模式可以定义出其文法的一种表示，并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后，使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构，也就是一系列的组合规则。每一个命令对象都有一个解释方法，代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。 </p>
<p>16、ITERATOR—我爱上了Mary，不顾一切的向她求婚。 </p>
<p>Mary：&#8220;想要我跟你结婚，得答应我的条件&#8221; </p>
<p>我：&#8220;什么条件我都答应，你说吧&#8221; </p>
<p>Mary：&#8220;我看上了那个一克拉的钻石&#8221; </p>
<p>我：&#8220;我买，我买，还有吗？&#8221; </p>
<p>Mary：&#8220;我看上了湖边的那栋别墅&#8221; </p>
<p>我：&#8220;我买，我买，还有吗？&#8221; </p>
<p>Mary：&#8220;我看上那辆法拉利跑车&#8221; </p>
<p>我脑袋嗡的一声，坐在椅子上，一咬牙：&#8220;我买，我买，还有吗？&#8221; </p>
<p>&#8230;&#8230; </p>
<p>迭代子模式：迭代子模式可以顺序访问一个聚集中的元素而不必暴露聚集的内部表象。多个对象聚在一起形成的总体称之为聚集，聚集对象是能够包容一组对象的容器对象。迭代子模式将迭代逻辑封装到一个独立的子对象中，从而与聚集本身隔开。迭代子模式简化了聚集的界面。每一个聚集对象都可以有一个或一个以上的迭代子对象，每一个迭代子的迭代状态可以是彼此独立的。迭代算法可以独立于聚集角色变化。 </p>
<p>17、MEDIATOR—四个MM打麻将，相互之间谁应该给谁多少钱算不清楚了，幸亏当时我在旁边，按照各自的筹码数算钱，赚了钱的从我这里拿，赔了钱的也付给我，一切就OK啦，俺得到了四个MM的电话。 </p>
<p>调停者模式：调停者模式包装了一系列对象相互作用的方式，使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时，不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化，把对象在小尺度的行为上与其他对象的相互作用分开处理。 </p>
<p>18、MEMENTO—同时跟几个MM聊天时，一定要记清楚刚才跟MM说了些什么话，不然MM发现了会不高兴的哦，幸亏我有个备忘录，刚才与哪个MM说了什么话我都拷贝一份放到备忘录里面保存，这样可以随时察看以前的记录啦。 </p>
<p>备忘录模式：备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下，将一个对象的状态捉住，并外部化，存储起来，从而可以在将来合适的时候把这个对象还原到存储起来的状态。 </p>
<p>19、OBSERVER—想知道咱们公司最新MM情报吗？加入公司的MM情报邮件组就行了，tom负责搜集情报，他发现的新情报不用一个一个通知我们，直接发布给邮件组，我们作为订阅者（观察者）就可以及时收到情报啦 </p>
<p>观察者模式：观察者模式定义了一种一队多的依赖关系，让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时，会通知所有观察者对象，使他们能够自动更新自己。 </p>
<p>20、STATE—跟MM交往时，一定要注意她的状态哦，在不同的状态时她的行为会有不同，比如你约她今天晚上去看电影，对你没兴趣的MM就会说&#8220;有事情啦&#8221;，对你不讨厌但还没喜欢上的MM就会说&#8220;好啊，不过可以带上我同事么？&#8221;，已经喜欢上你的MM就会说&#8220;几点钟？看完电影再去泡吧怎么样？&#8221;，当然你看电影过程中表现良好的话，也可以把MM的状态从不讨厌不喜欢变成喜欢哦。 </p>
<p>状态模式：状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里，每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候，其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时，系统便改变所选的子类。 </p>
<p>21、STRATEGY—跟不同类型的MM约会，要用不同的策略，有的请电影比较好，有的则去吃小吃效果不错，有的去海边浪漫最合适，单目的都是为了得到MM的芳心，我的追MM锦囊中有好多Strategy哦。 </p>
<p>策略模式：策略模式针对一组算法，将每一个算法封装到具有共同接口的独立的类中，从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类，各种算法在具体的策略类中提供。由于算法和环境独立开来，算法的增减，修改都不会影响到环境和客户端。 </p>
<p>22、TEMPLATE METHOD——看过《如何说服女生上床》这部经典文章吗？女生从认识到上床的不变的步骤分为巧遇、打破僵局、展开追求、接吻、前戏、动手、爱抚、进去八大步骤(Template method)，但每个步骤针对不同的情况，都有不一样的做法，这就要看你随机应变啦(具体实现)； </p>
<p>模板方法模式：模板方法模式准备一个抽象类，将部分逻辑以具体方法以及具体构造子的形式实现，然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法，从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架，而将逻辑的细节留给具体的子类去实现。 </p>
<p>23、VISITOR—情人节到了，要给每个MM送一束鲜花和一张卡片，可是每个MM送的花都要针对她个人的特点，每张卡片也要根据个人的特点来挑，我一个人哪搞得清楚，还是找花店老板和礼品店老板做一下Visitor，让花店老板根据MM的特点选一束花，让礼品店老板也根据每个人特点选一张卡，这样就轻松多了； </p>
<p>访问者模式：访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话，接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统，它把数据结构和作用于结构上的操作之间的耦合解脱开，使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易，就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中，而不是分散到一个个的节点类中。当使用访问者模式时，要将尽可能多的对象浏览逻辑放在访问者类中，而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/surfingsoft_mda/archive/2009/11/18/4830007.aspx</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/318723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2010-04-19 12:51 <a href="http://www.blogjava.net/luluyanglu/archive/2010/04/19/318723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JDOM解析XML字符串(非XML文档)</title><link>http://www.blogjava.net/luluyanglu/archive/2010/02/23/313716.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Tue, 23 Feb 2010 06:25:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2010/02/23/313716.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/313716.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2010/02/23/313716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/313716.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/313716.html</trackback:ping><description><![CDATA[<p>package com;</p>
<p>import java.io.IOException;<br />
import java.io.StringReader;<br />
import java.util.List;</p>
<p>import org.jdom.Document;<br />
import org.jdom.Element;<br />
import org.jdom.JDOMException;<br />
import org.jdom.Namespace;<br />
import org.jdom.input.SAXBuilder;<br />
import org.xml.sax.InputSource;</p>
<p><br />
public class DuXMLDoc { <br />
&nbsp;&nbsp;&nbsp; public List xmlElements(String xmlDoc) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //创建一个新的字符串 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringReader read = new StringReader(xmlDoc); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InputSource source = new InputSource(read); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //创建一个新的SAXBuilder <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SAXBuilder sb = new SAXBuilder(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //通过输入源构造一个Document <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Document doc = sb.build(source); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //取的根元素 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element root = doc.getRootElement(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(root.getName());//输出根元素的名称（测试） <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //得到根元素所有子元素的集合 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List jiedian = root.getChildren(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获得XML中的命名空间（XML中未定义可不写） <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Namespace ns = root.getNamespace(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element et = null; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;jiedian.size();i++){ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; et = (Element) jiedian.get(i);//循环依次得到子元素 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 无命名空间定义时 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * et.getChild("users_id").getText(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * et.getChild("users_address",ns).getText() <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(et.getChild("users_id",ns).getText()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(et.getChild("users_address",ns).getText()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 如要取&lt;row&gt;下的子元素的名称 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; et = (Element) jiedian.get(0); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List zjiedian = et.getChildren(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int j=0;j&lt;zjiedian.size();j++){ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Element xet = (Element) zjiedian.get(j); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(xet.getName()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (JDOMException e) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO 自动生成 catch 块 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (IOException e) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO 自动生成 catch 块 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args){ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DuXMLDoc doc = new DuXMLDoc(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String xml = "&lt;?xml version=\"1.0\" encoding=\"gb2312\"?&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;Result xmlns=\"http://www.fiorano.com/fesb/activity/DBQueryOnInput2/Out\"&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;row resultcount=\"1\"&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_id&gt;1001&nbsp;&nbsp;&nbsp;&nbsp; &lt;/users_id&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_name&gt;wangwei&nbsp;&nbsp; &lt;/users_name&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_group&gt;80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/users_group&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_address&gt;1001号&nbsp;&nbsp; &lt;/users_address&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;/row&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;row resultcount=\"1\"&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_id&gt;1002&nbsp;&nbsp;&nbsp;&nbsp; &lt;/users_id&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_name&gt;wangwei&nbsp;&nbsp; &lt;/users_name&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_group&gt;80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/users_group&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;users_address&gt;1002号&nbsp;&nbsp; &lt;/users_address&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;/row&gt;"+ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "&lt;/Result&gt;"; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doc.xmlElements(xml); <br />
&nbsp;&nbsp;&nbsp; } <br />
} <br />
</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/313716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2010-02-23 14:25 <a href="http://www.blogjava.net/luluyanglu/archive/2010/02/23/313716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM调优总结 -Xms -Xmx -Xmn -Xss</title><link>http://www.blogjava.net/luluyanglu/archive/2010/02/23/313713.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Tue, 23 Feb 2010 06:09:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2010/02/23/313713.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/313713.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2010/02/23/313713.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/313713.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/313713.html</trackback:ping><description><![CDATA[<p>堆大小设置 <br />
<br />
JVM 中最大堆大小有三方面限制：相关操作系统的数据模型（32-bt还是64-bit）限制；系统的可用虚拟内存限制；系统的可用物理内存限制。32位系统下，一般限制在1.5G~2G；64为操作系统对内存无限制。我在Windows Server 2003 系统，3.5G物理内存，JDK5.0下测试，最大可设置为1478m。 <br />
<br />
典型设置： <br />
<br />
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k <br />
<br />
-Xmx3550m：设置JVM最大可用内存为3550M。 <br />
<br />
-Xms3550m：设置JVM初始内存为3550m。此值可以设置与-Xmx相同，以避免每次垃圾回收完成后JVM重新分配内存。 <br />
<br />
-Xmn2g：设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m，所以增大年轻代后，将会减小年老代大小。此值对系统性能影响较大，Sun官方推荐配置为整个堆的3/8。 <br />
<br />
-Xss128k：设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M，以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下，减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的，不能无限生成，经验值在3000~5000左右。 <br />
<br />
<br />
java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0 <br />
<br />
-XX:NewRatio=4:设置年轻代（包括Eden和两个Survivor区）与年老代的比值（除去持久代）。设置为4，则年轻代与年老代所占比值为1：4，年轻代占整个堆栈的1/5 <br />
<br />
-XX:SurvivorRatio=4：设置年轻代中Eden区与Survivor区的大小比值。设置为4，则两个Survivor区与一个Eden区的比值为2:4，一个Survivor区占整个年轻代的1/6 <br />
<br />
-XX:MaxPermSize=16m:设置持久代大小为16m。 <br />
<br />
-XX:MaxTenuringThreshold=0：设置垃圾最大年龄。如果设置为0的话，则年轻代对象不经过Survivor区，直接进入年老代。对于年老代比较多的应用，可以提高效率。如果将此值设置为一个较大值，则年轻代对象会在Survivor区进行多次复制，这样可以增加对象再年轻代的存活时间，增加在年轻代即被回收的概论。 <br />
<br />
2、回收器选择 <br />
<br />
<br />
JVM给了三种选择：串行收集器、并行收集器、并发收集器，但是串行收集器只适用于小数据量的情况，所以这里的选择主要针对并行收集器和并发收集器。默认情况下，JDK5.0以前都是使用串行收集器，如果想使用其他收集器需要在启动时加入相应参数。JDK5.0以后，JVM会根据当前系统配置进行判断。 <br />
<br />
吞吐量优先的并行收集器 <br />
<br />
如上文所述，并行收集器主要以到达一定的吞吐量为目标，适用于科学技术和后台处理等。 <br />
<br />
典型配置： <br />
<br />
java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 <br />
<br />
-XX:+UseParallelGC：选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下，年轻代使用并发收集，而年老代仍旧使用串行收集。 <br />
<br />
-XX:ParallelGCThreads=20：配置并行收集器的线程数，即：同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。 <br />
<br />
<br />
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC <br />
<br />
-XX:+UseParallelOldGC：配置年老代垃圾收集方式为并行收集。JDK6.0支持对年老代并行收集。 <br />
<br />
<br />
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 <br />
<br />
-XX:MaxGCPauseMillis=100:设置每次年轻代垃圾回收的最长时间，如果无法满足此时间，JVM会自动调整年轻代大小，以满足此值。 <br />
<br />
<br />
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:MaxGCPauseMillis=100 -XX:+UseAdaptiveSizePolicy <br />
<br />
-XX:+UseAdaptiveSizePolicy：设置此选项后，并行收集器会自动选择年轻代区大小和相应的Survivor区比例，以达到目标系统规定的最低相应时间或者收集频率等，此值建议使用并行收集器时，一直打开。 <br />
<br />
2. 响应时间优先的并发收集器 <br />
<br />
<br />
如上文所述，并发收集器主要是保证系统的响应时间，减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。 <br />
<br />
典型配置： <br />
<br />
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC <br />
<br />
-XX:+UseConcMarkSweepGC：设置年老代为并发收集。测试中配置这个以后，-XX:NewRatio=4的配置失效了，原因不明。所以，此时年轻代大小最好用-Xmn设置。 <br />
<br />
-XX:+UseParNewGC:设置年轻代为并行收集。可与CMS收集同时使用。JDK5.0以上，JVM会根据系统配置自行设置，所以无需再设置此值。 <br />
<br />
java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection <br />
<br />
-XX:CMSFullGCsBeforeCompaction：由于并发收集器不对内存空间进行压缩、整理，所以运行一段时间以后会产生&#8220;碎片&#8221;，使得运行效率降低。此值设置运行多少次GC以后对内存空间进行压缩、整理。 <br />
<br />
-XX:+UseCMSCompactAtFullCollection：打开对年老代的压缩。可能会影响性能，但是可以消除碎片 <br />
<br />
3、辅助信息 <br />
<br />
<br />
JVM提供了大量命令行参数，打印信息，供调试使用。主要有以下一些： <br />
<br />
-XX:+PrintGC <br />
<br />
输出形式：[GC 118250K-&gt;113543K(130112K), 0.0094143 secs] <br />
<br />
[Full GC 121376K-&gt;10414K(130112K), 0.0650971 secs] <br />
<br />
-XX:+PrintGCDetails <br />
<br />
输出形式：[GC [DefNew: 8614K-&gt;781K(9088K), 0.0123035 secs] 118250K-&gt;113543K(130112K), 0.0124633 secs] <br />
<br />
[GC [DefNew: 8614K-&gt;8614K(9088K), 0.0000665 secs][Tenured: 112761K-&gt;10414K(121024K), 0.0433488 secs] 121376K-&gt;10414K(130112K), 0.0436268 secs] <br />
<br />
-XX:+PrintGCTimeStamps -XX:+PrintGC：PrintGCTimeStamps可与上面两个混合使用 <br />
<br />
输出形式：11.851: [GC 98328K-&gt;93620K(130112K), 0.0082960 secs] <br />
<br />
<br />
-XX:+PrintGCApplicationConcurrentTime:打印每次垃圾回收前，程序未中断的执行时间。可与上面混合使用 <br />
<br />
输出形式：Application time: 0.5291524 seconds <br />
<br />
<br />
-XX:+PrintGCApplicationStoppedTime：打印垃圾回收期间程序暂停的时间。可与上面混合使用 <br />
<br />
输出形式：Total time for which application threads were stopped: 0.0468229 seconds <br />
<br />
<br />
-XX:PrintHeapAtGC:打印GC前后的详细堆栈信息 <br />
<br />
输出形式： <br />
<br />
34.702: [GC {Heap before gc invocations=7: <br />
<br />
def new generation total 55296K, used 52568K [0x1ebd0000, 0x227d0000, 0x227d0000) <br />
<br />
eden space 49152K, 99% used [0x1ebd0000, 0x21bce430, 0x21bd0000) <br />
<br />
from space 6144K, 55% used [0x221d0000, 0x22527e10, 0x227d0000) <br />
<br />
to space 6144K, 0% used [0x21bd0000, 0x21bd0000, 0x221d0000) <br />
<br />
tenured generation total 69632K, used 2696K [0x227d0000, 0x26bd0000, 0x26bd0000) <br />
<br />
the space 69632K, 3% used [0x227d0000, 0x22a720f8, 0x22a72200, 0x26bd0000) <br />
<br />
compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000) <br />
<br />
the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000) <br />
<br />
ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000) <br />
<br />
rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000) <br />
<br />
34.735: [DefNew: 52568K-&gt;3433K(55296K), 0.0072126 secs] 55264K-&gt;6615K(124928K)Heap after gc invocations=8: <br />
<br />
def new generation total 55296K, used 3433K [0x1ebd0000, 0x227d0000, 0x227d0000) <br />
<br />
eden space 49152K, 0% used [0x1ebd0000, 0x1ebd0000, 0x21bd0000) <br />
<br />
from space 6144K, 55% used [0x21bd0000, 0x21f2a5e8, 0x221d0000) <br />
<br />
to space 6144K, 0% used [0x221d0000, 0x221d0000, 0x227d0000) <br />
<br />
tenured generation total 69632K, used 3182K [0x227d0000, 0x26bd0000, 0x26bd0000) <br />
<br />
the space 69632K, 4% used [0x227d0000, 0x22aeb958, 0x22aeba00, 0x26bd0000) <br />
<br />
compacting perm gen total 8192K, used 2898K [0x26bd0000, 0x273d0000, 0x2abd0000) <br />
<br />
the space 8192K, 35% used [0x26bd0000, 0x26ea4ba8, 0x26ea4c00, 0x273d0000) <br />
<br />
ro space 8192K, 66% used [0x2abd0000, 0x2b12bcc0, 0x2b12be00, 0x2b3d0000) <br />
<br />
rw space 12288K, 46% used [0x2b3d0000, 0x2b972060, 0x2b972200, 0x2bfd0000) <br />
<br />
} <br />
<br />
, 0.0757599 secs] <br />
<br />
-Xloggc:filename:与上面几个配合使用，把相关日志信息记录到文件以便分析。 <br />
4、常见配置汇总 <br />
<br />
堆设置 <br />
-Xms:初始堆大小 <br />
-Xmx:最大堆大小 <br />
-XX:NewSize=n:设置年轻代大小 <br />
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3，表示年轻代与年老代比值为1：3，年轻代占整个年轻代年老代和的1/4 <br />
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如：3，表示Eden：Survivor=3：2，一个Survivor区占整个年轻代的1/5 <br />
-XX:MaxPermSize=n:设置持久代大小 <br />
收集器设置 <br />
-XX:+UseSerialGC:设置串行收集器 <br />
-XX:+UseParallelGC:设置并行收集器 <br />
-XX:+UseParalledlOldGC:设置并行年老代收集器 <br />
-XX:+UseConcMarkSweepGC:设置并发收集器 <br />
垃圾回收统计信息 <br />
-XX:+PrintGC <br />
-XX:+PrintGCDetails <br />
-XX:+PrintGCTimeStamps <br />
-Xloggc:filename <br />
并行收集器设置 <br />
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。 <br />
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间 <br />
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) <br />
并发收集器设置 <br />
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。 <br />
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时，使用的CPU数。并行收集线程数。 <br />
<br />
四、调优总结 <br />
<br />
年轻代大小选择 <br />
响应时间优先的应用：尽可能设大，直到接近系统的最低响应时间限制（根据实际情况选择）。在此种情况下，年轻代收集发生的频率也是最小的。同时，减少到达年老代的对象。 <br />
吞吐量优先的应用：尽可能的设置大，可能到达Gbit的程度。因为对响应时间没有要求，垃圾收集可以并行进行，一般适合8CPU以上的应用。 <br />
年老代大小选择 <br />
响应时间优先的应用：年老代使用并发收集器，所以其大小需要小心设置，一般要考虑并发会话率和会话持续时间等一些参数。如果堆设置小了，可以会造成内存碎片、高回收频率以及应用暂停而使用传统的标记清除方式；如果堆大了，则需要较长的收集时间。最优化的方案，一般需要参考以下数据获得： <br />
并发垃圾收集信息 <br />
持久代并发收集次数 <br />
传统GC信息 <br />
花在年轻代和年老代回收上的时间比例 <br />
减少年轻代和年老代花费的时间，一般会提高应用的效率 <br />
吞吐量优先的应用：一般吞吐量优先的应用都有一个很大的年轻代和一个较小的年老代。原因是，这样可以尽可能回收掉大部分短期对象，减少中期的对象，而年老代尽存放长期存活对象。 <br />
较小堆引起的碎片问题 <br />
<br />
因为年老代的并发收集器使用标记、清除算法，所以不会对堆进行压缩。当收集器回收时，他会把相邻的空间进行合并，这样可以分配给较大的对象。但是，当堆空间较小时，运行一段时间以后，就会出现&#8220;碎片&#8221;，如果并发收集器找不到足够的空间，那么并发收集器将会停止，然后使用传统的标记、清除方式进行回收。如果出现&#8220;碎片&#8221;，可能需要进行如下配置： <br />
<br />
-XX:+UseCMSCompactAtFullCollection：使用并发收集器时，开启对年老代的压缩。 <br />
-XX:CMSFullGCsBeforeCompaction=0：上面配置开启的情况下，这里设置多少次Full GC后，对年老代进行压缩</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/313713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2010-02-23 14:09 <a href="http://www.blogjava.net/luluyanglu/archive/2010/02/23/313713.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActiveX控件打包成Cab置于网页中自动下载安装</title><link>http://www.blogjava.net/luluyanglu/archive/2009/12/07/304989.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Mon, 07 Dec 2009 05:09:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/12/07/304989.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/304989.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/12/07/304989.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/304989.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/304989.html</trackback:ping><description><![CDATA[<p>[背景] <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 做过ActiveX控件的朋友都知道，要想把自己做的ActiveX控件功能放在自己的网页上使用，那么用户在客户端就必须进行本地的注册，也就是说用户得首先要把该ActiveX控件(test.ocx)放在本机的%system%/system32下，然后运行DOS工具里面运行regsvr32 test.ocx命令进行注册。但如果真是这么去做的话，那么代表着你处于危险之中了，因为您是通过让用户自己去部署设置环境来达到你的目的，这就失去软件项目本身所存在的价值。那么面对这种情况，我们应该如何解决呢？聪明的你一定会很快就想到，我们可以使用户在客户端自动下载安装该ActiveX控件，这样一来即可以实现我们所想要的功能，又不需要用户自己去部署设置环境，这岂不是一举两得。<br />
[必备条件]<br />
一、用于将ActiveX控件进行打包并加数据鉴名的工具集：<br />
makecert.exe 制作cer格式的证书，即X.509证书，同时可以创建私钥和公钥。<br />
cert2spc.exe&nbsp; 将cer格式证书转换成spc格式证书，即PKCS #7证书。<br />
cabarc.exe&nbsp;&nbsp; 将ocx打包成cab。 <br />
signcode.exe 将证书签署到ocx上去。<br />
chktrust.exe&nbsp; 检查签署证书后的ocx是否正确。<br />
certmgr.exe 是管理证书用的。<br />
&nbsp;<br />
二、用于进行打包用的ocx控件evS1300.ocx。<br />
三、用于查看ocx控件的工具ActvxDoc。<br />
[制作过程]<br />
一、环境设置<br />
1、下载makeCAB包，解压到本地目录（如E盘根目录），如查看到如图1所示的工具集，则表示已下载成功：<br />
&nbsp;</p>
<p><br />
2、设置系统环境变量，右键单击&#8220;我的电脑&#8221;&#224;选择&#8220;属性&#8221;&#224;选择&#8220;高级&#8221;选项卡，打开如图2所示的系统属性面版块：</p>
<p>&nbsp;</p>
<p>3、在系统属性版块里单击&#8220;环境变量（N）&#8221;按钮，打开图3：</p>
<p>&nbsp;</p>
<p>4、选择&#8220;系统变量（S）&#8221;里的&#8220;新建（W）&#8221;按钮，打开&#8220;编辑系统变量&#8221;对话框，如图4所示，然后在&#8220;变量值（V）&#8221;里加入&#8220;;E\makeCAB&#8221;：</p>
<p>二、将用于打包的OCX控件放在E盘根目录下（本文档使用名为evS1300.ocx的控件来进行介绍），如图5所示，其中evS1300.ocx是本文档进行操作的控件对象，而mfc71.dll、msvcp71.dll、msvcr71.dll这三个文件通常是进行打包时一并打包的文件，但不是必须（推荐一起打包），其可在系统中的system32目录下找到，请自行准备。</p>
<p>&nbsp;</p>
<p>三、ActiveX发布步骤</p>
<p>1、单击&#8220;开始&#8221;&#224;&#8220;动行（R）&#8221;&#224;输入&#8220;cmd&#8221;&#224;回车&#224;进入到操作的控件所在的目录，如图6所示：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>2、创建PVK文件(私人密匙文件)，在命令行中输入&#8220;makecert -sk evS1300 evS1300.pvk -n CN=XXXXXXX公司&#8221;，然后回车，如图7所示：</p>
<p>&nbsp;</p>
<p>3、创建CER文件(公司证书)，在命令行中输入&#8220;makecert -sk evS1300.pvk evS1300.cer&#8221;，然后回车，如图8所示，若出现&#8220;Successed&#8221;提示，则会在E:\evS1300目录下生成evS1300.cer文件，如图9所示：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;4、创建SPC测试软件出版商证明书，在命令行中输入&#8220;cert2spc evS1300.cer evS1300.spc&#8221;，然后回车，如图10所示：</p>
<p>&nbsp;</p>
<p>5、创建INF文件，用记录本编辑以下信息 </p>
<p>[version]&nbsp;&nbsp;&nbsp; <br />
signature="$CHINA$"&nbsp;&nbsp; <br />
AdvancedINF=1.0&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
[Add.Code]&nbsp;&nbsp;&nbsp; <br />
evS1300.ocx=evS1300.ocx&nbsp;&nbsp;&nbsp; <br />
msvcr71.dll=msvcr71.dll&nbsp;&nbsp;&nbsp; <br />
mfc71.dll=mfc71.dll&nbsp;&nbsp;&nbsp; <br />
msvcp71.dll=msvcp71.dll&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
[evS1300.ocx]&nbsp;&nbsp;&nbsp; <br />
file=thiscab&nbsp;&nbsp;&nbsp; <br />
clsid={0440906E-9BD6-4F3E-B65A-39E1B339D9DA}&nbsp;&nbsp;&nbsp; <br />
FileVersion=1,0,0,0&nbsp;&nbsp; <br />
RegisterServer=yes&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
[msvcr71.dll]&nbsp;&nbsp;&nbsp; <br />
file-win32-x86=thiscab&nbsp;&nbsp;&nbsp; <br />
RegisterServer=no&nbsp;&nbsp;&nbsp; <br />
DestDir=11&nbsp;&nbsp; <br />
FileVersion=7,10,3052,4&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
[mfc71.dll]&nbsp;&nbsp;&nbsp; <br />
file-win32-x86=thiscab&nbsp;&nbsp;&nbsp; <br />
RegisterServer=no&nbsp;&nbsp;&nbsp; <br />
DestDir=11&nbsp;&nbsp; <br />
FileVersion=7,10,3077,0&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
[msvcp71.dll]&nbsp;&nbsp;&nbsp; <br />
file-win32-x86=thiscab&nbsp;&nbsp;&nbsp; <br />
RegisterServer=no&nbsp;&nbsp;&nbsp; <br />
DestDir=11&nbsp;&nbsp; <br />
FileVersion=7,10,3077,0&nbsp; </p>
<p>&nbsp;</p>
<p><br />
在evS1300.inf的内容里，[version]和[Add.Code]项是必须的，[Add.Code]的键值项的多少取决于以下你所配制项的多少。[msvcr71.dll]、[mfc71.dll]、[msvcp71.dll]就是上面我所说不是必须的项，只要你想把msvcr71.dll、mfc71.dll、msvcp71.dll包括在发布包里，那这么三项就必须写在inf里，而这三项的具体内容是固定的，可复制过去即可。最为关键的就是[evS1300.ocx]项，其中有clsid和FileVersion就是evS1300.ocx的classId和version，这要求必须一至，否我们发布出去的CAB包时不能在客户端自动更新下载安装。说到这里，那我们如何才能知道evS1300.ocx里面的classId和version呢？我在上面的必备条件里介绍到有一个用于查看ocx控件的工具ActvxDoc，对，就是用它，我们双击这个文件运行它，此时可以看到图13所示的界面：</p>
<p>&nbsp;</p>
<p>在图13的界面里，点击&#8220;File&#8221;&#224;&#8220;Open&#8230;&#8221;，打开您所要查看的OCX控件，如图14所示：</p>
<p>&nbsp;</p>
<p>打开了控件之后，我们在界面的右边部位&#8220;Class&#8221;的下拉框里选择&#8220;&#8221;就可以看到我们想要查找的FileVersion和classId，如图15所示：</p>
<p>&nbsp;</p>
<p>6、创建CAB文件，在命令行中输入&#8220;cabarc -s 6144 n evS1300.cab msvcr71.dll mfc71.dll msvcp71.dll evS1300.ocx evS1300.inf&#8221;，然后回车，如图16所示：</p>
<p>&nbsp;</p>
<p>7、使用Code Signing Wizard签署一个CAB文件，首先双击运行工具集里面的signcode.exe（或在命令行里直接输入&#8220;signcode&#8221;后回车），系统会弹出如图17所示的数字签名向导：</p>
<p>&nbsp;</p>
<p>8、单击&#8220;下一步（N）&#8221;按钮，来到图18所示，选择要进行数字签名的且已做成CAB包的文件evS1300.cab文件。</p>
<p>&nbsp;</p>
<p>9、选择好CAB包后单击&#8220;下一步（N）&#8221;按钮，在选择想要的签名类型里选择&#8220;自定议（C）&#8221;并单击&#8220;下一步（N）&#8221;按钮，如图19所示： </p>
<p>&nbsp;</p>
<p>10、接下来单击&#8220;从文件选择（F）&#8221;按钮，选择刚刚制作的evS1300.cer，如图20所示：</p>
<p>&nbsp;</p>
<p>11、在图20中单击&#8220;下一步（N）&#8221;按钮来到图21，然后在图21里选择&#8220;CSP中的私钥（K）&#8221;。</p>
<p>&nbsp;</p>
<p>12、在图21中单击&#8220;下一步（N）&#8221;按钮，然后在图22中的散列算法中选择&#8220;shal&#8221;，并单击&#8220;下一步（N）&#8221;按钮。</p>
<p>&nbsp;</p>
<p>13、在&#8220;证书路径中的证书&#8221;中选择&#8220;证书路径中的所有证书，包括根证书（C）&#8221;，在&#8220;其它证书（可选）&#8221;中选择&#8220;包括在以下PKCS #7 证书（.p7b）文件中的证书（P）：&#8221;，并单击&#8220;浏览（R）&#8230;&#8221;按钮选择evS1300.spc文件，选择完后单击&#8220;下一步（N）&#8221;按钮，如图23所示：</p>
<p>&nbsp;</p>
<p>14、接下来在弹出的&#8220;数据描述&#8221;窗口中输入公司的名称和网址并单击&#8220;下一步（N）&#8221;按钮，如图24所示：</p>
<p>&nbsp;</p>
<p>15、现大部份工作都已完成，在接下来的一步当中是可选的操作，其作用只是为CAB加入时间戳，此步骤完全可以不做，如图25所示：</p>
<p>（这里我提拱三个免费的代码签名时间戳地址）</p>
<p>VeriSign:&nbsp; http://timestamp.verisign.com/scripts/timstamp.dll</p>
<p>Comodo:&nbsp; http://timestamp.comodoca.com/authenticode</p>
<p>GeoTrust/TrustCenter: http://www.trustcenter.de/codesigning/timestamp</p>
<p>&nbsp;</p>
<p>16、完成，在图25中单击&#8220;下一步（N）&#8221;按钮便可来到数字签名向导的最后一步，即操作总览，如图26所示，单击&#8220;完成&#8221;按钮便可大功告成，如图27所示：<br />
</p>
<p><br />
<br />
转：http://blog.csdn.net/qcdn/archive/2008/03/07/2156655.aspx&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/304989.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-12-07 13:09 <a href="http://www.blogjava.net/luluyanglu/archive/2009/12/07/304989.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java内存溢出的详细解决方案</title><link>http://www.blogjava.net/luluyanglu/archive/2009/11/02/300802.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Mon, 02 Nov 2009 15:17:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/11/02/300802.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/300802.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/11/02/300802.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/300802.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/300802.html</trackback:ping><description><![CDATA[<p><strong>一、内存溢出类型</strong></p>
<p>1、java.lang.OutOfMemoryError: PermGen space </p>
<p>JVM管理两种类型的内存，堆和非堆。堆是给开发人员用的上面说的就是，是在JVM启动时创建；非堆是留给JVM自己用的，用来存放类的信息的。它和堆不同，运行期内GC不会释放空间。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小，超出了也会导致这块内存的占用过多造成溢出，或者tomcat热部署时侯不会清理前面加载的环境，只会将context更改为新部署的，非堆存的内容就会越来越多。</p>
<p>PermGen space的全称是Permanent Generation space,是指内存的永久保存区域，这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中，它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理，所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误，这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。 <br />
一个最佳的配置例子：(经过本人验证，自从用此配置之后，再未出现过tomcat死掉的情况)</p>
<p>set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m</p>
<p>2、java.lang.OutOfMemoryError: Java heap space</p>
<p>第一种情况是个补充，主要存在问题就是出现在这个情况中。其默认空间(即-Xms)是物理内存的1/64，最大空间(-Xmx)是物理内存的1/4。如果内存剩余不到40％，JVM就会增大堆到Xmx设置的值，内存剩余超过70％，JVM就会减小堆到Xms设置的值。所以服务器的Xmx和Xms设置一般应该设置相同避免每次GC后都要调整虚拟机堆的大小。假设物理内存无限大，那么JVM内存的最大值跟操作系统有关，一般32位机是1.5g到3g之间，而64位的就不会有限制了。</p>
<p>注意：如果Xms超过了Xmx值，或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。</p>
<p><strong>垃圾回收GC的角色</strong></p>
<p>JVM调用GC的频度还是很高的，主要两种情况下进行垃圾回收：</p>
<p>当应用程序线程空闲；另一个是java内存堆不足时，会不断调用GC，若连续回收都解决不了内存堆不足的问题时，就会报out of memory错误。因为这个异常根据系统运行环境决定，所以无法预期它何时出现。</p>
<p>根据GC的机制，程序的运行会引起系统运行环境的变化，增加GC的触发机会。</p>
<p>为了避免这些问题，程序的设计和编写就应避免垃圾对象的内存占用和GC的开销。显示调用System.GC()只能建议JVM需要在内存中对垃圾对象进行回收，但不是必须马上回收，</p>
<p>一个是并不能解决内存资源耗空的局面，另外也会增加GC的消耗。</p>
<p><strong>二、JVM内存区域组成</strong></p>
<p>简单的说java中的堆和栈</p>
<p>java把内存分两种：一种是栈内存，另一种是堆内存</p>
<p>1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配；</p>
<p>2。堆内存用来存放由new创建的对象和数组</p>
<p>在函数（代码块）中定义一个变量时，java就在栈中为这个变量分配内存空间，当超过变量的作用域后，java会自动释放掉为该变量所分配的内存空间；在堆中分配的内存由java虚拟机的自动垃圾回收器来管理</p>
<p>堆的优势是可以动态分配内存大小，生存期也不必事先告诉编译器，因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存，存取速度较慢；</p>
<p>栈的优势是存取速度比堆要快，缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。</p>
<p>java堆分为三个区：New、Old和Permanent</p>
<p>GC有两个线程：</p>
<p>新创建的对象被分配到New区，当该区被填满时会被GC辅助线程移到Old区，当Old区也填满了会触发GC主线程遍历堆内存里的所有对象。Old区的大小等于Xmx减去-Xmn</p>
<p><strong>java栈存放</strong></p>
<p>栈调整：参数有+UseDefaultStackSize -Xss256K，表示每个线程可申请256k的栈空间</p>
<p>每个线程都有他自己的Stack</p>
<p><strong>三、JVM如何设置虚拟内存</strong></p>
<p>提示：在JVM中如果98％的时间是用于GC且可用的Heap size 不足2％的时候将抛出此异常信息。</p>
<p>提示：Heap Size 最大不要超过可用物理内存的80％，一般的要将-Xms和-Xmx选项设置为相同，而-Xmn为1/4的-Xmx值。 </p>
<p>提示：JVM初始分配的内存由-Xms指定，默认是物理内存的1/64；JVM最大分配的内存由-Xmx指定，默认是物理内存的1/4。</p>
<p>默认空余堆内存小于40%时，JVM就会增大堆直到-Xmx的最大限制；空余堆内存大于70%时，JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。 </p>
<p>提示：假设物理内存无限大的话，JVM内存的最大值跟操作系统有很大的关系。</p>
<p>简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制，</p>
<p>这个限制一般是2GB-3GB（一般来说Windows系统下为1.5G-2G，Linux系统下为2G-3G），而64bit以上的处理器就不会有限制了</p>
<p>提示：注意：如果Xms超过了Xmx值，或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。</p>
<p>提示：设置NewSize、MaxNewSize相等，"new"的大小最好不要大于"old"的一半，原因是old区如果不够大会频繁的触发"主" GC ，大大降低了性能</p>
<p>JVM使用-XX:PermSize设置非堆内存初始值，默认是物理内存的1/64；</p>
<p>由XX:MaxPermSize设置最大非堆内存的大小，默认是物理内存的1/4。</p>
<p>解决方法：手动设置Heap size</p>
<p>修改TOMCAT_HOME/bin/catalina.bat</p>
<p>在&#8220;echo "Using CATALINA_BASE: $CATALINA_BASE"&#8221;上面加入以下行：</p>
<p>JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"</p>
<p><strong>四、性能检查工具使用</strong></p>
<p>定位内存泄漏：</p>
<p>JProfiler工具主要用于检查和跟踪系统（限于Java开发的）的性能。JProfiler可以通过时时的监控系统的内存使用情况，随时监视垃圾回收，线程运行状况等手段，从而很好的监视JVM运行情况及其性能。</p>
<p>1. 应用服务器内存长期不合理占用，内存经常处于高位占用，很难回收到低位； </p>
<p>2. 应用服务器极为不稳定，几乎每两天重新启动一次，有时甚至每天重新启动一次； </p>
<p>3. 应用服务器经常做Full GC(Garbage Collection)，而且时间很长，大约需要30-40秒，应用服务器在做Full GC的时候是不响应客户的交易请求的，非常影响系统性能。 </p>
<p>因为开发环境和产品环境会有不同，导致该问题发生有时会在产品环境中发生，通常可以使用工具跟踪系统的内存使用情况，在有些个别情况下或许某个时刻确实是使用了大量内存导致out of memory，这时应继续跟踪看接下来是否会有下降，</p>
<p>如果一直居高不下这肯定就因为程序的原因导致内存泄漏。</p>
<p><strong>五、不健壮代码的特征及解决办法</strong></p>
<p>1、尽早释放无用对象的引用。好的办法是使用临时变量的时候，让引用变量在退出活动域后，自动设置为null，暗示垃圾收集器来收集该对象，防止发生内存泄露。</p>
<p>对于仍然有指针指向的实例，jvm就不会回收该资源,因为垃圾回收会将值为null的对象作为垃圾，提高GC回收机制效率；</p>
<p>2、我们的程序里不可避免大量使用字符串处理，避免使用String，应大量使用StringBuffer，每一个String对象都得独立占用内存一块区域；</p>
<p>String str = "aaa"; </p>
<p>String str2 = "bbb"; </p>
<p>String str3 = str + str2;//假如执行此次之后str ,str2以后再不被调用,那它就会被放在内存中等待Java的gc去回收,程序内过多的出现这样的情况就会报上面的那个错误,建议在使用字符串时能使用StringBuffer就不要用String,这样可以省不少开销； </p>
<p>3、尽量少用静态变量，因为静态变量是全局的，GC不会回收的；</p>
<p>4、避免集中创建对象尤其是大对象，JVM会突然需要大量内存，这时必然会触发GC优化系统内存环境；显示的声明数组空间，而且申请数量还极大。</p>
<p>这是一个案例想定供大家警戒</p>
<p>使用jspsmartUpload作文件上传,运行过程中经常出现java.outofMemoryError的错误，</p>
<p>检查之后发现问题：组件里的代码</p>
<p>m_totalBytes = m_request.getContentLength();</p>
<p>m_binArray = new byte[m_totalBytes];</p>
<p>问题原因是totalBytes这个变量得到的数极大，导致该数组分配了很多内存空间，而且该数组不能及时释放。解决办法只能换一种更合适的办法，至少是不会引发outofMemoryError的方式解决。参考：<a href="http://bbs.xml.org.cn/blog/more.asp?name=hongrui&amp;id=3747">http://bbs.xml.org.cn/blog/more.asp?name=hongrui&amp;id=3747</a></p>
<p>5、尽量运用对象池技术以提高系统性能；生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏，例如大集合对象拥有大数据量的业务对象的时候，可以考虑分块进行处理，然后解决一块释放一块的策略。</p>
<p>6、不要在经常调用的方法中创建对象，尤其是忌讳在循环中创建对象。可以适当的使用hashtable，vector 创建一组对象容器，然后从容器中去取那些对象，而不用每次new之后又丢弃</p>
<p>7、一般都是发生在开启大型文件或跟数据库一次拿了太多的数据，造成 Out Of Memory Error 的状况，这时就大概要计算一下数据量的最大值是多少，并且设定所需最小及最大的内存空间值。</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/300802.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-11-02 23:17 <a href="http://www.blogjava.net/luluyanglu/archive/2009/11/02/300802.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中的时间转换及时间对比</title><link>http://www.blogjava.net/luluyanglu/archive/2009/09/07/294157.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Mon, 07 Sep 2009 04:17:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/09/07/294157.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/294157.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/09/07/294157.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/294157.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/294157.html</trackback:ping><description><![CDATA[<p style="text-indent: 2em">&nbsp;SimpleDateFormat函数语法：</p>
<p style="text-indent: 2em">&nbsp;&nbsp;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; G 年代标志符</p>
<p style="text-indent: 2em">&nbsp;&nbsp; y 年</p>
<p style="text-indent: 2em">&nbsp;&nbsp; M 月</p>
<p style="text-indent: 2em">&nbsp;&nbsp; d 日</p>
<p style="text-indent: 2em">&nbsp;&nbsp; h 时 在上午或下午 (1~12)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; H 时 在一天中 (0~23)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; m 分</p>
<p style="text-indent: 2em">&nbsp;&nbsp; s 秒</p>
<p style="text-indent: 2em">&nbsp;&nbsp; S 毫秒</p>
<p style="text-indent: 2em">&nbsp;&nbsp; E 星期</p>
<p style="text-indent: 2em">&nbsp;&nbsp; D 一年中的第几天</p>
<p style="text-indent: 2em">&nbsp;&nbsp; F 一月中第几个星期几</p>
<p style="text-indent: 2em">&nbsp;&nbsp; w 一年中第几个星期</p>
<p style="text-indent: 2em">&nbsp;&nbsp; W 一月中第几个星期</p>
<p style="text-indent: 2em">&nbsp;&nbsp; a 上午 / 下午 标记符 </p>
<p style="text-indent: 2em">&nbsp;&nbsp; k 时 在一天中 (1~24)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; K 时 在上午或下午 (0~11)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; z 时区</p>
<p style="text-indent: 2em">*/</p>
<p style="text-indent: 2em"></p>
<li>
<li>DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>DateFormat format 2= new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>Date date = null;&nbsp;&nbsp;&nbsp;
<li>String str = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>// String转Date &nbsp;&nbsp;
<li>str = "2007-1-18";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<li>try {&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp; date = format1.parse(str);&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp; da<wbr>ta = format2.parse(str);
<li>} catch (ParseException e) {&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;
<li>}&nbsp;&nbsp;&nbsp;
<li>&nbsp;&nbsp;
<li>//Date转String
<li>date=new Date();
<li>str=format1.format(date);
<li>str=format2.format(date);
<p>&nbsp;</p>
<p style="text-indent: 2em"></p>
<p style="text-indent: 2em">1、Date——&gt;String</p>
<p style="text-indent: 2em">String sdate;</p>
<p style="text-indent: 2em">Date ddate;</p>
<p style="text-indent: 2em">&#8230;&#8230;</p>
<p style="text-indent: 2em">sdate=(new SimpleDateFormat("yyyy-MM-dd")).format(ddate);</p>
<p style="text-indent: 2em"></p>
<p style="text-indent: 2em">2、String——&gt;Date</p>
<p style="text-indent: 2em">SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");</p>
<p style="text-indent: 2em">sdf.setLenient(false);</p>
<p style="text-indent: 2em">String sdate="2006-06-06";</p>
<p style="text-indent: 2em">Date ddate;</p>
<p style="text-indent: 2em">ddate=sdf.parse(sdate);</p>
<p style="text-indent: 2em"></p>
<p style="text-indent: 2em">另外Integer、Double等数据包装类型与String类型的相互转换为：</p>
<p style="text-indent: 2em">（以Integer为例）</p>
<p style="text-indent: 2em">Integer——&gt;String</p>
<p style="text-indent: 2em">Integer ii;</p>
<p style="text-indent: 2em">String si;</p>
<p style="text-indent: 2em">&#8230;&#8230;</p>
<p style="text-indent: 2em">si=ii.toString;</p>
<p style="text-indent: 2em"></p>
<p style="text-indent: 2em">String——&gt;Intteger</p>
<p style="text-indent: 2em">Integer ii;</p>
<p style="text-indent: 2em">String si;</p>
<p style="text-indent: 2em">&#8230;&#8230;</p>
<p style="text-indent: 2em">ii=Integer.valueOf(si);</p>
<p style="text-indent: 2em">字符串转换成时间及时间相减：<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1:) SimpleDateFormat formatter = new SimpleDateFormat （"yyyy.MM.dd");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //假定像2002.07.04的是合法日期其他都非法。<br />
&nbsp;&nbsp;&nbsp;&nbsp; String str="2002.07.04";<br />
&nbsp;&nbsp;&nbsp;&nbsp; ParsePosition pos = new ParsePosition(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp; Date dt=formatter.parse(str,pos);<br />
&nbsp;&nbsp;&nbsp; if(dt!=null)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //是合法日期<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //非法日期<br />
&nbsp;&nbsp;&nbsp; }<br />
</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>2:)<br />
两个日期相减<br />
imp<wbr>ort java.util.*;<br />
imp<wbr>ort java.text.*; <br />
class a <br />
{<br />
public static void main(String[] args) <br />
{<br />
&nbsp;&nbsp; String s1 = "2003/08/15 17:15:30";<br />
&nbsp;&nbsp; String s2 = "2002/09/14 14:18:37";<br />
&nbsp;&nbsp; try{ <br />
&nbsp;&nbsp; SimpleDateFormat formatter = new SimpleDateFormat ("yyyy/MM/dd HH:mm:ss");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp; ParsePosition pos = new ParsePosition(0);<br />
&nbsp;&nbsp; ParsePosition pos1 = new ParsePosition(0);<br />
&nbsp;&nbsp; Date dt1=formatter.parse(s1,pos);<br />
&nbsp;&nbsp; Date dt2=formatter.parse(s2,pos1);<br />
&nbsp;&nbsp; System.out.println("dt1="+dt1);<br />
&nbsp;&nbsp; System.out.println("dt2="+dt2);<br />
&nbsp;&nbsp; long l = dt1.getTime() - dt2.getTime();<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp; System.out.println("Hello World!="+l);<br />
&nbsp;&nbsp; }catch(Exception e){<br />
&nbsp;&nbsp;&nbsp; System.out.println("exception"+e.toString());<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp;<br />
}<br />
}</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p><br />
3:)得到2个月后的日期：<br />
imp<wbr>ort java.util.*;<br />
imp<wbr>ort java.text.DateFormat;<br />
public class test2<br />
{<br />
&nbsp;&nbsp; public static void main(String args[]) throws Exception<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; String date="2001/11/30";<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; DateFormat dateFormat =<br />
&nbsp;&nbsp; DateFormat.getDateInstance(DateFormat.MEDIUM);<br />
&nbsp;&nbsp;&nbsp; GregorianCalendar grc=new GregorianCalendar();<br />
&nbsp;&nbsp;&nbsp; grc.setTime(new Date(date));</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p><br />
&nbsp;&nbsp;&nbsp; grc.add(GregorianCalendar.MONTH,2);<br />
&nbsp;&nbsp;&nbsp; System.out.println("grc="+dateFormat.format(grc.getTime()));&nbsp;&nbsp;<br />
&nbsp;&nbsp; }<br />
}</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>15.计算日期间隔<br />
public int getDays(Date sd,Date ed){<br />
&nbsp;&nbsp; return (ed.getTime()-sd.getTime())/(3600*24*1000)<br />
}</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>16.日期加减<br />
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");<br />
String str="20011230";<br />
Date dt=sdf.parse(str,new ParsePosition(0));<br />
Calendar rightNow = Calendar.getInstance();<br />
rightNow.setTime(dt);<br />
rightNow.add(Calendar.DATE,2);//你要加减的日期 <br />
Date dt1=rightNow.getTime();<br />
String reStr=sdf.format(dt1,"",new FieldPosition(0));<br />
System.out.println(reStr);</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>17.时间显示控制&nbsp;&nbsp;&nbsp;<br />
第一种方式： <br />
&lt;html&gt; <br />
&lt;head&gt;&lt;title&gt;取得系统时间&lt;/title&gt;&lt;/head&gt; <br />
&lt;body&gt; <br />
&lt;%java.util.Date date=new java.util.Date();%&gt; <br />
现在是：&lt;%=date%&gt; <br />
&lt;/body&gt; <br />
&lt;/html&gt; <br />
运行结果： <br />
现在是：Tue Jul 31 10:32:52 CST 2001</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>第二种方式： <br />
&lt;%@ page imp<wbr>ort="java.util.*, java.text.*" %&gt; <br />
&lt;HTML&gt; <br />
&lt;HEAD&gt;&lt;TITLE&gt;显示当前时间&lt;/TITLE&gt;&lt;/HEAD&gt; <br />
&lt;BODY&gt; <br />
当前时间： <br />
&lt;% <br />
Date now = new Date(); <br />
out.println(DateFormat.getTimeInstance().format(now)); <br />
%&gt; <br />
&lt;/BODY&gt; <br />
&lt;/HTML&gt; <br />
运行结果： <br />
10:31:42 AM</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>第三种方式： <br />
&lt;% <br />
java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy年MM月dd日"); <br />
java.util.Date currentTime_1 = new java.util.Date(); <br />
out.print(formatter.format(currentTime_1)); <br />
%&gt; <br />
运行结果： <br />
2001年07月31日</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>&nbsp;</p>
<p style="text-indent: 2em"><br />
&nbsp;</p>
<p>第四种方式： <br />
&lt;% <br />
java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat("yyyy/MM/dd HH/mm/ss"); <br />
java.util.Date currentTime_1 = new java.util.Date(); <br />
out.print(formatter.format(currentTime_1)); <br />
%&gt; <br />
运行结果： <br />
2001/07/31 10/32/52 <br />
第三四两种方式其实是一样的他可以产生千变万化的格式。</p>
<p style="text-indent: 2em"><font color="#ff0000">//比较两个时间是否相同</font> </p>
<p style="text-indent: 2em"><font color="#ff0000">public class Test {</font> </p>
<p style="text-indent: 2em"><font color="#ff0000">&nbsp;/**<br />
&nbsp; * @param args<br />
&nbsp; */<br />
&nbsp;<br />
&nbsp;private static boolean isSameDate(Date date){<br />
&nbsp;&nbsp;Calendar calendar=Calendar.getInstance();<br />
&nbsp;&nbsp;//int todays=calendar.get(Calendar.DAY_OF_YEAR);<br />
//&nbsp;&nbsp;calendar.setTime(date);<br />
&nbsp;//&nbsp;int lastDate=calendar.get(Calendar.DAY_OF_YEAR);<br />
&nbsp;&nbsp;if(calendar.getTime().after(date)){//判断当前时间是否为以后的时间<br />
&nbsp;&nbsp;&nbsp;return true;<br />
&nbsp;&nbsp;}else{<br />
&nbsp;&nbsp;&nbsp;return false;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;public static void main(String[] args) throws ParseException {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");<br />
&nbsp;&nbsp;sdf.setLenient(false);<br />
&nbsp;&nbsp;String sdate="2009-08-28";<br />
&nbsp;&nbsp;Date ddate;<br />
&nbsp;&nbsp;ddate=sdf.parse(sdate);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;Date da=new Date();<br />
&nbsp;&nbsp;System.out.println(da);<br />
&nbsp;<br />
&nbsp;&nbsp;isSameDate(da);<br />
&nbsp;&nbsp;System.out.println(isSameDate(ddate));<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;}</font> </p>
<p style="text-indent: 2em"><font color="#ff0000">}</font> </p>
<p style="text-indent: 2em"><font color="#ff0000"></font>&nbsp;</p>
</li>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/294157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-09-07 12:17 <a href="http://www.blogjava.net/luluyanglu/archive/2009/09/07/294157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中的值传递和引用传递</title><link>http://www.blogjava.net/luluyanglu/archive/2009/04/01/263450.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Wed, 01 Apr 2009 14:42:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/04/01/263450.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/263450.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/04/01/263450.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/263450.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/263450.html</trackback:ping><description><![CDATA[<div class="postTitle"><a class="postTitle2" id="viewpost1_TitleUrl" href="http://www.blogjava.net/jiafang83/archive/2007/10/23/155412.html">java中的值传递和引用传递</a> </div>
值传递：方法调用时，实际参数把它的值传递给对应的形式参数，方法执行中形式参数值的改变不影响实际参&nbsp;数的值。<br />
引用传递：也称为传地址。方法调用时，实际参数的引用(地址，而不是参数的值)被传递给方法中相对应的形式参数，在方法执行中，对形式参数的操作实际上就是对实际参数的操作，方法执行中形式参数值的改变将会影响实际参数的值。<br />
下面举例说明：<br />
<strong><em><span style="color: red"><strong><em style="color: #ff6600">传值---传递基本数据类型参数<br />
</em></strong></span>基本类型变量，包括char、byte、short、int、long、float、double、boolean。 <br />
<br />
</em></strong>public&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PassValue{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static void exchange(int a, int b){//静态方法，交换a,b的值<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp = a;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a = b;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i = 10;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j = 100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("before call: " + "i=" + i + "\t" + "j = " + j);//调用前<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exchange(i, j);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//值传递，main方法只能调用静态方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("after call: " + "i=" + i + "\t" + "j = " + j);//调用后<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
运行结果：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before call: i = 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;after&nbsp;&nbsp;&nbsp;&nbsp;call: i = 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = 100<br />
说明：调用exchange(i, j)时，实际参数i，j分别把值传递给相应的形式参数a，b,在执行方法exchange()时，形式参数a，b的值的改变不影响实际参数i和j的值，i和j的值在调用前后并没改变。<br />
<strong><em style="color: #ff6600">引用传递---对象作为参数<br />
引用类型变量，包括类、接口、数组（基本类型数组和对象数组）。 <br />
</em></strong>如果在方法中把对象（或数组）作为参数，方法调用时，参数传递的是对象的引用（地址），即在方法调用时，实际参数把对对象的引用（地址）传递给形式参数。这是实际参数与形式参数指向同一个地址，即同一个对象（数组），方法执行时，对形式参数的改变实际上就是对实际参数的改变，这个结果在调用结束后被保留了下来。<br />
class Book{<br />
&nbsp;&nbsp;&nbsp;&nbsp;String name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;private folat price;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Book(String n,&nbsp;&nbsp;&nbsp;&nbsp;float ){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//构造方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name = n;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;price = p;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;&nbsp;void&nbsp; change(Book a_book,&nbsp;&nbsp;&nbsp;&nbsp;String n,&nbsp;&nbsp;&nbsp;&nbsp;float p){&nbsp;&nbsp;&nbsp;&nbsp;//静态方法，对象作为参数<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a_book.name = n;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a_book.price = p;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void output(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//实例方法，输出对象信息<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("name: " + name + "\t" + "price: " + price);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
&nbsp;public class PassAddr{<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String [] args){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Book b = new Book("java2",&nbsp;&nbsp;&nbsp;&nbsp;32.5f);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print("before call:\t");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//调用前<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b.output();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b.change(b,&nbsp;&nbsp;&nbsp;&nbsp;"c++",&nbsp;&nbsp;&nbsp;&nbsp;45.5f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//引用传递，传递对象b的引用，修改对象b的值<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print("after call:\t");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//调用后<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b.output();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
运行结果：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before&nbsp;&nbsp;&nbsp;&nbsp;call:&nbsp;&nbsp;&nbsp;&nbsp;name:java2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;price:32.5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;after&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;call:&nbsp;&nbsp;&nbsp;&nbsp;name:c++&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;price:45.5<br />
说明：调用change(b,"c++",45.5f)时，对象b作为实际参数，把引用传递给相应的形式参数a_book,实际上a_book也指向同一个对象，即该对象有两个引用名：b和a_book。在执行方法change()时，对形式参数a_book操作就是对实际参数b的操作。<br />
<img src ="http://www.blogjava.net/luluyanglu/aggbug/263450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-04-01 22:42 <a href="http://www.blogjava.net/luluyanglu/archive/2009/04/01/263450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA面试题集</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259891.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 14:13:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259891.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259891.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259891.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259891.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259891.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;java基础知识：1.C++或Java中的异常处理机制的简单原理和应用。当JAVA程序违反了JAVA的语义规则时，JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种情况就...&nbsp;&nbsp;<a href='http://www.blogjava.net/luluyanglu/archive/2009/03/15/259891.html'>阅读全文</a><img src ="http://www.blogjava.net/luluyanglu/aggbug/259891.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 22:13 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259891.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>23种设计模式的代码</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259890.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 14:10:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259890.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259890.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259890.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259890.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259890.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: java代码:&nbsp; package lq.test; import java.io.*; import java.util.*; //*********创建型模式*************** //factory method 1 //1具体的构造算法，和2构造出的具体产品由子类实现&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs...&nbsp;&nbsp;<a href='http://www.blogjava.net/luluyanglu/archive/2009/03/15/259890.html'>阅读全文</a><img src ="http://www.blogjava.net/luluyanglu/aggbug/259890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 22:10 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>制作可执行的JAR文件包及jar命令详解</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259888.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 14:00:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259888.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259888.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259888.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259888.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259888.html</trackback:ping><description><![CDATA[<p>常在网上看到有人询问：如何把 java 程序编译成 .exe 文件。通常回答只有两种，一种是制作一个可执行的 JAR 文件包，然后就可以像.chm 文档一样双击运行了；而另一种是使用 JET 来进行&nbsp;&nbsp; <br />
编译。但是 JET 是要用钱买的，而且据说 JET 也不是能把所有的 Java 程序都编译成执行文件，性能也要打些折扣。所以，使用制作可执行 JAR 文件包的方法就是最佳选择了，何况它还能保持 Java 的跨平台特性。 </p>
<p>下面就来看看什么是 JAR 文件包吧： </p>
<p>1. JAR 文件包 </p>
<p>JAR 文件就是 Java Archive File，顾名思意，它的应用是与 Java 息息相关的，是 Java 的一种文档格式。JAR 文件非常类似 ZIP 文件——准确的说，它就是 ZIP 文件，所以叫它文件包。JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中，包含了一个 META-INF/MANIFEST.MF 文件，这个文件是在生成 JAR 文件的时候自动创建的。举个例子，如果我们具有如下目录结构的一些文件： </p>
<p>　　== </p>
<p>　　`-- test </p>
<p>　　　 `-- Test.class </p>
<p>把它压缩成 ZIP 文件 test.zip，则这个 ZIP 文件的内部目录结构为： </p>
<p>　　test.zip </p>
<p>　　`-- test </p>
<p>　　　 `-- Test.class </p>
<p>如果我们使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar，则这个 JAR 文件的内部目录结构为： </p>
<p>　　test.jar </p>
<p>　　|-- META-INF </p>
<p>　　|　 `-- MANIFEST.MF </p>
<p>　　`-- test </p>
<p>　　　　`--Test.class </p>
<p>2. 创建可执行的 JAR 文件包 </p>
<p>制作一个可执行的 JAR 文件包来发布你的程序是 JAR 文件包最典型的用法。 </p>
<p>Java 程序是由若干个 .class 文件组成的。这些 .class 文件必须根据它们所属的包不同而分级分目录存放；运行前需要把所有用到的包的根目录指定给 CLASSPATH 环境变量或者 java 命令的 -cp 参数；运行时还要到控制台下去使用 java 命令来运行，如果需要直接双击运行必须写 Windows 的批处理文件 (.bat) 或者 Linux 的 Shell 程序。因此，许多人说，Java 是一种方便开发者苦了用户的程序设计语言。 </p>
<p>其实不然，如果开发者能够制作一个可执行的 JAR 文件包交给用户，那么用户使用起来就方便了。在 Windows 下安装 JRE (Java Runtime Environment) 的时候，安装文件会将 .jar 文件映射给 javaw.exe 打开。那么，对于一个可执行的 JAR 文件包，用户只需要双击它就可以运行程序了，和阅读 .chm 文档一样方便 (.chm 文档默认是由 hh.exe 打开的)。那么，现在的关键，就是如何来创建这个可执行的 JAR 文件包。 </p>
<p>创建可执行的 JAR 文件包，需要使用带 cvfm 参数的 jar 命令，同样以上述 test 目录为例，命令如下： </p>
<p>jar cvfm test.jar manifest.mf test </p>
<p>这里 test.jar 和 manifest.mf 两个文件，分别是对应的参数 f 和 m，其重头戏在 manifest.mf。因为要创建可执行的 JAR 文件包，光靠指定一个 manifest.mf 文件是不够的，因为 MANIFEST 是 JAR 文件包的特征，可执行的 JAR 文件包和不可执行的 JAR 文件包都包含 MANIFEST。关键在于可执行 JAR 文件包的 MANIFEST，其内容包含了 Main-Class 一项。这在 MANIFEST 中书写格式如下： </p>
<p>Main-Class: 可执行主类全名(包含包名) </p>
<p>例如，假设上例中的 Test.class 是属于 test 包的，而且是可执行的类 (定义了 public static void main(String[]) 方法)，那么这个 manifest.mf 可以编辑如下： </p>
<p>Main-Class: test.Test &lt;回车&gt; </p>
<p>这个 manifest.mf 可以放在任何位置，也可以是其它的文件名，只需要有 Main-Class: test.Test 一行，且该行以一个回车符结束即可。创建了 manifest.mf 文件之后，我们的目录结构变为： </p>
<p>　　== </p>
<p>　　|-- test </p>
<p>　　|　 `-- Test.class </p>
<p>　　`-- manifest.mf </p>
<p>这时候，需要到 test 目录的上级目录中去使用 jar 命令来创建 JAR 文件包。也就是在目录树中使用&#8220;==&#8221;表示的那个目录中，使用如下命令： </p>
<p>jar cvfm test.jar manifest.mf test </p>
<p>之后在&#8220;==&#8221;目录中创建了 test.jar，这个 test.jar 就是执行的 JAR 文件包。运行时只需要使用 java -jar test.jar 命令即可。 </p>
<p>需要注意的是，创建的 JAR 文件包中需要包含完整的、与 Java 程序的包结构对应的目录结构，就像上例一样。而 Main-Class 指定的类，也必须是完整的、包含包路径的类名，如上例的 test.Test；而且在没有打成 JAR 文件包之前可以使用 java &lt;类名&gt; 来运行这个类，即在上例中 java test.Test 是可以正确运行的 (当然要在 CLASSPATH 正确的情况下)。 </p>
<p>3. jar 命令详解 </p>
<p>jar 是随 JDK 安装的，在 JDK 安装目录下的 bin 目录中，Windows 下文件名为 jar.exe，Linux 下文件名为 jar。它的运行需要用到 JDK 安装目录下 lib 目录中的 tools.jar 文件。不过我们除了安装 JDK 什么也不需要做，因为 SUN 已经帮我们做好了。我们甚至不需要将 tools.jar 放到 CLASSPATH 中。 </p>
<p>使用不带任何的 jar 命令我们可以看到 jar 命令的用法如下： </p>
<p>jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目录] 文件名 ... </p>
<p>其中 {ctxu} 是 jar 命令的子命令，每次 jar 命令只能包含 ctxu 中的一个，它们分别表示： </p>
<p>-c　创建新的 JAR 文件包 </p>
<p>-t　列出 JAR 文件包的内容列表 </p>
<p>-x　展开 JAR 文件包的指定文件或者所有文件 </p>
<p>-u　更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中) </p>
<p>[vfm0M] 中的选项可以任选，也可以不选，它们是 jar 命令的选项参数 </p>
<p>-v　生成详细报告并打印到标准输出 </p>
<p>-f　指定 JAR 文件名，通常这个参数是必须的 </p>
<p>-m　指定需要包含的 MANIFEST 清单文件 </p>
<p>-0　只存储，不压缩，这样产生的 JAR 文件包会比不用该参数产生的体积大，但速度更快 </p>
<p>-M　不产生所有项的清单（MANIFEST〕文件，此参数会忽略 -m 参数 </p>
<p>[jar-文件] 即需要生成、查看、更新或者解开的 JAR 文件包，它是 -f 参数的附属参数 </p>
<p>[manifest-文件] 即 MANIFEST 清单文件，它是 -m 参数的附属参数 </p>
<p>[-C 目录] 表示转到指定目录下去执行这个 jar 命令的操作。它相当于先使用 cd 命令转该目录下再执行不带 -C 参数的 jar 命令，它只能在创建和更新 JAR 文件包的时候可用。　　 </p>
<p>文件名 ... 指定一个文件/目录列表，这些文件/目录就是要添加到 JAR 文件包中的文件/目录。如果指定了目录，那么 jar 命令打包的时候会自动把该目录中的所有文件和子目录打入包中。 </p>
<p>下面举一些例子来说明 jar 命令的用法： </p>
<p>1) jar cf test.jar test </p>
<p>该命令没有执行过程的显示，执行结果是在当前目录生成了 test.jar 文件。如果当前目录已经存在 test.jar，那么该文件将被覆盖。 </p>
<p>2) jar cvf test.jar test </p>
<p>该命令与上例中的结果相同，但是由于 v 参数的作用，显示出了打包过程，如下： </p>
<p>标明清单(manifest) </p>
<p>增加：test/(读入= 0) (写出= 0)(存储了 0%) </p>
<p>增加：test/Test.class(读入= 7) (写出= 6)(压缩了 14%) </p>
<p>3) jar cvfM test.jar test </p>
<p>该命令与 2) 结果类似，但在生成的 test.jar 中没有包含 META-INF/MANIFEST 文件，打包过程的信息也略有差别： </p>
<p>增加：test/(读入= 0) (写出= 0)(存储了 0%) </p>
<p>增加：test/Test.class(读入= 7) (写出= 6)(压缩了 14%) </p>
<p>4) jar cvfm test.jar manifest.mf test </p>
<p>运行结果与 2) 相似，显示信息也相同，只是生成 JAR 包中的 META-INF/MANIFEST 内容不同，是包含了 manifest.mf 的内容 </p>
<p>5) jar tf test.jar </p>
<p>在 test.jar 已经存在的情况下，可以查看 test.jar 中的内容，如对于 2) 和 3) 生成的 test.jar 分别应该此命令，结果如下； </p>
<p>对于 2) </p>
<p>META-INF/ </p>
<p>META-INF/MANIFEST.MF </p>
<p>test/ </p>
<p>test/Test.class </p>
<p>对于 3) </p>
<p>test/ </p>
<p>test/Test.class </p>
<p>6) jar tvf test.jar </p>
<p>除显示 5) 中显示的内容外，还包括包内文件的详细信息，如： </p>
<p>&nbsp;0 Wed Jun 19 15:39:06 GMT 2002 META-INF/ </p>
<p>86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF </p>
<p>&nbsp;0 Wed Jun 19 15:33:04 GMT 2002 test/ </p>
<p>&nbsp;7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class </p>
<p>7) jar xf test.jar </p>
<p>解开 test.jar 到当前目录，不显示任何信息，对于 2) 生成的 test.jar，解开后的目录结构如下： </p>
<p>　　== </p>
<p>　　|-- META-INF </p>
<p>　　|　 `-- MANIFEST </p>
<p>　　`-- test </p>
<p>　　　　`--Test.class </p>
<p>8) jar xvf test.jar </p>
<p>运行结果与 7) 相同，对于解压过程有详细信息显示，如： </p>
<p>创建：META-INF/ </p>
<p>展开：META-INF/MANIFEST.MF </p>
<p>创建：test/ </p>
<p>展开：test/Test.class </p>
<p>9) jar uf test.jar manifest.mf </p>
<p>在 test.jar 中添加了文件 manifest.mf，此使用 jar tf 来查看 test.jar 可以发现 test.jar 中比原来多了一个 manifest。这里顺便提一下，如果使用 -m 参数并指定 manifest.mf 文件，那么 manifest.mf 是作为清单文件 MANIFEST 来使用的，它的内容会被添加到 MANIFEST 中；但是，如果作为一般文件添加到 JAR 文件包中，它跟一般文件无异。 </p>
<p>10) jar uvf test.jar manifest.mf </p>
<p>与 9) 结果相同，同时有详细信息显示，如： </p>
<p>增加：manifest.mf(读入= 17) (写出= 19)(压缩了 -11%) </p>
<p>4. 关于 JAR 文件包的一些技巧 </p>
<p>1) 使用 unzip 来解压 JAR 文件 </p>
<p>在介绍 JAR 文件的时候就已经说过了，JAR 文件实际上就是 ZIP 文件，所以可以使用常见的一些解压 ZIP 文件的工具来解压 JAR 文件，如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等来解压是因为它们解压比较直观，方便。而使用 unzip，则是因为它解压时可以使用 -d 参数指定目标目录。 </p>
<p>在解压一个 JAR 文件的时候是不能使用 jar 的 -C 参数来指定解压的目标的，因为 -C 参数只在创建或者更新包的时候可用。那么需要将文件解压到某个指定目录下的时候就需要先将这具 JAR 文件拷贝到目标目录下，再进行解压，比较麻烦。如果使用 unzip，就不需要这么麻烦了，只需要指定一个 -d 参数即可。如： </p>
<p>unzip test.jar -d dest/ </p>
<p>2) 使用 WinZip 或者 WinRAR 等工具创建 JAR 文件 </p>
<p>上面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件，所以，只需要使用 WinZip、WinRAR 等工具创建所需要 ZIP 压缩包，再往这个 ZIP 压缩包中添加一个包含 MANIFEST 文件的 META-INF 目录即可。对于使用 jar 命令的 -m 参数指定清单文件的情况，只需要将这个 MANIFEST 按需要修改即可。 </p>
<p>3) 使用 jar 命令创建 ZIP 文件 </p>
<p>有些 Linux 下提供了 unzip 命令，但没有 zip 命令，所以需要可以对 ZIP 文件进行解压，即不能创建 ZIP 文件。如要创建一个 ZIP 文件，使用带 -M 参数的 jar 命令即可，因为 -M 参数表示制作 JAR 包的时候不添加 MANIFEST 清单，那么只需要在指定目标 JAR 文件的地方将 .jar 扩展名改为 .zip 扩展名，创建的就是一个不折不扣的 ZIP 文件了，如将上一节的第 3) 个例子略作改动： </p>
<p>jar cvfM test.zip test </p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/259888.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 22:00 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>细说Java之util类</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259887.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 13:57:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259887.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259887.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259887.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259887.html</trackback:ping><description><![CDATA[<p>细说Java之util类 <br />
&nbsp;<br />
&nbsp;&nbsp; <br />
关键字&nbsp;&nbsp;&nbsp;&nbsp; java util collection list map set hashmap 集合 链表 哈希 <br />
　　线性表，链表，哈希表是常用的数据结构，在进行Java开发时，JDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。本文试图通过简单的描述，向读者阐述各个类的作用以及如何正确使用这些类。 </p>
<p>Collection <br />
├List <br />
│├LinkedList <br />
│├ArrayList <br />
│└Vector <br />
│　└Stack <br />
└Set <br />
Map <br />
├Hashtable <br />
├HashMap <br />
└WeakHashMap </p>
<p>Collection接口 <br />
　　Collection是最基本的集合接口，一个Collection代表一组Object，即Collection的元素（Elements）。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类，Java SDK提供的类都是继承自Collection的&#8220;子接口&#8221;如List和Set。 <br />
　　所有实现Collection接口的类都必须提供两个标准的构造函数：无参数的构造函数用于创建一个空的Collection，有一个Collection参数的构造函数用于创建一个新的Collection，这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。 <br />
　　如何遍历Collection中的每一个元素？不论Collection的实际类型如何，它都支持一个iterator()的方法，该方法返回一个迭代子，使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下： <br />
　　　　Iterator it = collection.iterator(); // 获得一个迭代子 <br />
　　　　while(it.hasNext()) { <br />
　　　　　　Object obj = it.next(); // 得到下一个元素 <br />
　　　　} <br />
　　由Collection接口派生的两个接口是List和Set。 </p>
<p>List接口 <br />
　　List是有序的Collection，使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引（元素在List中的位置，类似于数组下标）来访问List中的元素，这类似于Java的数组。 <br />
和下面要提到的Set不同，List允许有相同的元素。 <br />
　　除了具有Collection接口必备的iterator()方法外，List还提供一个listIterator()方法，返回一个ListIterator接口，和标准的Iterator接口相比，ListIterator多了一些add()之类的方法，允许添加，删除，设定元素，还能向前或向后遍历。 <br />
　　实现List接口的常用类有LinkedList，ArrayList，Vector和Stack。 </p>
<p>LinkedList类 <br />
　　LinkedList实现了List接口，允许null元素。此外LinkedList提供额外的get，remove，insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈（stack），队列（queue）或双向队列（deque）。 <br />
　　注意LinkedList没有同步方法。如果多个线程同时访问一个List，则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List： <br />
　　　　List list = Collections.synchronizedList(new LinkedList(...)); </p>
<p>ArrayList类 <br />
　　ArrayList实现了可变大小的数组。它允许所有元素，包括null。ArrayList没有同步。 <br />
size，isEmpty，get，set方法运行时间为常数。但是add方法开销为分摊的常数，添加n个元素需要O(n)的时间。其他的方法运行时间为线性。 <br />
　　每个ArrayList实例都有一个容量（Capacity），即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加，但是增长算法并没有定义。当需要插入大量元素时，在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。 <br />
　　和LinkedList一样，ArrayList也是非同步的（unsynchronized）。 </p>
<p>Vector类 <br />
　　Vector非常类似ArrayList，但是Vector是同步的。由Vector创建的Iterator，虽然和ArrayList创建的Iterator是同一接口，但是，因为Vector是同步的，当一个Iterator被创建而且正在被使用，另一个线程改变了Vector的状态（例如，添加或删除了一些元素），这时调用Iterator的方法时将抛出ConcurrentModificationException，因此必须捕获该异常。 </p>
<p>Stack 类 <br />
　　Stack继承自Vector，实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法，还有peek方法得到栈顶的元素，empty方法测试堆栈是否为空，search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。 </p>
<p>Set接口 <br />
　　Set是一种不包含重复的元素的Collection，即任意的两个元素e1和e2都有e1.equals(e2)=false，Set最多有一个null元素。 <br />
　　很明显，Set的构造函数有一个约束条件，传入的Collection参数不能包含重复的元素。 <br />
　　请注意：必须小心操作可变对象（Mutable Object）。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。 </p>
<p>Map接口 <br />
　　请注意，Map没有继承Collection接口，Map提供key到value的映射。一个Map中不能包含相同的key，每个key只能映射一个value。Map接口提供3种集合的视图，Map的内容可以被当作一组key集合，一组value集合，或者一组key-value映射。 </p>
<p>Hashtable类　　Hashtable继承Map接口，实现一个key-value映射的哈希表。任何非空（non-null）的对象都可作为key或者value。 <br />
　　添加数据使用put(key, value)，取出数据使用get(key)，这两个基本操作的时间开销为常数。 <br />
Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor 0.75较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大，这会影响像get和put这样的操作。 <br />
使用Hashtable的简单示例如下，将1，2，3放到Hashtable中，他们的key分别是&#8221;one&#8221;，&#8221;two&#8221;，&#8221;three&#8221;： <br />
　　　　Hashtable numbers = new Hashtable(); <br />
　　　　numbers.put(&#8220;one&#8221;, new Integer(1)); <br />
　　　　numbers.put(&#8220;two&#8221;, new Integer(2)); <br />
　　　　numbers.put(&#8220;three&#8221;, new Integer(3)); <br />
　　要取出一个数，比如2，用相应的key： <br />
　　　　Integer n = (Integer)numbers.get(&#8220;two&#8221;); <br />
　　　　System.out.println(&#8220;two = &#8221; + n); <br />
　　由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置，因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object，如果你用自定义的类当作key的话，要相当小心，按照散列函数的定义，如果两个对象相同，即obj1.equals(obj2)=true，则它们的hashCode必须相同，但如果两个对象不同，则它们的hashCode不一定不同，如果两个不同对象的hashCode相同，这种现象称为冲突，冲突会导致操作哈希表的时间开销增大，所以尽量定义好的hashCode()方法，能加快哈希表的操作。 <br />
　　如果相同的对象有不同的hashCode，对哈希表的操作会出现意想不到的结果（期待的get方法返回null），要避免这种问题，只需要牢记一条：要同时复写equals方法和hashCode方法，而不要只写其中一个。 <br />
　　Hashtable是同步的。 </p>
<p>HashMap类 <br />
　　HashMap和Hashtable类似，不同之处在于HashMap是非同步的，并且允许null，即null value和null key。，但是将HashMap视为Collection时（values()方法可返回Collection），其迭代子操作时间开销和HashMap的容量成比例。因此，如果迭代操作的性能相当重要的话，不要将HashMap的初始化容量设得过高，或者load factor过低。 </p>
<p>WeakHashMap类 <br />
　　WeakHashMap是一种改进的HashMap，它对key实行&#8220;弱引用&#8221;，如果一个key不再被外部所引用，那么该key可以被GC回收。 </p>
<p>总结 <br />
　　如果涉及到堆栈，队列等操作，应该考虑用List，对于需要快速插入，删除元素，应该使用LinkedList，如果需要快速随机访问元素，应该使用ArrayList。 <br />
　　如果程序在单线程环境中，或者访问仅仅在一个线程中进行，考虑非同步的类，其效率较高，如果多个线程可能同时操作一个类，应该使用同步的类。 <br />
　　要特别注意对哈希表的操作，作为key的对象要正确复写equals和hashCode方法。 <br />
　　尽量返回接口而非实际的类型，如返回List而非ArrayList，这样如果以后需要将ArrayList换成LinkedList时，客户端代码不用改变。这就是针对抽象编程。 <br />
</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/259887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 21:57 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>wait,notify,sleep,join这几个方法很常用</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259884.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 13:49:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259884.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259884.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259884.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259884.html</trackback:ping><description><![CDATA[<p><br />
wait,notify,sleep,join这几个方法很常用,这里涉及到多线程和同步问题,这里稍微解释一下. </p>
<p>1.wait和notify<br />
这两个方法都是Object中的方法,放在一块是因为他们关系非常密切.<br />
wait就是等待这个对象的同步锁,不过调用这个方法必须先获得这个对象的同步锁,就这一点很多人就搞晕了.<br />
这里先解释一下这两个方法,然后给出一个小例子说明.</p>
<p>wait:等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则后收到一个IllegalMonitorStateException,这个是运行时异常.调用这个方法后,就放弃了这个同步锁了.如果不带参数的wait方法就只有等别人唤醒了,如果带一个参数的<br />
化就设置等待最长时间,过了这个时间即使没有人唤醒这个线程也不再等待了.</p>
<p>notify:唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),但是notifyAll可以唤醒所有等待的线程,注意唤醒的时在notify之前wait的线程,之后的没有效果.</p>
<p>这里举一个通俗的例子,两个人共有一个卫生间(每次只能一个人用),他们都要刷牙和方便,他们是这样约定的,轮流用,第一个人先刷牙,然后第二个人刷牙...</p>
<p>&nbsp;</p>
<p>class Syn<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TwoPeople.ONE.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TwoPeople.TWO.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
} </p>
<p><br />
class TwoPeople extends Thread<br />
{<br />
&nbsp;&nbsp;&nbsp; private int i=0;<br />
&nbsp;&nbsp;&nbsp; static Thread ONE=new TwoPeople(1);<br />
&nbsp;&nbsp;&nbsp; static Thread TWO=new TwoPeople(2);</p>
<p>&nbsp;&nbsp;&nbsp; static Object washroom=new Object();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private TwoPeople(int i){this.i=i;}<br />
&nbsp;&nbsp;&nbsp; public void run(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(washroom){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(i==1){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brush(); //1 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; washroom.wait(); //2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; release(); //6&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; washroom.notify(); //7<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brush(); //3<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; washroom.notify(); //4<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; washroom.wait(); //5<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; release(); //8<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(InterruptedException e){e.printStackTrace();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private void brush() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("People "+i+" is brushing !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //延迟两秒看效果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("People "+i+" has burshed !");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private void release(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("People "+i+" is releasing !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //延迟两秒看效果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("People "+i+" has released !");<br />
&nbsp;&nbsp;&nbsp; }<br />
}; </p>
<p>上面的代码很简短,而且表明了执行顺序,至于join和sleep还是下次再讨论吧.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
wait,notify,sleep,join和线程同步问题(续) <br />
昨天没有时间写完这篇,今天补上,前面只说明了wait和notify这两个方法,这里讨论一下sleep和join,说实在的这两个方法比wait和notify简单的多.<br />
http://blog.csdn.net/treeroot/archive/2004/11/10/175508.aspx</p>
<p>sleep:Thread的静态方法,当前线程休眠一段时间,时间到了再恢复可运行状态,时间到了不一定就执行吧,还得竞争CPU呢.</p>
<p>join:这个方法其实就是特殊的wait,wait方法一般都需要别人notify(当然也可以设置超时),但是join方法就不需要别人notify了,一直等到这个线程死亡(就相当于这个线程临时前告诉那些在等它的人:你们进来吧!)</p>
<p>本人不是很会举例子,还是两个人公用一个卫生间吧,这回不刷牙了,改洗澡吧,总不能两个人同时洗澡吧!就算可以,这里假设不可以吧.情况时这样的：A在洗澡,B要等。</p>
<p>第一种情况:<br />
B很聪明的,A洗澡可能要20分钟到1小时,我就先睡10分钟看看好了没有,没有好就再睡10分钟,最多多等10分钟而已吧.</p>
<p><br />
class Syn<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread a=new Bathing();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.start(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //B<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int time=0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(a.isAlive()){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(10000);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time+=10;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("B has waited "+time+" minutes");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("B can bath now!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>class Bathing extends Thread<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bathing();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void bathing() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("A is bathing !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //延迟20秒看效果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("A has bathed !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}; </p>
<p><br />
这里连同步都不需要,不过B可能需要多等一段时间,因为它可能刚好去敲门A还没有洗完,于是他又去睡,结果刚睡下A就洗完了.<br />
第二种情况:<br />
B变得更加聪明了，这样等我不是亏了，如果我10分钟敲一次门，我可能要多等10分钟，但是如果我每秒敲一次我也没法睡呀，于是想了一个高招，装了一个机关，当A出来的时候机关就会按响门铃，这样B就可以高枕无忧了。</p>
<p>class Syn<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread a=new Bathing();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.start(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //B<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int time=0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.join();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("B can bath now!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>class Bathing extends Thread<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bathing();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void bathing() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("A is bathing !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //延迟20秒看效果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("A has bathed !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
};</p>
<p>这样只要A一洗完，B就会被唤醒，这里A并没有去notify他，但是还是间接的通知了B，当然这里也可以用wati和notify实现，不过就显得不好了。</p>
<p>class Syn<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread a=new Bathing();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.start(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //B<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int time=0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(a){a.wait();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("B can bath now!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>class Bathing extends Thread<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(this){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bathing();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notify();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void bathing() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("A is bathing !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{Thread.sleep(20000);}catch(InterruptedException e){e.printStackTrace();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //延迟20秒看效果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("A has bathed !");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
};</p>
<p>对于一般的对象就要用wait和notify了，但是对于一个线程来说，join方法有时候更加方便。</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/259884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 21:49 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>int转换到String方法的选择</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259879.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 13:45:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259879.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259879.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259879.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259879.html</trackback:ping><description><![CDATA[<p>int转换到String方法的选择 <br />
我们经常遇到需要将你int转换到String的问题,下面给出四种转换方法,到底那一种方法最好呢.<br />
1. ""+i<br />
2.new Integer(i).toString();<br />
3.String.valueOf(i);<br />
4.Integer.toString(i);<br />
好像第1种方法比较多见,第2种比较少见吧.<br />
可读性的话:第1种最差,第3和4中很好,第二种次之.<br />
性能比较:第1种最差,测试循环执行一段转换时所用时间大概为 3:2:1:1.<br />
可见第1和第2中方法是不可取的,第4种方法最佳,第3种几乎就是直接调用4.<br />
所以无论如何都应该选择4,我就很纳闷很多人都喜欢用1,不但可读性差,而且性能差,主要是所要写的字符数最少吧.</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/259879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 21:45 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Equals探索</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259878.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 13:44:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259878.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259878.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259878.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259878.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259878.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Equals探索</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>第一节：eqauls 与 = =之异同</p>
<p>1）比较方式角度：</p>
<p>= =是面向过程的操作符；equals是面向对象的操作符</p>
<p>= =不属于任何类，equals则是任何类（在Java中）的一个方法；</p>
<p>我们可以1）Primitive1 (基本类型)= = Primitive2(基本类型)；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）Object Reference1(对象引用)= = Object Reference2(对象引用)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）Object Reference1 (对象引用) .equals(Object Reference2 (对象引用))</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这三种比较</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但却不能Primitive1 (基本类型).equals( Primitive2(基本类型))；</p>
<p>&nbsp;对于基本类型，没有面向对象中发送消息一说，自然也不会有</p>
<p>方法成员。</p>
<p>&nbsp;</p>
<p>2）比较目的角度:</p>
<p>1）&nbsp;&nbsp;&nbsp; 如果要比较两个基本类型是否相等，请用= =；</p>
<p>2）&nbsp;&nbsp;&nbsp; 如果要比较两个对象引用是否相等，请用= =；</p>
<p>3）&nbsp;&nbsp;&nbsp; 如果要比较两个对象（逻辑上）是否一致，请用equals；</p>
<p>&nbsp;</p>
<p>第二节：对两个对象（逻辑上）是否一致的阐释：</p>
<p>&nbsp;&nbsp; 有人会问:在C++中, 比较两个对象相等不是也可以用==吗？我知道您是指运算符重载，但是很遗憾，Java中不支持运算符重载（java中亦有重载过运算符，他们是&#8220;+&#8221;，&#8220;+=&#8221;，不过也仅此两个，而且是内置实现的）；所以，对象的是否相等的比较这份责任就交由&nbsp; equals()来实现 。&nbsp;&nbsp;&nbsp; </p>
<p>这个&#8220;逻辑上&#8221;其实就取决于人类的看法，实际开发中，就取决于用户的需求；</p>
<p>有人会有看法：&#8220;取决于人类的看法&#8221;太过宽泛和不严肃，如果某人要两件</p>
<p>风牛马不相及的事物也相等，equals是否也能作出这样的比较呢？我们说可以的</p>
<p>下面这个例子说明了这一点：</p>
<p>&nbsp;</p>
<p>class Horse {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String Type;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int Legs;</p>
<p>&nbsp; //相等的标准：腿的数目相等</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public boolean equals(Object o){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(this.Legs==((Cattle)o).Legs){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</p>
<p>}</p>
<p>public Horse(String Type,int legs){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Type=Type;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Legs=legs;</p>
<p>}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>}</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>class Cattle</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; String Type;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp; Legs;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; //相等的标准：腿的数目相等</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Cattle(String Type,int legs){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Type=Type;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Legs=legs;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public boolean equals(Object o){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(this.Legs==((Horse)o).Legs){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>} </p>
<p>&nbsp;</p>
<p>public class EqualsTest{</p>
<p>public static void main(String[] args) </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cattle c=new Cattle("I'm the Cattle",4);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Horse h=new Horse("I'm the Horse",4);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(c.equals(h)){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(c.Type);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(h.Type);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Cattle Equals Horse");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p>&nbsp;</p>
<p>输出结果："I'm the Cattle"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "I'm the Horse"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Cattle Equals Horse"</p>
<p>您瞧瞧：牛果真等于了马，为何相等？因为我们定义的相等标准是：腿的数目相等；您会说：&#8220;这太滑稽&#8221;，是滑稽，可这是人类的看法，计算机可没有滑稽的概念，当然也没有&#8220;不滑稽&#8221;的概念，我们定义了什么相等标准，他就踏踏实实的为我们实现了；</p>
<p>&nbsp;所以说：相等标准（即需求）一定要定好，否则，滑稽的事可就多了</p>
<p>第三节：equals()缘起：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; equals()是每个对象与生俱来的方法，因为所有类的最终基类就是Object(除去Object本身)；而equals()是Object的方法之一。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们不妨观察一下Object中equals()的source code:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public boolean equals(Object obj) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (this == obj);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意 &#8220;return (this == obj)&#8221;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this与obj都是对象引用，而不是对象本身。所以equals()的缺省实现就是比较</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对象引用是否一致；为何要如此实现呢？ 前面我们说过：对象是否相等，是由我们的需求决定的，世界上的类千奇百怪（当然，这些类都是我们根据模拟现实世界而创造的），虽然Object是他们共同的祖先，可他又怎能知道他的子孙类比较相等的标准呢？但是他明白，任何一个对象，自己总是等于自己的，何谓&#8220;自己总是等于自己&#8221;呢，又如何判断&#8220;自己总是等于自己&#8221;呢？一个对象在内存中只有一份，但他的引用却可以有无穷多个，&#8220;对象自己的引用1=对象自己的引用2&#8221;，不就能判断&#8220;自己总是等于自己&#8221;吗？所以缺省实现实现自然也就是</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;return (this == obj)&#8221;；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而到了我们自己编写的类，对象相等的标准由我们确立，于是就不可避免的要覆写</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 继承而来的public boolean equals(Object obj)；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果您有过编覆写过equals（）的经验（没有过也不要紧），请您思考一个问题：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;两个对象（逻辑上）是否一致&#8221;实际上是比较什么？没错，或许您已脱口而出：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就是对象的属性（即field，或称数据成员）的比较。方法是不可比较的哦。（这个问题是不是有些弱智呢？哈哈）</p>
<p>&nbsp;第四节：对一个推论的思考</p>
<p>推论如下：一言以蔽之：欲比较栈中数据是否相等，请用= =；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 欲比较堆中数据是否相等，请用equals； </p>
<p>因为（根）基本类型，（根）对象引用都在栈中； 而对象本身在堆中；</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这句话又对又不对，问题出在哪，就是&#8220;数据&#8221;二字，先看栈中，数据或为基本类型，或为对象引用，用==比较当然没错；但是堆中呢？对象不是堆中吗？不是应该用equals比较吗？可是，我们比较的是堆中&#8220;数据&#8221;，堆中有对象，对象由什么构成呢？可能是对象引用，可能是基本类型，或两者兼而有之。如果我们要比较他们，该用什么呢，用&#8221;equals()&#8221;?不对吧，只能是&#8221;= =&#8221;!所以正确的结论是：欲比较栈中数据是否相等，请用= =； 欲比较堆中数据是否相等，请用equals；</p>
<p>因为（根）基本类型，（根）对象引用都在栈中（所谓&#8220;根&#8221;，指未被任何其他对象所包含）； 而对象本身在堆中。</p>
<p>&nbsp;<br />
</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/259878.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 21:44 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259878.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最简单的时间格式类SimpleDateFormat</title><link>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259877.html</link><dc:creator>大鱼</dc:creator><author>大鱼</author><pubDate>Sun, 15 Mar 2009 13:42:00 GMT</pubDate><guid>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259877.html</guid><wfw:comment>http://www.blogjava.net/luluyanglu/comments/259877.html</wfw:comment><comments>http://www.blogjava.net/luluyanglu/archive/2009/03/15/259877.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/luluyanglu/comments/commentRss/259877.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/luluyanglu/services/trackbacks/259877.html</trackback:ping><description><![CDATA[<p>&nbsp;最简单的时间格式类</p>
<p>import java.lang.*;<br />
import java.text.*;<br />
import java.util.*;</p>
<p>public class timeformat{</p>
<p>&nbsp; public timeformat(){<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp; <br />
&nbsp; static public String getChineseFormatTime(){<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return sdf.format(new Date());&nbsp; <br />
&nbsp; }<br />
&nbsp; <br />
&nbsp; static public String getSimpleFormatTime(){<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm", Locale.US);<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return sdf.format(new Date());&nbsp; <br />
&nbsp; }<br />
}</p>
<img src ="http://www.blogjava.net/luluyanglu/aggbug/259877.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/luluyanglu/" target="_blank">大鱼</a> 2009-03-15 21:42 <a href="http://www.blogjava.net/luluyanglu/archive/2009/03/15/259877.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>