﻿<?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-谁动了我的代码-随笔分类-Java</title><link>http://www.blogjava.net/smcdl/category/25612.html</link><description>抽象即是空，空即是抽象。</description><language>zh-cn</language><lastBuildDate>Sun, 22 Nov 2009 10:47:07 GMT</lastBuildDate><pubDate>Sun, 22 Nov 2009 10:47:07 GMT</pubDate><ttl>60</ttl><item><title>Java偏向锁实现原理讲解(Biased Locking)</title><link>http://www.blogjava.net/smcdl/archive/2009/11/18/302787.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Wed, 18 Nov 2009 05:10:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2009/11/18/302787.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/302787.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2009/11/18/302787.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/302787.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/302787.html</trackback:ping><description><![CDATA[<h2><a target="_blank" href="http://www.blogjava.net/bitmap123/archive/2009/11/16/302571.html">引用：Java偏向锁实现原理讲解(Biased Locking)(版权归原作者所有)<br />
</a></h2>
<br />
<img src ="http://www.blogjava.net/smcdl/aggbug/302787.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2009-11-18 13:10 <a href="http://www.blogjava.net/smcdl/archive/2009/11/18/302787.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat乱码问题研究，附带AJAX乱码问题研究。</title><link>http://www.blogjava.net/smcdl/archive/2009/06/07/280415.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Sun, 07 Jun 2009 15:47:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2009/06/07/280415.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/280415.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2009/06/07/280415.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/280415.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/280415.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt;"><span style="font-size: 10pt;">
<span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;">
很奇怪测试了多个应用服务器，只有Tomcat出现了乱码问题。让我们来分析一下原因，测试环境是Tomcat5.5.27，字符集编码统一为<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>。<br />
<br />
<strong><span style="font-size: 12pt;">1.页面静态内容乱码（非动态生成内容乱码）</span></strong><br />
这一般是&lt;%@ page pageEncoding="<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>" %&gt;设置的问题，建议在每个页面上都加上pageEncoding设定，让应用服务器能正确把JSP文件按照设定的编码转换为Java文件，只要这个pageEncoding设置正确就可以避免静态内容的乱码。有人可能会说我没有设置也没有乱码，那是因为应用服务器还可以读取&lt;%@ page contentType="text/html; charset=<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>" %&gt;中的<strong>charset</strong>作为备选方案，虽然这是JSP规范中要求的，但是难保有的容器没有实现或实现有BUG，所以有时候在某个应用服务器下（如Tomcat）不设置pageEncoding也可以，但是同样的页面拿到别的应用服务器下就不能保证不出现乱码。<br />
<br />
<strong><span style="font-size: 12pt;">2.动态生成内容乱码</span></strong><br />
新下载的Tomcat没有经过任何特殊的设置，无论是GET和POST都出现乱码。首先设置HTTP Connector（server.xml中监听8080端口的那个Connector），加上URIEncoding="<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>"，消除了GET乱码，再在JSP页面中第一句加入&lt;% request.setCharacterEncoding("<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>"); %&gt;，消除了POST乱码。<br />
通过上面两个设置我们发现，<strong>URIEncoding</strong>控制的是GET字符集编码，<strong>Request</strong>的<strong>CharacterEncoding</strong>控制的是POST字符集编码。<br />
如果没有上面那句</span></span></span></span></span><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;">&lt;% request.setCharacterEncoding("<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>"); %&gt;，</span></span></span></span></span><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;">在页面起始加入&lt;%= request.getCharacterEncoding() %&gt;，在Tomcat下我们发现输出<strong>null</strong>，在其他服务器下却输出<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>。这就是为什么在Tomcat下应该正确设置<strong>Request</strong>的<strong>CharacterEncoding</strong>的原因。<br />
上面提到的&lt;%@ page contentType="text/html; charset=<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>" %&gt;，除了声明返回给客户端的流是text/html外，同时设置了<strong>Response</strong>的<strong>CharacterEncoding</strong>，即相当于执行了Response.setCharacterEncoding("<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>")这段代码。它保证了服务器端生成的动态内容到达客户端也不会乱码。<br />
但有一种情况下也不会出现乱码，就是如下例这种情况，前提是没有设置</span></span></span></span></span><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;"><strong>Request</strong>的<strong>CharacterEncoding</strong></span></span></span></span></span><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;">：<br />
</span></span></span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;"><span style="font-size: 12pt;"><span style="color: #008080;"><span style="font-size: 10pt;"><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;doPost(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse&nbsp;response)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;ServletException,&nbsp;IOException&nbsp;{<br />
</span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;response.getWriter().write(request.getParameter(</span><span style="color: #000000;">"xxxxx</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
</span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">}</span></span></span></span></span></div>
这种情况下提交过来的表单数据其实是ISO-8859-1的编码，而返回给客户端又没有<span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;">&lt;%@ page contentType="text/html; charset=<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>" %&gt;</span></span></span>的设置，所以还是ISO-8859-1的编码，但是为什么没有乱码呢？其实已经乱码了，如果在第2行下断点的话，会发现<span style="color: #008080;"><span style="font-size: 12pt;"><span style="color: #008080;"><span style="font-size: 10pt;"><span style="color: #000000;">request.getParameter(</span><span style="color: #000000;">"xxxxx</span><span style="color: #000000;">"</span><span style="color: #000000;">)</span></span></span></span></span>的返回值就是乱码。可以用一句Java代码来解释为什么客户端显示结果没有乱码，如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">System.out.println(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String(</span><span style="color: #000000;">"</span><span style="color: #000000;">你好，世界</span><span style="color: #000000;">"</span><span style="color: #000000;">.getBytes(</span><span style="color: #000000;">"</span><span style="color: #000000;">ISO-8859-1</span><span style="color: #000000;">"</span><span style="color: #000000;">),&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">ISO-8859-1</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
很奇怪这句代码，明明是中文，应该用GB2312或GBK之类的字符集编码来getBytes，却用了ISO-8859-1，事实证明，这种互逆操作对字符串本身没有任何影响，只要getBytes和new String的时候字符集编码是一致的就不会引起乱码。<br />
上面这句代码正好说明了数据从客户端POST到服务器端时是ISO-8859-1编码，然后从服务器端写回到客户端还是ISO-8859-1编码，所以就没有造成乱码，如果这里不是直接写回到客户端，而是forward到另一个JSP页面，而这个页面恰好使用了</span><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;">&lt;%@ page contentType="text/html; charset=<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>" %&gt;</span></span></span></span>来设置Response的CharacterEncoding，那么在页面中输出xxxxx还会产生乱码，同样用一句Java代码来解释，如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">System.out.println(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String(</span><span style="color: #000000;">"</span><span style="color: #000000;">你好，世界</span><span style="color: #000000;">"</span><span style="color: #000000;">.getBytes(</span><span style="color: #000000;">"</span><span style="color: #000000;">ISO-8859-1</span><span style="color: #000000;">"</span><span style="color: #000000;">),&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">UTF-8</span><span style="color: #000000;">"</span><span style="color: #000000;">));</span></div>
所以，最后结论是如果想POST到服务器端不乱码就要设置Request的CharacterEncoding，写回到客户端不乱码就要设置Response的CharacterEncoding，若是JSP页面要设置&lt;%@ page contentType="text/html; charset=<span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;"><strong><em><span style="color: #ff0000;">UTF-8</span></em></strong></span></span></span></span>" %&gt;。<br />
<span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;">
<br />
<strong><span style="font-size: 12pt;"><strong>3.AJAX乱码问题</strong></span></strong>（不借助任何JS框架，像Prototype之类的框架会对GET请求的queryString自动应用encodeURIComponent()编码）<br />
GET请求时，需要对queryString使用encodeURIComponent()编码之后再提交到服务器。这是XMLHttpRequest规范所要求的。<br />
POST请求时，不需要使用encodeURIComponent()。<br />
通过对应用程序下断点发现，GET请求和POST请求的数据发送到服务器端都是正常的没有乱码，但是服务器端生成的动态内容写回客户端却是乱码，说明<strong>Response</strong>的<strong>CharacterEncoding</strong>设置错误，反过来我们再想一下，我们根本就没有设置过<strong>Response</strong>的<strong>CharacterEncoding</strong>，为什么呢？因为我们是以AJAX的方式提交表单，返回后不像JSP页面那样有&lt;%@ page contentType="text/html; charset=<strong><em><span style="color: #ff0000;">UTF-8</span></em></strong>" %&gt;来设置<strong>Response</strong>的<strong>CharacterEncoding</strong>，所以就会出错。<br />
<br />
综合上述，解决的办法就是各大网站提出的通用解决方案<strong>Filter</strong>，如果你的应用没有用到AJAX，只设置<strong>Request</strong>的<strong>CharacterEncoding</strong>即可，否则<strong>Response</strong>的<strong>CharacterEncoding</strong>也要设置。下面是一个Filter的示例，只引用doFilter方法来说明问题：</span></span></span><br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;"><span style="font-size: 12pt;"><span style="color: #008080;"><span style="font-size: 10pt;"><span style="color: #008080;">1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;doFilter(ServletRequest&nbsp;request,&nbsp;ServletResponse&nbsp;response,&nbsp;FilterChain&nbsp;chain)&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException,&nbsp;ServletException&nbsp;{<br />
</span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;request.setCharacterEncoding(</span><span style="color: #000000;">"</span><span style="color: #000000;">UTF-8</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;response.setCharacterEncoding(</span><span style="color: #000000;">"</span><span style="color: #000000;">UTF-8</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;chain.doFilter(request,&nbsp;response);<br />
</span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">}</span></span></span></span></span></div>
<br />
<br />
</span></span>
<img src ="http://www.blogjava.net/smcdl/aggbug/280415.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2009-06-07 23:47 <a href="http://www.blogjava.net/smcdl/archive/2009/06/07/280415.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jad和Java Decompiler的小小不同</title><link>http://www.blogjava.net/smcdl/archive/2009/03/10/258754.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Tue, 10 Mar 2009 03:25:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2009/03/10/258754.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/258754.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2009/03/10/258754.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/258754.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/258754.html</trackback:ping><description><![CDATA[今天用Java Decompiler反编译一个类发现其中字符串连加的代码反编译的结果和jad的不同。<br />
源码一般somestr = "a" + "b" + "c" + "d" ....;<br />
<br />
jad反编译过来会自动生成一个StringBuffer，然后把各个子串append到一起。如：<br />
somestr = (new StringBuilder(String.valueOf("a"))).append("b").append("c").append("d")....).toString();<br />
<br />
Java Decompiler反编译的代码基本上和原来一样，有字节码查看工具看出，编译器确实对字符串相加做了优化。请在eclipse使用byte outline插件查看。但是有一种情况是例外的，如：<br />
somestr = "a" + "b";<br />
somestr += "c" + "d";<br />
编译器会为每一条语句建立一个StringBuilder，像上面的情况请把两句合并成一句。<br />
<img src ="http://www.blogjava.net/smcdl/aggbug/258754.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2009-03-10 11:25 <a href="http://www.blogjava.net/smcdl/archive/2009/03/10/258754.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4J基本使用教程</title><link>http://www.blogjava.net/smcdl/archive/2009/02/17/254922.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Tue, 17 Feb 2009 03:43:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2009/02/17/254922.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/254922.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2009/02/17/254922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/254922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/254922.html</trackback:ping><description><![CDATA[在Log4J中存在几个概念首先介绍一下，最最重要的两个是Logger和Appender（请参考Log4J手册），其实是继承层次以及输出控制。<br />
<br />
首先Log4J中总是存在一个rootLogger，即使没有显示配置也是存在的，并且默认输出级别为DEBUG。<br />
其它的logger都继承自这个rootLogger（如果其他logger未单独定义其输出级别）。<br />
Log4J中的层次是用'.'来分隔的，如log4j.logger.com.example.test，这里并不是说log4j.logger后面一定是具体的包名乃至类名，<br />
这个名称可以自定义，我们甚至可以定义一个log4j.logger.A.B.C， 在com.example.test中的类里取名称为A.B的logger,如<br />
Logger logger = Logger.getLogger("A.B")<br />
上例中我们建立了3个logger实例，它们分别是"A"、"A.B"、"A.B.C"。每次我们在系统中取得logger时，并不是新建实例，这些实例是<br />
系统启动的时候就按照配置文件初始化好的（也可能时第一次引用的时候建立的，然后缓存其实例供以后使用，这部分还没有时间研究）。<br />
<br />
<strong>限制appender叠加性</strong><br />
例1：<br />
log4j.rootLogger=DEBUG, Console<br />
log4j.logger.A=DEBUG, Console<br />
log4j.logger.A.B=INFO, Console<br />
对于logger A.B输出的任何日志会往控制台输出三次，原因是A.B继承A的以及A的父logger的所有appender，<br />
这种继承关系仅仅是把父logger的appender添加到自己的appender列表中，父logger的输出level不会影响<br />
子logger的输出。<br />
<br />
例2：限制appender叠加<br />
log4j.rootLogger=DEBUG, Console<br />
log4j.logger.A=DEBUG, Console<br />
log4j.logger.A.B=INFO, Console<br />
log4j.additivity.A.B=false<br />
logger A.B的日志仅会输出到自己Console中，不会继承任何父logger的appender。<br />
<br />
<strong>控制appender的输出级别</strong><br />
若想对输出到appender中的日志级别进行限制的话，就需要用到threshold来控制。<br />
log4j.threshold=ERROR 用来控制所有的appender，即输出到所有appender的日志，<br />
不管原来是什么级别的，都不能低于threshold所规定的级别。<br />
<br />
log4j.appender.Console.threshold=ERROR 用来控制指定的appender的输出级别。<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/smcdl/aggbug/254922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2009-02-17 11:43 <a href="http://www.blogjava.net/smcdl/archive/2009/02/17/254922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java范型需要注意的地方</title><link>http://www.blogjava.net/smcdl/archive/2008/10/23/236140.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Thu, 23 Oct 2008 05:59:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/10/23/236140.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/236140.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/10/23/236140.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/236140.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/236140.html</trackback:ping><description><![CDATA[<ol>
    <li>静态方法要想范化，需要指定其类型参数</li>
    <li>非范化类型中的实例方法要想范化，也需要制定其类型参数。</li>
    <li>范化类型中的实力方法可以直接使用其类型本身的类型参数。</li>
    <li>范型不是协变的，即List&lt;Integer&gt;不是List&lt;Number&gt;的子类。</li>
    <li>不能实例化范型类型的数组，即<code>new List&lt;String&gt;[3]</code> 是不合法的，除非类型参数是一个未绑定的通配符，即<code>new List&lt;?&gt;[3]</code> 是合法的。<br />
    </li>
    <li>构造延迟，在代码编写时我们不能通过类型参数来构造一个该类型的实例，原因是我们不知道如何构造，类型参数的实际类型是在运行时确定的。</li>
    <li>对于注意5所描述的问题我们有一个解决方法是List&lt;String&gt; list = (List&lt;String&gt;[]) new Object[3];但是如果是运行时建立数组呢，类型信息是运行时确定的，那就换种写法T[] tarray = (T[]) new Object[3];</li>
    <li>上面的数组构造是不被推荐的，最好的方法是将类型信息传递到方法中，如method(Class&lt;V&gt; type) { V[] array = (V[])Array.newInstance(type, length); }，可以参考ArrayList类的toArray(T[] a)方法的实现。<br />
    </li>
    <li>构造通配符引用，如果set是一个Set&lt;?&gt;类型，则Set&lt;?&gt; set2 = new HashSet&lt;?&gt;(set);是不合法的，改成Set&lt;?&gt; set2 = new HashSet&lt;Object&gt;(set);就合法了。</li>
</ol>
最后，推荐三篇IBM上的文章<br />
<h1><a title="多角度看 Java 中的泛型" href="http://www.ibm.com/developerworks/cn/java/j-lo-gj/">多角度看 Java 中的泛型</a></h1>
<h1><a title="了解泛型" href="http://www.ibm.com/developerworks/cn/java/j-jtp01255.html">了解泛型</a></h1>
<h1><a title="使用通配符简化泛型使用" href="http://www.ibm.com/developerworks/cn/java/j-jtp04298.html">使用通配符简化泛型使用</a></h1>
<img src ="http://www.blogjava.net/smcdl/aggbug/236140.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-10-23 13:59 <a href="http://www.blogjava.net/smcdl/archive/2008/10/23/236140.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java事件传递技术 （链接至IBM网站）</title><link>http://www.blogjava.net/smcdl/archive/2008/10/22/235955.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Wed, 22 Oct 2008 08:01:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/10/22/235955.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/235955.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/10/22/235955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/235955.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/235955.html</trackback:ping><description><![CDATA[IBM开发者乐园上的教程（需注册才能浏览，建议注册一个帐号，IBM网站上有很多好文章），很详细的介绍了3种粒度模型（对象、属性、事件）。<br />
<strong><a title="Java事件传递技术" href="http://www.ibm.com/developerworks/cn/views/java/tutorials.jsp?cv_doc_id=84975">Java事件传递技术</a></strong><br />
<br />
<img src ="http://www.blogjava.net/smcdl/aggbug/235955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-10-22 16:01 <a href="http://www.blogjava.net/smcdl/archive/2008/10/22/235955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java集合框架使用注意事项（二，Map）</title><link>http://www.blogjava.net/smcdl/archive/2008/10/22/235916.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Wed, 22 Oct 2008 04:59:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/10/22/235916.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/235916.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/10/22/235916.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/235916.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/235916.html</trackback:ping><description><![CDATA[Map接口常用的实现类有：<br />
1.HashMap<br />
2.Hashtable<br />
3.TreeMap<br />
4.LinkedHashMap<br />
<br />
讨论1：底层机制<br />
HashMap与Hashtable基于数组实现，TreeMap基于树型结构，底层存储结构是典型的链表结构。LinkedHashMap继承自HashMap，所以也是基于数组实现的。<br />
<br />
讨论2：继承关系<br />
HashMap与TreeMap继承自AbstractMap，Hashtable继承自Dictionary，LinkedHashMap继承自HashMap。<br />
<br />
讨论3：同步关系<br />
Hashtable是同步的，而HashMap与TreeMap以及LinkedHashMap不是同步的，可以使用Collections中提供的方法转换为同步的。<br />
<br />
讨论4：迭代器<br />
迭代器都是快速失败的（注：参考本系列第一篇List篇）<br />
<br />
讨论5：不可修改<br />
通过使用Collections.unmodifiableMap(Map map)来转换
<img src ="http://www.blogjava.net/smcdl/aggbug/235916.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-10-22 12:59 <a href="http://www.blogjava.net/smcdl/archive/2008/10/22/235916.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java集合框架使用注意事项（一， List）</title><link>http://www.blogjava.net/smcdl/archive/2008/10/22/235890.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Wed, 22 Oct 2008 03:22:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/10/22/235890.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/235890.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/10/22/235890.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/235890.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/235890.html</trackback:ping><description><![CDATA[List的有用实现<br />
1.ArrayList<br />
2.LinkedList<br />
3.Vector<br />
4.Stack<br />
<br />
讨论1：底层机制（牵扯到的数据结构的知识请读者自行复习）<br />
ArrayList与Vector都是基于数组实现的，这就说明ArrayList与Vector适合做遍历而不适合做频繁的插入和删除。<br />
LinkedList是基于链表实现的，所以它生来就是为了频繁插入与删除对象。<br />
<br />
讨论2：特殊功能<br />
Stack是一个后进先出（LIFO）对象堆栈，而LinkedList除可以被用作堆栈外，还可以被用作队列或双端队列。<br />
不同的是Stack继承自Vector，也就是说它也是基于数组实现的。<br />
<br />
讨论3：内存占用<br />
基于数组实现的List，在动态扩展时会产生新的数组，然后把旧数组里的内容复制到新数组里，<br />
这会产生大量的不再被使用的对象引用变量等待系统回收。而基于链表实现的List就不会有这种问题。<br />
<br />
讨论4：同步问题<br />
Vector与Stack生来就是同步的，
而ArrayList与LinkedList需要使用Collections.synchronizedList(List list)方法来转换成同步List。<br />
从它们的对象上返回的迭代器是快速失败的，也就是说在使用迭代器进行迭代的时候，必须使用迭代器本身的remove、add、set<br />
方法来添加或更改List元素，如果在迭代的同时，在其他线程中<strong><span style="color: #ff0000;">从结构上修改</span></strong>了List（结构上的修改是指任何添加或删除一个或多个元素的操作，或者显式调整底层数组的大小；仅仅设置元素的值不是结构上的修改），快速失败迭代器会尽最大努力抛出ConcurrentModificationException。<br />
<br />
讨论5：使用策略<br />
如果数据被从数据源提取，数据量不确定，该数据一经被提取后就几乎不会再添加或删除，那么应该建立一个LinkedList来保存从数据源中取出的数据，然后将该LinkedList转换成ArrayList来优化遍历操作。反过来，数据量确定的数据从数据源取出可以先建立一个ArrayList来保存，根据需要如需频繁增删，就转换为LinkedList，如频繁遍历就不需转换。<br />
转换的方法就是使用对应的List类来封装目标List对象。如<br />
ArrayList al = new ArrayList();<br />
LinkedList ll = new LinkedList(al);<br />
同理反过来也可以<br />
LinkedList ll = new LinkedList();<br />
ArrayList al = new ArrayList(ll);<br />
<br />
讨论6:toArray()方法<br />
基于数组实现的List会直接返回一个底层数组的拷贝(使用了System.arraycopy方法)，基于链表实现的List会新生成一个数组。<br />
<br />
讨论7：不可修改<br />
通过使用Collections.unmodifiableList(List list)来生成一个不可修改的List，试图修改返回的列表，不管是直接修改还是通过其迭代器进行修改，都将导致抛出UnsupportedOperationException。<br />
<br />
讨论8：遍历器<br />
请尽量使用Iterator，Enumeration已不被鼓励使用。<br />
<br />
最后，请参考java.util.Collections类，该类提供了很多有用的操纵集合对象的方法。<br />
<dl><dd><br />
</dd></dl><br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/smcdl/aggbug/235890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-10-22 11:22 <a href="http://www.blogjava.net/smcdl/archive/2008/10/22/235890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat对Servlet及JSP规范支持的情况</title><link>http://www.blogjava.net/smcdl/archive/2008/05/15/200693.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Thu, 15 May 2008 10:01:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/05/15/200693.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/200693.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/05/15/200693.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/200693.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/200693.html</trackback:ping><description><![CDATA[<p><span style="font-size: 14pt"><strong><a title="请参考Tomcat官方网站" href="http://tomcat.apache.org/"><span style="font-size: 14pt"><strong></strong></span>&nbsp;</a><a title="请参考Tomcat官方网站" href="http://tomcat.apache.org/">请参考Tomcat官方网站</a></strong></span></p>
<img src ="http://www.blogjava.net/smcdl/aggbug/200693.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-05-15 18:01 <a href="http://www.blogjava.net/smcdl/archive/2008/05/15/200693.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 5.0的新特性</title><link>http://www.blogjava.net/smcdl/archive/2008/05/15/200565.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Thu, 15 May 2008 01:36:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/05/15/200565.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/200565.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/05/15/200565.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/200565.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/200565.html</trackback:ping><description><![CDATA[<p><a title="Dev2Dev中文版" href="http://dev2dev.bea.com.cn/techdoc/20060105718.html" target="_blank">Dev2Dev中文版</a><br />
<br />
</p>
<a title="官方英文版" href="http://java.sun.com/j2se/1.5.0/docs/guide/language/" target="_blank">官方英文版</a>
  <img src ="http://www.blogjava.net/smcdl/aggbug/200565.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-05-15 09:36 <a href="http://www.blogjava.net/smcdl/archive/2008/05/15/200565.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java类载入的时机</title><link>http://www.blogjava.net/smcdl/archive/2008/05/14/200369.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Wed, 14 May 2008 03:28:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/05/14/200369.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/200369.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/05/14/200369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/200369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/200369.html</trackback:ping><description><![CDATA[1.类成员变量或类实例成员变量在该类被载入的时候被载入。<br />
例：<br />
private ClassA ca = new ClassA();<br />
static ClassB cb = new ClassB();<br />
<br />
这里的new是必须的，否则ClassA和ClassB不会被载入。<br />
<br />
2.类成员函数或类实例成员函数在反射方法（未调用方法前）时，<br />
如果该方法的返回类型不是void，则返回类型被载入。<br />
<br />
3.类成员函数或类实例成员函数在反射方法被调用或直接调用该方法时，<br />
方法中引用的其他类型被载入。
<img src ="http://www.blogjava.net/smcdl/aggbug/200369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-05-14 11:28 <a href="http://www.blogjava.net/smcdl/archive/2008/05/14/200369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java点滴（一）</title><link>http://www.blogjava.net/smcdl/archive/2008/05/13/200146.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Tue, 13 May 2008 02:39:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/05/13/200146.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/200146.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/05/13/200146.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/200146.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/200146.html</trackback:ping><description><![CDATA[<p>1.建立数组</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span>&nbsp;<span style="color: #0000ff">int</span><span style="color: #000000">[]&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">2</span><span style="color: #000000">,</span><span style="color: #000000">3</span><span style="color: #000000">};<br />
</span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">String[]&nbsp;s&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;{</span><span style="color: #000000">"</span><span style="color: #000000">a</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">b</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">c</span><span style="color: #000000">"</span><span style="color: #000000">};</span></div>
上面的语句确实可以建立数组。看似{1,2,3}可以<span style="color: red"><strong>独立代表</strong></span>一个数组对象，其实是不可以的，这和String类型的字面值不同，一个String类型的字面值就是一个String类的实例，而一个数组的字面值什么都不是。<br />
<br />
2.静态方法或变量的覆盖<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">&nbsp;1</span>&nbsp;<span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Main&nbsp;{<br />
</span><span style="color: #008080">&nbsp;2</span>&nbsp;<span style="color: #000000"><br />
</span><span style="color: #008080">&nbsp;3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;<br />
</span><span style="color: #008080">&nbsp;4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/**</span><span style="color: #008000"><br />
</span><span style="color: #008080">&nbsp;5</span>&nbsp;<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080">@param</span><span style="color: #008000">&nbsp;args&nbsp;the&nbsp;command&nbsp;line&nbsp;arguments<br />
</span><span style="color: #008080">&nbsp;6</span>&nbsp;<span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br />
</span><span style="color: #008080">&nbsp;7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
</span><span style="color: #008080">&nbsp;8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(TTT.i);<br />
</span><span style="color: #008080">&nbsp;9</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Main.i);<br />
</span><span style="color: #008080">10</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Main&nbsp;m&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Main();<br />
</span><span style="color: #008080">11</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(m.i);<br />
</span><span style="color: #008080">12</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TTT&nbsp;t&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TTT();<br />
</span><span style="color: #008080">13</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(t.i);<br />
</span><span style="color: #008080">14</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Main&nbsp;m2&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;TTT();<br />
</span><span style="color: #008080">15</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(m2.i);<br />
</span><span style="color: #008080">16</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(((TTT)m2).i);<br />
</span><span style="color: #008080">17</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">18</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Main.Test();<br />
</span><span style="color: #008080">19</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TTT.Test();<br />
</span><span style="color: #008080">20</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.Test();<br />
</span><span style="color: #008080">21</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.Test();<br />
</span><span style="color: #008080">22</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m2.Test();<br />
</span><span style="color: #008080">23</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((TTT)m2).Test();<br />
</span><span style="color: #008080">24</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080">25</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">26</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Test()&nbsp;{<br />
</span><span style="color: #008080">27</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Hello&nbsp;Test&nbsp;From&nbsp;Main.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">28</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080">29</span>&nbsp;<span style="color: #000000"><br />
</span><span style="color: #008080">30</span>&nbsp;<span style="color: #000000">}<br />
</span><span style="color: #008080">31</span>&nbsp;<span style="color: #000000"><br />
</span><span style="color: #008080">32</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;TTT&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;Main&nbsp;{<br />
</span><span style="color: #008080">33</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">34</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">20</span><span style="color: #000000">;<br />
</span><span style="color: #008080">35</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080">36</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Test()&nbsp;{<br />
</span><span style="color: #008080">37</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000">"</span><span style="color: #000000">Hello&nbsp;Test&nbsp;From&nbsp;TTT.</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">38</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080">39</span>&nbsp;<span style="color: #000000">}</span></div>
<br />
3.一个接口可以继承多个接口（使用extends关键字）<br />
<br />
4.如果一个类中定义了final常量，并且在多个类中被引用，当该常量被修改时（<strong style="color: red">代码级修改</strong>），其他引用该常量的类都要被重新编译，<br />
否则，新值是不会被代入引用该常量的类中。原因是常量在编译期被硬编码到引用它的类中，可以通过反编译工具来验证。<br />
<br />
5.一个方法的返回类型必须直接写在方面名称的前面 <br />
<br />
6.与类名相同的方法名（非构造函数）是被允许的（JDK1.4测试通过，也许1.4之前的版本不能通过）<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span>&nbsp;<span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Test&nbsp;{<br />
</span><span style="color: #008080">2</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Test()&nbsp;{<br />
</span><span style="color: #008080">3</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
</span><span style="color: #008080">4</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080">5</span>&nbsp;<span style="color: #000000"><br />
</span><span style="color: #008080">6</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Test()&nbsp;{<br />
</span><span style="color: #008080">7</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
</span><span style="color: #008080">8</span>&nbsp;<span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080">9</span>&nbsp;<span style="color: #000000">}</span></div>
<img src ="http://www.blogjava.net/smcdl/aggbug/200146.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-05-13 10:39 <a href="http://www.blogjava.net/smcdl/archive/2008/05/13/200146.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4j自带Log Viewer的用法</title><link>http://www.blogjava.net/smcdl/archive/2008/03/19/187199.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Wed, 19 Mar 2008 03:36:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/03/19/187199.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/187199.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/03/19/187199.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/187199.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/187199.html</trackback:ping><description><![CDATA[这两天在研究Log4j的一些用法，无意中发现Log4j提供了一个Log Viewer，名字叫做ChainSaw。<br />
这个工具在Log4j的jar包中，这个工具可以分析xml格式的log文件，同时这个工具可以监听当前<br />
项目发送过来的log。<br />
用法很简单&nbsp; java -cp ./log4j-1.2.15.jar org.apache.log4j.chainsaw.Main，执行该命令后就会出现<br />
ChainSaw的Swing窗口了。<br />
要想监听当前项目发送过来的Log，需要配置项目里的log4j.properties文件，加入下面一段：<br />
log4j.appender.CHAINSAW_CLIENT=org.apache.log4j.net.SocketAppender<br />
log4j.appender.CHAINSAW_CLIENT.RemoteHost=localhost<br />
log4j.appender.CHAINSAW_CLIENT.Port=4445<br />
log4j.appender.CHAINSAW_CLIENT.LocationInfo=true<br />
在rootLogger中加入CHAINSAW_CLIENT的appender，如：log4j.rootLogger=INFO,CHAINSAW_CLIENT<br />
<br />
改工具可以设置多个过滤条件，如级别、线程、Logger、消息等。<br />
更多使用方法可以自己摸索一下，很简单哦。
<img src ="http://www.blogjava.net/smcdl/aggbug/187199.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-03-19 11:36 <a href="http://www.blogjava.net/smcdl/archive/2008/03/19/187199.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4j输出日志消息时，不必再检测当前输出Level是否Enabled。</title><link>http://www.blogjava.net/smcdl/archive/2008/03/18/186995.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Tue, 18 Mar 2008 06:17:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2008/03/18/186995.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/186995.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2008/03/18/186995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/186995.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/186995.html</trackback:ping><description><![CDATA[今天为了解决一个项目问题，跟踪到Log4j的源码里，发现我们以前都写过下面的程序吧：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #008080;">1</span><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />if (<span style="color: #000000;">log.isDebugEnabled())<br />
</span><span style="color: #008080;">2</span><span style="color: #000000;"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;log.debug(</span><span style="color: #000000;">"</span><span style="color: #000000;">Erro&nbsp;Message</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
其实再确认是否Enabled，因为debug、info等方法里面有同样的验证。<br />
所以以后少一段这样的验证也许会提高一些性能。<br />
我测试的Log4j的版本是1.2.9<br />
<br />
补充：有些情况下对于这个判断还是很必要的，如log的信息是调用不同的方法的结果组合而成的，并且这些方法执行起来比较费时，这个时候就需要先判断一下。<br />
<img src ="http://www.blogjava.net/smcdl/aggbug/186995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2008-03-18 14:17 <a href="http://www.blogjava.net/smcdl/archive/2008/03/18/186995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于对可以从Request中取出的路径信息的研究</title><link>http://www.blogjava.net/smcdl/archive/2007/10/19/154187.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Fri, 19 Oct 2007 05:35:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2007/10/19/154187.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/154187.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2007/10/19/154187.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/154187.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/154187.html</trackback:ping><description><![CDATA[Servlet的Request中和用户请求路径相关的操作有多个，下面一一列举：<br />
1.getQueryString()，&amp;之后GET方法的参数部分。<br />
2.getServletPath()，web.xml中定义的Servlet访问路径。<br />
3.getPathInfo()，Servlet访问路径之后，QueryString之前的中间部分。<br />
4.getContextPath()，Context路径前缀（这个应该是最熟悉的啦）。<br />
5.getRequestURI()，等于getContextPath() + getServletPath() + getPathInfo()。<br />
6.getRequestURL()，等于getScheme() + "://" + getServerName() + ":" + getServerPort() + getRequestURI()。<br />
7.getPathTranslated()，等于getServletContext().getRealPath("/") + getPathInfo()。<br />
<br />
注意：<br />
1.getServletContext().getRealPath("/") 后包含当前系统的文件夹分隔符（windows系统是"\"，linux系统是"/"），而getPathInfo()以"/"开头。 <br />
2.getPathInfo()与getPathTranslated()在servlet的url-pattern被设置为/*或/aa/*之类的pattern时才有值，其他时候都返回null。<br />
3.在servlet的url-pattern被设置为*.xx之类的pattern时，getServletPath()返回的是getRequestURI()去掉前面ContextPath的剩余部分。
<img src ="http://www.blogjava.net/smcdl/aggbug/154187.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2007-10-19 13:35 <a href="http://www.blogjava.net/smcdl/archive/2007/10/19/154187.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Java的Cookie操作</title><link>http://www.blogjava.net/smcdl/archive/2007/09/05/142945.html</link><dc:creator>teddy</dc:creator><author>teddy</author><pubDate>Wed, 05 Sep 2007 09:05:00 GMT</pubDate><guid>http://www.blogjava.net/smcdl/archive/2007/09/05/142945.html</guid><wfw:comment>http://www.blogjava.net/smcdl/comments/142945.html</wfw:comment><comments>http://www.blogjava.net/smcdl/archive/2007/09/05/142945.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smcdl/comments/commentRss/142945.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smcdl/services/trackbacks/142945.html</trackback:ping><description><![CDATA[<p>测试环境：JDK1.5、Tomcat5.5<br />
<br />
1.设置Cookie<br />
</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">Cookie&nbsp;cookie&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Cookie(</span><span style="color: #000000">"</span><span style="color: #000000">key</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">value</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />cookie.setMaxAge(</span><span style="color: #000000">60</span><span style="color: #000000">);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">设置60秒生存期，如果设置为负值的话，则为浏览器进程Cookie（内存中保存），关闭浏览器就失效。</span><span style="color: #008000"><br />
</span><span style="color: #008080">3</span><span style="color: #008000"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">cookie.setPath(</span><span style="color: #000000">"</span><span style="color: #000000">/test/test2</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">设置Cookie路径，不设置的话为当前路径（对于Servlet来说为request.getContextPath()&nbsp;+&nbsp;web.xml里配置的该Servlet的url-pattern路径部分）</span><span style="color: #008000"><br />
</span><span style="color: #008080">4</span><span style="color: #008000"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">response.addCookie(cookie);</span></div>
<br />
2.读取Cookie<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">1</span><span style="color: #008000">//</span><span style="color: #008000">该方法可以读取当前路径以及&#8220;直接父路径&#8221;的所有Cookie对象，如果没有任何Cookie的话，则返回null</span><span style="color: #008000"><br />
</span><span style="color: #008080">2</span><span style="color: #008000"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">2Cookie[]&nbsp;cookies&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;request.getCookies();</span></div>
<br />
3.删除Cookie<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #008080">1</span><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">Cookie&nbsp;cookie&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Cookie(</span><span style="color: #000000">"</span><span style="color: #000000">key</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">);<br />
</span><span style="color: #008080">2</span><span style="color: #000000"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />cookie.setMaxAge(</span><span style="color: #000000">0</span><span style="color: #000000">);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">设置为0为立即删除该Cookie</span><span style="color: #008000"><br />
</span><span style="color: #008080">3</span><span style="color: #008000"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">cookie.setPath(</span><span style="color: #000000">"</span><span style="color: #000000">/test/test2</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">删除指定路径上的Cookie，不设置该路径，默认为删除当前路径Cookie</span><span style="color: #008000"><br />
</span><span style="color: #008080">4</span><span style="color: #008000"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">response.addCookie(cookie);</span></div>
<p><br />
<br />
4.注意：假设路径结构如下<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/test<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/test/test2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/test345<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /test555/test666<br />
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;a.相同键名的Cookie（值可以相同或不同）可以存在于不同的路径下。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; b.&nbsp;删除时，如果当前路径下没有键为"key"的Cookie，则查询全部父路径，检索到就执行删除操作（每次只能删除一个与自己最近的父路径Cookie）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FF.必须指定与设定cookie时使用的相同路径来删除改cookie，而且cookie的键名不论大写、小写或大小混合都要指定路径。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IE.键名小写时，如果当前路径为/test/test2，如果找不到再向上查询/test、/test555、/test345，如果还找不到就查询/&nbsp;。（/test555/test666不查询）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 键名大小写混合或大写时，不指定路径则默认删除当前路径，并且不向上查询。<br />
<br />
&nbsp;&nbsp;&nbsp; c.读取Cookie时只能读取直接父路径的Cookie。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果当前路径为/test/test2，要读取的键为"key"。当前路径读取后，还要读取/test，/test读取后，还要读取/<br />
<br />
&nbsp;&nbsp;&nbsp; d.在做Java的web项目时，由于一般的Web服务器（如Tomcat或Jetty）都用Context来管理不同的Web Application，这样对于每个Context有不同的Path，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在一个Server中有多个Web Application时要特别小心，不要设置Path为/的Cookie，容易误操作。（当然前提是域名相同）<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.最好也不要在不同路径下使用相同键名的cookie，这样做很容易引起歧义。<br />
<br />
&nbsp;&nbsp;&nbsp; f.为了避免对FF和IE或其他浏览器区分操作，设置cookie时最好指定路径，删除cookie也要指定路径。<br />
</p>
 <img src ="http://www.blogjava.net/smcdl/aggbug/142945.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smcdl/" target="_blank">teddy</a> 2007-09-05 17:05 <a href="http://www.blogjava.net/smcdl/archive/2007/09/05/142945.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>