﻿<?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-上善若水-随笔分类-Core Java</title><link>http://blogjava.net/DLevin/category/48883.html</link><description>In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation.
To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra</description><language>zh-cn</language><lastBuildDate>Thu, 13 Aug 2015 10:48:20 GMT</lastBuildDate><pubDate>Thu, 13 Aug 2015 10:48:20 GMT</pubDate><ttl>60</ttl><item><title>分布式Map中实现引用计数</title><link>http://www.blogjava.net/DLevin/archive/2015/04/20/424554.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 20 Apr 2015 12:30:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2015/04/20/424554.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/424554.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2015/04/20/424554.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/424554.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/424554.html</trackback:ping><description><![CDATA[<h1>前言</h1>在《<a href="http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html">ReferenceCountSet无锁实现</a>》中，详细介绍了如何在一个进程中实现一个无锁版本的ReferenceCountSet（或者说是在自己的代码里没有锁），但是最近遇到一个问题，如果是在分布式的环境中呢？如何实现这个引用计数？这个问题如果从头开始写，会是一个比较复杂的问题，在实际中，我们可以使用ZooKeeper设置时的version机制来实现，即CAS（Compare-And-Set）。这是一个本人在实际项目中遇到的一个问题，但是会更简单一些，因为在我们的项目中，我们使用GemFire，即已经有一个现成的分布式Map了（在Gemfire中叫做Region），所以问题简化成如果如何使用一个分布式Map实现引用计数？<br /><br /><h1>实现</h1>如果对ConcurrentMap接口比较熟悉的话，这个其实是一个比较简单的问题。在ConcurrentMap中最主要的就是引入几个CAS相关的操作：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;ConcurrentMap&lt;K,&nbsp;V&gt;&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;Map&lt;K,&nbsp;V&gt;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;putIfAbsent(K&nbsp;key,&nbsp;V&nbsp;value);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;remove(Object&nbsp;key,&nbsp;Object&nbsp;value);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;replace(K&nbsp;key,&nbsp;V&nbsp;oldValue,&nbsp;V&nbsp;newValue);<br />&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;replace(K&nbsp;key,&nbsp;V&nbsp;value);<br />}</div>在《<a href="http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html">ReferenceCountSet无锁实现</a>》中我们只需要使用putIfAbsent就可以了，剩下的实现可以交给AtomicInteger提供的CAS来实现，因为它是在同一个进程中，但是如果在分布式的环境中就不能使用这个AtomicInteger，这个时候应该怎么办呢？其实这个时候我们就可以求助于replace方法了。replace方法的注释中这样描述：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Replaces&nbsp;the&nbsp;entry&nbsp;for&nbsp;a&nbsp;key&nbsp;only&nbsp;if&nbsp;currently&nbsp;mapped&nbsp;to&nbsp;a&nbsp;given&nbsp;value.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;This&nbsp;is&nbsp;equivalent&nbsp;to<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&lt;pre&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;if&nbsp;(map.containsKey(key)&nbsp;&amp;amp;&amp;amp;&nbsp;map.get(key).equals(oldValue))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;map.put(key,&nbsp;newValue);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;return&nbsp;false;&lt;/pre&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;except&nbsp;that&nbsp;the&nbsp;action&nbsp;is&nbsp;performed&nbsp;atomically.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;key&nbsp;key&nbsp;with&nbsp;which&nbsp;the&nbsp;specified&nbsp;value&nbsp;is&nbsp;associated<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;oldValue&nbsp;value&nbsp;expected&nbsp;to&nbsp;be&nbsp;associated&nbsp;with&nbsp;the&nbsp;specified&nbsp;key<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@param</span><span style="color: #008000; ">&nbsp;newValue&nbsp;value&nbsp;to&nbsp;be&nbsp;associated&nbsp;with&nbsp;the&nbsp;specified&nbsp;key<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@return</span><span style="color: #008000; ">&nbsp;&lt;tt&gt;true&lt;/tt&gt;&nbsp;if&nbsp;the&nbsp;value&nbsp;was&nbsp;replaced<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@throws</span><span style="color: #008000; ">&nbsp;UnsupportedOperationException&nbsp;if&nbsp;the&nbsp;&lt;tt&gt;put&lt;/tt&gt;&nbsp;operation<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is&nbsp;not&nbsp;supported&nbsp;by&nbsp;this&nbsp;map<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@throws</span><span style="color: #008000; ">&nbsp;ClassCastException&nbsp;if&nbsp;the&nbsp;class&nbsp;of&nbsp;a&nbsp;specified&nbsp;key&nbsp;or&nbsp;value<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prevents&nbsp;it&nbsp;from&nbsp;being&nbsp;stored&nbsp;in&nbsp;this&nbsp;map<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@throws</span><span style="color: #008000; ">&nbsp;NullPointerException&nbsp;if&nbsp;a&nbsp;specified&nbsp;key&nbsp;or&nbsp;value&nbsp;is&nbsp;null,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;this&nbsp;map&nbsp;does&nbsp;not&nbsp;permit&nbsp;null&nbsp;keys&nbsp;or&nbsp;values<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080; ">@throws</span><span style="color: #008000; ">&nbsp;IllegalArgumentException&nbsp;if&nbsp;some&nbsp;property&nbsp;of&nbsp;a&nbsp;specified&nbsp;key<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;value&nbsp;prevents&nbsp;it&nbsp;from&nbsp;being&nbsp;stored&nbsp;in&nbsp;this&nbsp;map<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;replace(K&nbsp;key,&nbsp;V&nbsp;oldValue,&nbsp;V&nbsp;newValue);</div><br />在ConcurrentMap的value中我们只需要给Integer，然后用replace去不断的尝试，即自己实现一个CAS：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;incrementRefCount(Object key)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;curCount&nbsp;=&nbsp;distributedMap.get(key);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(curCount&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;curCount&nbsp;=&nbsp;distributedMap.putIfAbsent(key,&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Integer(1));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(curCount&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;newCount&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Integer(curCount.intValue()&nbsp;+&nbsp;1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(distributedMap.replace(key,&nbsp;curCount,&nbsp;newCount))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;newCount;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(<span style="color: #0000FF; ">true</span>);<br />}</div><br />主要逻辑就是这样了，其实比较简单，只是之前没有遇到过这个问题，所以感觉可以记录下来。或许什么时候补充一下ZooKeeper版本的实现。<img src ="http://www.blogjava.net/DLevin/aggbug/424554.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2015-04-20 20:30 <a href="http://www.blogjava.net/DLevin/archive/2015/04/20/424554.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ReferenceCountSet无锁实现</title><link>http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Fri, 05 Dec 2014 16:29:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/421110.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/421110.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/421110.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 记得很久以前有一次面试被问到如何编写无锁程序，我当时觉得那个面试官脑子进水了，我们确实可以在某些情况下减少锁的使用，但是怎么可能避免呢？当然我现在还是持这种观点，在Java中，你可以有很多方法减少锁的使用(至少在你自己的代码中看起来)：  1.&nbsp;&nbsp;&nbsp;&nbsp; 比如常见的可以使用volatile关键字来保证某个字段在一个线程中的更新对其他线程的可见性；  2.&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/421110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2014-12-06 00:29 <a href="http://www.blogjava.net/DLevin/archive/2014/12/06/421110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Exchanger实现两个线程之间的数据交互</title><link>http://www.blogjava.net/DLevin/archive/2014/03/23/411377.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Sun, 23 Mar 2014 05:40:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2014/03/23/411377.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/411377.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2014/03/23/411377.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/411377.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/411377.html</trackback:ping><description><![CDATA[在看Jetty源码中的EndPointTest类，对EndPoint的测试，我的思路是：<br />
1. 建立一个连接（创建ServerSocket实例，一般还会给定一个端口，其实可以bind(null)以让操作系统分配一个可用端口），新启动一个线程，在新线程中监听给定端口（调用accept方法）。<br />
2. 发送客户端请求（创建一个Socket实例，并向该Socket写入请求数据）。<br />
3. 在接收端读取数据，验证写入的请求和接收到的数据相同。<br />
<br />
在以上流程实现中，accept方法返回的接收端Socket需要传给主线程，同时要保证使用该Socket是在accept方法返回之后，以我习惯，我会使用一个Lock或CountDownLatch：<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;SocketHolder&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;socket;<br />
}<br />
<br />
@Test<br />
<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;levinOldWayTest()&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;ServerSocket&nbsp;server&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;ServerSocket(10240);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;CountDownLatch&nbsp;latch&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;CountDownLatch(1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;SocketHolder&nbsp;socketHolder&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;SocketHolder();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Thread()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;run()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socketHolder.socket&nbsp;=&nbsp;server.accept();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;latch.countDown();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>(Exception&nbsp;ex)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;socket&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Socket(server.getInetAddress(),&nbsp;server.getLocalPort());<br />
&nbsp;&nbsp;&nbsp;&nbsp;socket.getOutputStream().write("My&nbsp;Test&nbsp;String".getBytes());<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;latch.await(5,&nbsp;TimeUnit.SECONDS);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">byte</span>[]&nbsp;receives&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;<span style="color: #0000FF; ">byte</span>[4096];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;length&nbsp;=&nbsp;socketHolder.socket.getInputStream().read(receives);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;assertEquals("My&nbsp;Test&nbsp;String",&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;String(receives,&nbsp;0,&nbsp;length));<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;socket.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;socketHolder.socket.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;server.close();<br />
}</div><br />不知道有多少人也像我一样把这段代码写成这样？这里有两个问题：<br />1. ServerSocket的监听的端口不一定是可用的，类似测试代码我之前没有写过，我估计自己正真在写的时候应该会想到让操作系统动态分配。<br />2. 为了在两个线程中传递数据，这里首先创建了一个SocketHolder类，然后使用CountDownLatch，写起来好麻烦。为了简化这段代码，可以使用Exchanger，即当一个生产者线程准备好数据后可以通过Exchanger将数据传递给消费者，而消费者在生产者传递过来数据后就可以消费了，这里的数据就是Socket。<br /><br />改进后的代码如下：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->@Test<br /><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;levinImprovedWayTest()&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;ServerSocket&nbsp;server&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;ServerSocket();<br />&nbsp;&nbsp;&nbsp;&nbsp;server.bind(<span style="color: #0000FF; ">null</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;Exchanger&lt;Socket&gt;&nbsp;exchanger&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Exchanger&lt;Socket&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Thread()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;run()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exchanger.exchange(server.accept());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">catch</span>(Exception&nbsp;ex)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}.start();<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;socket&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Socket(server.getInetAddress(),&nbsp;server.getLocalPort());<br />&nbsp;&nbsp;&nbsp;&nbsp;socket.getOutputStream().write("My&nbsp;Test&nbsp;String".getBytes());<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;receiverSocket&nbsp;=&nbsp;exchanger.exchange(<span style="color: #0000FF; ">null</span>,&nbsp;5,&nbsp;TimeUnit.SECONDS);<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">byte</span>[]&nbsp;receives&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;<span style="color: #0000FF; ">byte</span>[4096];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;length&nbsp;=&nbsp;receiverSocket.getInputStream().read(receives);<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;assertEquals("My&nbsp;Test&nbsp;String",&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;String(receives,&nbsp;0,&nbsp;length));<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;socket.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;receiverSocket.close();<br />&nbsp;&nbsp;&nbsp;&nbsp;server.close();<br />}</div><img src ="http://www.blogjava.net/DLevin/aggbug/411377.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2014-03-23 13:40 <a href="http://www.blogjava.net/DLevin/archive/2014/03/23/411377.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Core系列之TreeMap实现详解</title><link>http://www.blogjava.net/DLevin/archive/2013/10/26/405667.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Sat, 26 Oct 2013 10:41:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2013/10/26/405667.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/405667.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2013/10/26/405667.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/405667.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/405667.html</trackback:ping><description><![CDATA[因为看EHCache中溢出文件的管理代码，它用到了AA－Tree作为文件中的磁盘管理，因而决定先复习以下红黑树(RBT, Red Black Tree)，顺便看看TreeMap的代码。关于红黑树，网上已经有各种相关的文章了，因而属于多一篇不多，少一篇不少的状态，因而我纯粹当作是我自己理解的纪录，加深印象，如果能对部分思路和我类似的人有一些帮助，那就最好了。基于这样的目的，我并不打算深入，如果想看更深入的或者更好的，可以读读我最后的参考链接。<br />
<br />
<strong style="color: orange;">红黑树引入的目的</strong>
<br />首先要从对有序序列的查找问题开始，对一个静态的有序序列数组，只需要二分查找即可得到O(log(n))的查找效率；然而实现并不会显得那么&#8220;静态&#8221;，需要实现动态的插入、删除同时保持序列的有序性，并且尽量提高插入、删除、查找的效率。<br />
<br />
为实现动态插入、删除，最简单的实现是二叉排序树(BST, Binary Sort Tree)，它具有以下性质：<br />
1. 它可以是一个空树。<br />
2. 若它的左子树不为空，则它的左子树所有节点的值均小于根节点的值。<br />
3. 若它的右子树不为空，则它的右子树所有节点的值均大于根节点的值。<br />
4. 它的左子树和右子树都是一个二叉排序树。<br />
根据以上性质，<br />对查找，比较查找数和当前节点，如果查找数和当前节点相等，则找到返回；如果查找数小于当前节点，查找其左子树，如果查找数大于当前节点，查找其右子树，直到找到或直到叶子节点为null，返回null。<br />对插入，先查找这棵树，如果找到已存在的节点，更新节点值，否则把新值插入到最后一个为null的节点中。<br />对删除，首先找到要删除的节点，a）如果找到的节点P没有子节点，直接删除即可；b）如果找到的节点P只有左子树或右子树，删除该节点，并将其父节点原来的指针指向它唯一的左子树、或右子树即可；c）如果找到的节点P既有左子树又有右子树，可以有两种做法：I）删除节点P，把节点P的父节点原来指向P的指针指向节点P的左字节点，而将节点P的右节点插入到节点P右节点的最右叶子节点上（如果节点P是其父节点的右节点，则将节点P的父节点原来指向P节点的指针指向P节点的右子树，而将节点P的左子树插入到节点P最左叶子节点上），II）将节点P替换成节点P的直接前驱（或直接后继），然后删除节点P的直接前驱（或直接后继）（注：直接前驱查找：节点P左子树的最右节点，直接后继查找：节点P右子树的最左节点）。<br />
二叉排序树实现比较简单，但是它查找效率却不理想，最好的效率是O(log(n))，最会效率为O(n)。<br />
<br />
为了提高查找效率，后来有人提出了平衡二叉树（AVL树），它具有二叉排序树的所有特点，并添加了以下性质：<br />
1. 左子树和右子树的深度之差绝对值不超过1。<br />
2. 左子树和右子树都是平衡二叉树。<br />
为了实现平衡二叉树，需要在没个节点上添加平衡因子字段，在插入后，如果发现平衡因子不符合性质1，则需要经过旋转以调整。平衡二叉树可以保证其查找的最好、最坏查找时间复杂度都为O(log(n))。<br />
<br />
红黑树是平衡二叉树的变种，它是一种自平衡的二叉排序树，也需要通过一些旋转调整以保持它的性质，它的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。不同于平衡二叉树的高度平衡，红黑树只能保证从根到叶子节点的最长路径不超过最短路径的2倍，因而它的最坏查找时间复杂度为O(2log(n + 1))，然而有研究表明它的统计性能要好于平衡二叉树，因而它具有更广泛的应用。<br />
<br />
<strong style="color: orange;">红黑树的性质</strong><br />
一棵树需要满足以下性质才能保证它是一颗红黑树：<br />
1. 它是一颗二叉查找树（BST）。<br />
2. 它的所有节点是红色或黑色。<br />
3. 它的根节点是黑色。<br />
4. 它的叶子节点是黑色（空节点视为叶子节点）。<br />
5. 它的红节点的子节点必须是黑色的；而黑节点的字节点可以是黑色或红色。<br />
6. 它任一节点到其后代的叶子节点路径上有相同的黑色节点数。<br />
一般的文章都是把性质列出来，然后根据这些性质来写代码实现（我也一样:)），但是如何得出这些性质呢？多问几个为什么总是好事，这个问题需要去读上面提到的论文，我没读过也不打算读，这貌似不是我能涉及的，那就提出问题不回答了。。。<br />
<br /><strong style="color: orange;">TreeMap中红黑树的节点</strong><br />对一颗树的节点，最基础是该节点的值、左节点指针、右节点指针。对TreeMap，因为它存储的是键值对，因而它包含了key、value，为了纪录节点的颜色，它还需要有color字段：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;RED&nbsp;&nbsp;&nbsp;=&nbsp;<span style="color: #0000FF; ">false</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;BLACK&nbsp;=&nbsp;<span style="color: #0000FF; ">true</span>;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Entry&lt;K,V&gt;&nbsp;<span style="color: #0000FF; ">implements</span>&nbsp;Map.Entry&lt;K,V&gt;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K&nbsp;key;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;left&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;right&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;parent;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;color&nbsp;=&nbsp;BLACK;<br />&nbsp; &nbsp; &nbsp; &nbsp; ....<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /><strong style="color: orange;">TreeMap中红黑树节点插入</strong><br />红黑数的插入分以下步骤：<br />1. 如果当前为空树，插入节点直接作为根节点，并将该节点颜色比较<br />
2. 以二叉排序树的查找算法查找当前树，如果在当前树中找到已存在的节点，更新节点的值，并返回。<br />3. 否则，创建一个新节点，将其插入到最后一个查找到的叶子节点上，其初始颜色为红色。<br />4. 如果新插入节点的父节点是黑节点，则没有破坏当前红黑树的性质，直接返回。<br />5. 如果新插入节点的父节点是红节点，则需要做一些调整。<br />在TreeMap中，key值的比较可以通过构造TreeMap传入的Comparator实例，如果没有Comparator，则key必须实现Comparable接口作为比较逻辑，key不可以为null。以二叉排序树的算法插入新节点的代码比较简单：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;V&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;t&nbsp;=&nbsp;root;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(t&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;compare(key,&nbsp;key);&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;type&nbsp;(and&nbsp;possibly&nbsp;null)&nbsp;check</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Entry&lt;&gt;(key,&nbsp;value,&nbsp;<span style="color: #0000FF; ">null</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size&nbsp;=&nbsp;1;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modCount++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;cmp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;parent;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;split&nbsp;comparator&nbsp;and&nbsp;comparable&nbsp;paths</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Comparator&lt;?&nbsp;<span style="color: #0000FF; ">super</span>&nbsp;K&gt;&nbsp;cpr&nbsp;=&nbsp;comparator;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(cpr&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent&nbsp;=&nbsp;t;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmp&nbsp;=&nbsp;cpr.compare(key,&nbsp;t.key);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(cmp&nbsp;&lt;&nbsp;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;t.left;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(cmp&nbsp;&gt;&nbsp;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;t.right;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;t.setValue(value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(t&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(key&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">throw</span>&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;NullPointerException();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Comparable&lt;?&nbsp;<span style="color: #0000FF; ">super</span>&nbsp;K&gt;&nbsp;k&nbsp;=&nbsp;(Comparable&lt;?&nbsp;<span style="color: #0000FF; ">super</span>&nbsp;K&gt;)&nbsp;key;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">do</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent&nbsp;=&nbsp;t;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmp&nbsp;=&nbsp;k.compareTo(t.key);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(cmp&nbsp;&lt;&nbsp;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;t.left;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(cmp&nbsp;&gt;&nbsp;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;t.right;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;t.setValue(value);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(t&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;e&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Entry&lt;&gt;(key,&nbsp;value,&nbsp;parent);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(cmp&nbsp;&lt;&nbsp;0)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent.left&nbsp;=&nbsp;e;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent.right&nbsp;=&nbsp;e;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixAfterInsertion(e);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modCount++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;fixAfterInsertion(Entry&lt;K,V&gt;&nbsp;x)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.color&nbsp;=&nbsp;RED;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" />..<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root.color&nbsp;=&nbsp;BLACK;<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><strong style="color: orange;"><br />TreeMap中红黑树新节点插入后调整</strong><br />红黑树的调整比较复杂，首先它会从当前节点向上查找，直到当前节点为null，或是root节点，或者当前节点的父节点颜色不是红色，然后根据以下不同情况做处理（设当前节点为C（红色），其父节点为P（红色），其祖先节点为A（黑色），其叔叔节点为U（待定））：<br />1. P是A的左子树，U节点颜色为红色，此时不管C是节点是P的左子树还是右子树，只需要将P和U设为黑色，A设为红色，则可保证当前局部树符合红黑树定义，把A作为新插入节点重新调整，如果当前树已经是整棵树，则因为根节点为红色，不符合红黑树定义，此时只需要将根节点颜色设置为黑色即可，即fixAfterInsertion()最后一句代码的作用。<br />2. P是A的左子树，U节点颜色为黑色，C是P的左子树，将P设置为黑色，A设置为红色，并对A做右旋操作。此时C的父节点已变为黑色，循环可以直接退出。<br />3. P是A的左子树，U节点颜色为黑色，C是P的右子树，此时只需要先对P左旋，然后设置C为黑色，A为红色，并对A右旋，此时P的父节点已变为黑色，循环可以直接退出。<br />如下图所示：<br /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/P是A的左子树.png" alt="" height="484" border="0" width="648" /><br />代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(x&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>&nbsp;&amp;&amp;&nbsp;x&nbsp;!=&nbsp;root&nbsp;&amp;&amp;&nbsp;x.parent.color&nbsp;==&nbsp;RED)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(parentOf(x)&nbsp;==&nbsp;leftOf(parentOf(parentOf(x))))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;y&nbsp;=&nbsp;rightOf(parentOf(parentOf(x)));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(y)&nbsp;==&nbsp;RED)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(x),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(y,&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(parentOf(x)),&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;parentOf(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(x&nbsp;==&nbsp;rightOf(parentOf(x)))&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;x&nbsp;=&nbsp;parentOf(x);<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;rotateLeft(x);<br />&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;setColor(parentOf(x),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(parentOf(x)),&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rotateRight(parentOf(parentOf(x)));<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;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ....<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div>4. P是A的右子树，U节点颜色为红色，此时不管C是节点是P的左子树还是右子树，只需要将P和U设为黑色，A设为红色，则可保证当前局部树符合红黑树定义，把A作为新插入节点重新调整，如果当前树已经是整棵树，则因为根节点为红色，不符合红黑树定义，此时只需要将根节点颜色设置为黑色即可，即fixAfterInsertion()最后一句代码的作用。<br />5. P是A的右子树，U节点颜色为黑色，C是P的右子树，将P设置为黑色，A设置为红色，并对A做左旋操作。此时C的父节点以变为黑色，循环可以直接退出。<br />6. P是A的右子树，U节点颜色为黑色，C是P的左子树，此时只需要先对P左旋，然后设置C为黑色，A为红色，并对A右旋，此时P的父节点已为黑色，循环可以直接退出。<br />如下图所示：<br /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/P是A的右子树.JPG" alt="" height="484" border="0" width="648" /><br />代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(x&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>&nbsp;&amp;&amp;&nbsp;x&nbsp;!=&nbsp;root&nbsp;&amp;&amp;&nbsp;x.parent.color&nbsp;==&nbsp;RED)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(parentOf(x)&nbsp;==&nbsp;leftOf(parentOf(parentOf(x))))&nbsp;{<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ....<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;y&nbsp;=&nbsp;leftOf(parentOf(parentOf(x)));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(y)&nbsp;==&nbsp;RED)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(x),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(y,&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(parentOf(x)),&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;parentOf(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(x&nbsp;==&nbsp;leftOf(parentOf(x)))&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;x&nbsp;=&nbsp;parentOf(x);<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;rotateRight(x);<br />&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;setColor(parentOf(x),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(parentOf(x)),&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rotateLeft(parentOf(parentOf(x)));<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;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /><strong style="color: orange;">TreeMap中红黑树节点删除</strong><br />红黑树的删除类似二叉查找树删除逻辑类似，在对同时有左子树和右子树存在时，TreeMap选择先将要删除的节点替换成其直接后继节点，然后删除其直接后继节点（其直接后继节点不可能同时存在左子节点和右子字节点）。对红黑树，由于红色节点不影响路径计算（性质6），因而对红色节点可以直接删除。然而在删除黑色节点时，如果删除的节点不是树的唯一节点，那么在某些路径上的黑色节点数会发生改变，破坏性质6；如果被删除的唯一子节点为红色，而父节点也为红色，那么性质5被破坏，因为存在红色节点的子节点为红色；如果删除的是根节点，而它的唯一子节点是红色，则性质3被破坏。因而需要做一些调整。<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;deleteEntry(Entry&lt;K,V&gt;&nbsp;p)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;modCount++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size--;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;If&nbsp;strictly&nbsp;internal,&nbsp;copy&nbsp;successor's&nbsp;element&nbsp;to&nbsp;p&nbsp;and&nbsp;then&nbsp;make&nbsp;p<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;point&nbsp;to&nbsp;successor.</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p.left&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>&nbsp;&amp;&amp;&nbsp;p.right&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;s&nbsp;=&nbsp;successor(p);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.key&nbsp;=&nbsp;s.key;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.value&nbsp;=&nbsp;s.value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;=&nbsp;s;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;p&nbsp;has&nbsp;2&nbsp;children<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Start&nbsp;fixup&nbsp;at&nbsp;replacement&nbsp;node,&nbsp;if&nbsp;it&nbsp;exists.</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;replacement&nbsp;=&nbsp;(p.left&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>&nbsp;?&nbsp;p.left&nbsp;:&nbsp;p.right);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(replacement&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Link&nbsp;replacement&nbsp;to&nbsp;parent</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;replacement.parent&nbsp;=&nbsp;p.parent;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p.parent&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root&nbsp;=&nbsp;replacement;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p&nbsp;==&nbsp;p.parent.left)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.parent.left&nbsp;&nbsp;=&nbsp;replacement;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.parent.right&nbsp;=&nbsp;replacement;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Null&nbsp;out&nbsp;links&nbsp;so&nbsp;they&nbsp;are&nbsp;OK&nbsp;to&nbsp;use&nbsp;by&nbsp;fixAfterDeletion.</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.left&nbsp;=&nbsp;p.right&nbsp;=&nbsp;p.parent&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Fix&nbsp;replacement</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p.color&nbsp;==&nbsp;BLACK)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixAfterDeletion(replacement);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p.parent&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;return&nbsp;if&nbsp;we&nbsp;are&nbsp;the&nbsp;only&nbsp;node.</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;root&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;&nbsp;No&nbsp;children.&nbsp;Use&nbsp;self&nbsp;as&nbsp;phantom&nbsp;replacement&nbsp;and&nbsp;unlink.</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p.color&nbsp;==&nbsp;BLACK)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixAfterDeletion(p);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p.parent&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p&nbsp;==&nbsp;p.parent.left)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.parent.left&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(p&nbsp;==&nbsp;p.parent.right)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.parent.right&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.parent&nbsp;=&nbsp;<span style="color: #0000FF; ">null</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /><strong style="color: orange;">TreeMap中红黑树删除黑色节点后调整</strong><br />调整的逻辑分以下步骤来考虑（假设新替换的节点为C，即代码中的x参数，C的父节点为P，C是P的左子节点，C的兄弟节点为S，S的左子树为SL，S的右子树为SR）：<br />1. 如果C为红色，直接将C标记为黑色即可，因为删除的黑节点数被该节点补上，该树已经恢复成一颗红黑树。<br />2. 如果C为黑色，且C为根节点，直接返回。<br />3. 如果C为黑色，且S为红色，那么节点P、SL、SR都为黑色，此时设置P为红色，S为黑色，对P左旋，并重新计算S，即S变为SL，即把问题转换为兄弟节点为黑色的情况。图片来自http://blog.csdn.net/v_JULY_v/article/details/6105630，自己画太麻烦了，虽然图片的命名规则和我的不一样，凑合的看把，囧。<br /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为红节点-变换前.jpg" alt="" height="362" width="487" />&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为红节点-变换后.jpg" alt="" height="349" width="469" /><br />4. 如果C为黑色，S为黑色，且SL、SR都为黑色，将S设置为红色，P赋值给C，重新计算。<br /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为黑节点-变换前.jpg" alt="" height="349" width="469" /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为黑节点-变换后.jpg" alt="" height="349" width="469" /><br />5. 如果C为黑色，S为黑色，且SL为红色，SR为黑色，那么设置SL为黑色，S为红色，对S右旋，重新设置S为SL。<br /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为黑节点左子节点为红色-变换前.jpg" alt="" height="349" width="469" /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为黑节点左子节点为红色-变换后.jpg" alt="" height="445" width="469" /><br />6. 如果C为黑色，S为黑色，且SR为红色，SL为任一颜色，则把S节点的颜色设置为P节点的颜色，设置P节点的颜色为黑色，SR节点的颜色为黑色，对P节点右旋，算法结束。<br /><img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为黑节点右子节点为红色-变换前.jpg" alt="" height="349" width="469" />&nbsp;<img src="http://www.blogjava.net/images/blogjava_net/dlevin/当前节点为黑节点兄弟节点为黑节点右子节点为红色-变换后.jpg" alt="" height="349" width="469" /><br />当C为P的右子节点时，其逻辑和以上对称，不再赘述。<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;fixAfterDeletion(Entry&lt;K,V&gt;&nbsp;x)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;(x&nbsp;!=&nbsp;root&nbsp;&amp;&amp;&nbsp;colorOf(x)&nbsp;==&nbsp;BLACK)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(x&nbsp;==&nbsp;leftOf(parentOf(x)))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;sib&nbsp;=&nbsp;rightOf(parentOf(x));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(sib)&nbsp;==&nbsp;RED)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(sib,&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(x),&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rotateLeft(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sib&nbsp;=&nbsp;rightOf(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(leftOf(sib))&nbsp;&nbsp;==&nbsp;BLACK&nbsp;&amp;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colorOf(rightOf(sib))&nbsp;==&nbsp;BLACK)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(sib,&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;parentOf(x);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(rightOf(sib))&nbsp;==&nbsp;BLACK)&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;setColor(leftOf(sib),&nbsp;BLACK);<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;setColor(sib,&nbsp;RED);<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;rotateRight(sib);<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;sib&nbsp;=&nbsp;rightOf(parentOf(x));<br />&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;setColor(sib,&nbsp;colorOf(parentOf(x)));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(x),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(rightOf(sib),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rotateLeft(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;root;<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;<span style="color: #0000FF; ">else</span>&nbsp;{&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;symmetric</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;sib&nbsp;=&nbsp;leftOf(parentOf(x));<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(sib)&nbsp;==&nbsp;RED)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(sib,&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(x),&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rotateRight(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sib&nbsp;=&nbsp;leftOf(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(rightOf(sib))&nbsp;==&nbsp;BLACK&nbsp;&amp;&amp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colorOf(leftOf(sib))&nbsp;==&nbsp;BLACK)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(sib,&nbsp;RED);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;parentOf(x);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(colorOf(leftOf(sib))&nbsp;==&nbsp;BLACK)&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;setColor(rightOf(sib),&nbsp;BLACK);<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;setColor(sib,&nbsp;RED);<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;rotateLeft(sib);<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;sib&nbsp;=&nbsp;leftOf(parentOf(x));<br />&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;setColor(sib,&nbsp;colorOf(parentOf(x)));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(parentOf(x),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(leftOf(sib),&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rotateRight(parentOf(x));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;root;<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;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setColor(x,&nbsp;BLACK);<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><br /><strong style="color: orange;">TreeMap中红黑树节点查找</strong><br />红黑树的节点查找同二叉查找树逻辑，不再赘述。这里有一点不太明白：getEntryUsingComparator()方法注释中说它从getEntry()方法提取出来是为了性能上的考虑，<span style="color: red;">这是为什么？</span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp;&nbsp;<span style="color: #008000; ">/**</span><span style="color: #008000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Version&nbsp;of&nbsp;getEntry&nbsp;using&nbsp;comparator.&nbsp;Split&nbsp;off&nbsp;from&nbsp;getEntry<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;for&nbsp;performance.&nbsp;(This&nbsp;is&nbsp;not&nbsp;worth&nbsp;doing&nbsp;for&nbsp;most&nbsp;methods,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;that&nbsp;are&nbsp;less&nbsp;dependent&nbsp;on&nbsp;comparator&nbsp;performance,&nbsp;but&nbsp;is<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;worthwhile&nbsp;here.)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">*/</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;Entry&lt;K,V&gt;&nbsp;getEntryUsingComparator(Object&nbsp;key)</div><br /><strong style="color: orange;">TreeMap中其他方法</strong><br />TreeMap中其他方法实现比较直观，只要理解了红黑树，基本上很容易理解，不再赘述。<br /><br />参考链接：<br />
<div>http://blog.csdn.net/v_JULY_v/article/details/6105630<br />
<div>http://blog.csdn.net/zhaojinjia/article/details/8120403<br />
<div>http://blog.csdn.net/eric491179912/article/details/6179908<br /><div>http://dongxicheng.org/structure/red-black-tree/</div></div>
</div>
</div><img src ="http://www.blogjava.net/DLevin/aggbug/405667.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2013-10-26 18:41 <a href="http://www.blogjava.net/DLevin/archive/2013/10/26/405667.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Core系列之ConcurrentHashMap实现(JDK 1.7)</title><link>http://www.blogjava.net/DLevin/archive/2013/10/18/405030.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Fri, 18 Oct 2013 14:24:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2013/10/18/405030.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/405030.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2013/10/18/405030.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/405030.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/405030.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: ConcurrentHashMap类似Hashtable，是HashMap更高效的线程安全版本的实现。不同于Hashtable简单的将所有方法标记为synchronized，它将内部数组分成多个Segment，每个Segment类似一个Hashtable，从而减少锁的粒度，并且它内部有一些比较tricky实现，让get操作很多时候甚至不需要锁（本文代码基于JDK 1.7，它在JDK 1.6的基础上...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2013/10/18/405030.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/405030.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2013-10-18 22:24 <a href="http://www.blogjava.net/DLevin/archive/2013/10/18/405030.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Core系列之HashMap实现</title><link>http://www.blogjava.net/DLevin/archive/2013/10/15/404984.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Tue, 15 Oct 2013 15:40:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2013/10/15/404984.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/404984.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2013/10/15/404984.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/404984.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/404984.html</trackback:ping><description><![CDATA[最近在看Guava中的Cache的源码，它的实现基于ConcurrentHashMap，前段时间组里招人，据说很多看起来很牛掰的简历，一个HashMap就能刷掉很多，所以顺便把HashMap和ConcurrentHashMap的源码复习一遍。先从HashMap开始（另：Hashtable是HashMap的线程安全版本，它的实现和HashMap实现基本一致，除了它不能包含null值的key和value，并且它在计算hash值和数组索引值的方式要稍微简单一些。对于线程安全的实现，Hashtable简单的将所有操作都标记成synchronized，即对当前实例的锁，这样容易引起一些性能问题，所以目前一般使用性能更好的ConcurrentHashMap）。<br />
<br />
Map是对键值对存储的抽象，因而其最主要的方法有：<br />1. 添加新的键值对(key,value)；<br />2. 通过键(key)查找关联的值(value)；<br />3. 通过键(key)移除关联的值(value)；<br />4. 判断键(key)或值(value)的存在性。<br />其他的方法有：判断键值对的空属性以及目前的键值对数，获取所有键、所有值或者所有键值对的集合，批量添加，清除所有键值对等。在Map中，一个键值对用Entry接口来表示。因而在Java中，对Map接口的定义如下：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;Map&lt;K,V&gt;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isEmpty();<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;containsKey(Object&nbsp;key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;containsValue(Object&nbsp;value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;get(Object&nbsp;key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;put(K&nbsp;key,&nbsp;V&nbsp;value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;remove(Object&nbsp;key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;putAll(Map&lt;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;K,&nbsp;?&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;V&gt;&nbsp;m);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;clear();<br />
&nbsp;&nbsp;&nbsp;&nbsp;Set&lt;K&gt;&nbsp;keySet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;Collection&lt;V&gt;&nbsp;values();<br />
&nbsp;&nbsp;&nbsp;&nbsp;Set&lt;Map.Entry&lt;K,&nbsp;V&gt;&gt;&nbsp;entrySet();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;Entry&lt;K,V&gt;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;K&nbsp;getKey();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;getValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;setValue(V&nbsp;value);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;equals(Object&nbsp;o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;hashCode();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;equals(Object&nbsp;o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;hashCode();<br />
}</div>
HashMap是哈希表对Map非线程安全版本的实现，<strong>它允许key为null，也允许value为null</strong>。所谓哈希表就是通过一个哈希函数计算出一个key的哈希值，然后使用该哈希值定位对应的value所在的位置；如果出现哈希值冲突（多个key产生相同的哈希值），则采用一定的冲突处理方法定位到正真value位置，然后返回查找到的value值。一般哈希表内部使用一个数组实现，使用哈希函数计算出key对应数组中的位置，然后使用处理冲突法找到真正的value，并返回。因而实现哈希表最主要的问题在于选择哈希函数和冲突处理方法，好的哈希函数能使数据分布更加零散，从而减少冲突的可能性，而好的冲突处理方法能使冲突处理更快，尽量让数据分布更加零散，从而不会影响将来的冲突处理方法。<br />
<br />
在严蔚敏、吴伟明版本的《数据结构（C语言版）》中提供的哈希函数有：1. 直接定址法（线性函数法）；2. 数字分析法；3. 平方取中法；4. 折叠法；5. 除留余数法；6. 随机数法。在JDK的HashMap中采用了移位异或法后除留余数（和2的n次方'&amp;'操作）。HashMap内部的数据结构是一个Entry&lt;K, V&gt;的数组，在使用key查找value时，先使用key实例计算hash值，然后对计算出的hash值做各种移位和异或操作，然后取其数组的最大索引值的余数（'&amp;'操作，一般其容量值都是2的倍数，因而可以认为是除留余数）。在JDK 1.7中对String类型采用了内部hash算法（当数组容量超过一定的阀值，使用&#8220;jdk.map.althashing.threshold&#8221;设置该阀值，默认为Integer.MAX_VALUE，即关闭该功能），并且使用了一个hashSeed作为初始值，不了解这些算法的具体缘由，就这样浅尝辄止了。<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;hash(Object&nbsp;k)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;h&nbsp;=&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(useAltHashing)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(k&nbsp;<span style="color: #0000FF; ">instanceof</span>&nbsp;String)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;sun.misc.Hashing.stringHash32((String)&nbsp;k);<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;&nbsp;h&nbsp;=&nbsp;hashSeed;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;^=&nbsp;k.hashCode();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h&nbsp;^=&nbsp;(h&nbsp;&gt;&gt;&gt;&nbsp;20)&nbsp;^&nbsp;(h&nbsp;&gt;&gt;&gt;&nbsp;12);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;h&nbsp;^&nbsp;(h&nbsp;&gt;&gt;&gt;&nbsp;7)&nbsp;^&nbsp;(h&nbsp;&gt;&gt;&gt;&nbsp;4);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;indexFor(<span style="color: #0000FF; ">int</span>&nbsp;h,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;length)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;h&nbsp;&amp;&nbsp;(length-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</div>
同样在上述的数据结构书中关于冲突处理提供了几个方法：1. 开放定址法；2. 再哈希法；3.链地址法；4. 建立一个公共溢出区法。在JDK的HashMap中采用了链地址法，即每个数组bucket中存放的是一个Entry链，每次新添加一个键值对，就是向链头添加一个Entry实例，新添加的Entry的下一个元素是原有的链头（如果该数组bucket不存在Entry链，则原有链头值为null，不影响逻辑）。每个Entry包含key、value、hash值和指向下一个Entry的next指针。<br />
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Entry&lt;K,V&gt;&nbsp;<span style="color: #0000FF; ">implements</span>&nbsp;Map.Entry&lt;K,V&gt;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;K&nbsp;key;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;next;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;hash;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</div>
<br />
<strong>添加</strong><br />
从以上描述中，我们可以知道添加新的键值对可以分成两部分：<br />
1. 使用key计算出内部数组的索引值（index）。<br />
2. 如果该索引的数组bucket中已经存在Entry链，并且该链中已经存在新添加的key的值，则将原有的值设置成新添加的值，并返回旧值。<br />
3. 否则，创建新的Entry实例，将该实例插入到原有链的头部。<br />
4. 在新添加Entry实例时，如果当前size超过阀值（capacity * loadFactor），数组容量将会自动扩大两倍，在数组扩容时，所有原存在的Entry会重新计算索引值，并且Entry链的顺序也会发生颠倒（如果还在同一个链中的话）；而该新添加的Entry的索引值也会重新计算。<br />
5. 对key为null时，默认数组的索引值为0，其他逻辑不变。<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;addEntry(<span style="color: #0000FF; ">int</span>&nbsp;hash,&nbsp;K&nbsp;key,&nbsp;V&nbsp;value,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;bucketIndex)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;((size&nbsp;&gt;=&nbsp;threshold)&nbsp;&amp;&amp;&nbsp;(<span style="color: #0000FF; ">null</span>&nbsp;!=&nbsp;table[bucketIndex]))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resize(2&nbsp;*&nbsp;table.length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hash&nbsp;=&nbsp;(<span style="color: #0000FF; ">null</span>&nbsp;!=&nbsp;key)&nbsp;?&nbsp;hash(key)&nbsp;:&nbsp;0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bucketIndex&nbsp;=&nbsp;indexFor(hash,&nbsp;table.length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;createEntry(hash,&nbsp;key,&nbsp;value,&nbsp;bucketIndex);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;createEntry(<span style="color: #0000FF; ">int</span>&nbsp;hash,&nbsp;K&nbsp;key,&nbsp;V&nbsp;value,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;bucketIndex)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry&lt;K,V&gt;&nbsp;e&nbsp;=&nbsp;table[bucketIndex];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table[bucketIndex]&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;Entry&lt;&gt;(hash,&nbsp;key,&nbsp;value,&nbsp;e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</div>
插入原理图：<br />
<img src="http://www.blogjava.net/images/blogjava_net/dlevin/hashmap_insert.png" alt="" height="325" border="0" width="564" />
<br />
<strong>
查找
</strong><br />
查找和添加类似，首先根据key计算出数组的索引值（如果key为null，则索引值为0），然后顺序查找该索引值对应的Entry链，如果在Entry链中找到相等的key，则表示找到相应的Entry记录，否则，表示没找到，返回null。对get()操作返回Entry中的Value值，对于containsKey()操作，则判断是否存在记录，两个方法都调用getEntry()方法：<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;Entry&lt;K,V&gt;&nbsp;getEntry(Object&nbsp;key)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;hash&nbsp;=&nbsp;(key&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;?&nbsp;0&nbsp;:&nbsp;hash(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(Entry&lt;K,V&gt;&nbsp;e&nbsp;=&nbsp;table[indexFor(hash,&nbsp;table.length)];&nbsp;e&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>;&nbsp;e&nbsp;=&nbsp;e.next)&nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object&nbsp;k;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(e.hash&nbsp;==&nbsp;hash&nbsp;&amp;&amp;&nbsp;((k&nbsp;=&nbsp;e.key)&nbsp;==&nbsp;key&nbsp;||&nbsp;(key&nbsp;!=&nbsp;<span style="color: #0000FF; ">null</span>&nbsp;&amp;&amp;&nbsp;key.equals(k))))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;e;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #0000FF; ">null</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</div>
而对于value查找（如containsValue()操作）则需要整个表遍历（数组遍历和数组中的Entry链遍历），因而这种查找的效率比较低，代码实现也比较简单。<br /><br /><strong>移除<br /></strong>移除操作（remove()）也是先通过key值计算数组中的索引号（当key为null时索引号为0），从而找到Entry链，查找Entry链中的Entry，并将该Entry删除。<br /><br /><strong>遍历<br /></strong>HashMap中实现了一个HashIterator，它首先遍历数组，查找到一个非null的Entry实例，记录该Entry所在数组索引，然后在下一个next()操作中，继续查找下一个非null的Entry，并将之前查找到的非null Entry返回。为实现遍历时不能修改HashMap的内容（可以更新已存在的记录的值，但是不可以添加、删除原有记录），HashMap记录一个modCount字段，在每次添加或删除操作起效时，将modCount自增，而在创建HashIterator时记录当前的modCount值（expectedModCount），如果在遍历过程中（next()、remove()）操作时，HashMap中的modCount和已存储的expectedModCount不一样，表示HashMap已经被修改，抛出ConcurrentModificationException。即所谓的fail fast原则。<br />在HashMap中返回的key、value、Entry集合都是基于该Iterator实现，实现比较简单，不细讲。<br /><br /><strong>注：clear()操作引起的内存问题-</strong>由于clear()操作只是将数组中的所有项置为null，数组本身大小并不改变，因而当某个HashMap已存储过较大的数据时，调用clear()有些时候不是一个好的做法。<br /><br />最后吐槽一下，即使JDK内部的HashMap也有很多的代码重复。。。。。<img src ="http://www.blogjava.net/DLevin/aggbug/404984.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2013-10-15 23:40 <a href="http://www.blogjava.net/DLevin/archive/2013/10/15/404984.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SAX解析XML文件</title><link>http://www.blogjava.net/DLevin/archive/2012/11/18/391545.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Sun, 18 Nov 2012 12:10:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2012/11/18/391545.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/391545.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2012/11/18/391545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/391545.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/391545.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 就目前来说，有三种方式可以解析XML文件：DOM、SAX、StAX。DOM将整个XML文件加载到内存中，并构建出节点树；应用程序可以通过遍历节点树的方式来解析XML文件中的各个节点、属性等信息；这种方式便于对XML节点的添加修改等，而且解析也很方便，然后它比较耗费内存，解析速度也不快。SAX则是基于事件的解析，解析器在一次读取XML文件中根据读取的数据产生相应的事件，由应用程序实现相应的事件处理逻...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2012/11/18/391545.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/391545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2012-11-18 20:10 <a href="http://www.blogjava.net/DLevin/archive/2012/11/18/391545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】关于AccessController.doPrivileged</title><link>http://www.blogjava.net/DLevin/archive/2012/11/02/390637.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Thu, 01 Nov 2012 17:04:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2012/11/02/390637.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/390637.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2012/11/02/390637.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/390637.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/390637.html</trackback:ping><description><![CDATA[转自：<a href="http://hi.baidu.com/qmiao128/item/eedc21dfa60d2051d63aae2b">http://hi.baidu.com/qmiao128/item/eedc21dfa60d2051d63aae2b</a><br />最近在看一些框架代码，偶尔都会遇到AccessController.doPrivileged()方法的使用，虽然之前在《深入解析Java虚拟机》这本书上看到过对这个方法的解释，但是貌似当时没有真正理解，虽然到现在对这个方法的概念还比较模糊，感觉这边文章介绍的挺清晰的，因而转载过来。<br /><br /><span class="Apple-style-span" style="color: #454545; font-family: tahoma, Helvetica, arial; "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">AccessController.doPrivileged是一个在AccessController类中的静态方法，允许在一个类实例中的代码通知这个AccessController：它的代码主体是享受"privileged(特权的)"，它单独负责对它的可得的资源的访问请求，而不管这个请求是由什么代码所引发的。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">这就是说，一个调用者在调用doPrivileged方法时，可被标识为 "特权"。在做访问控制决策时，如果checkPermission方法遇到一个通过doPrivileged调用而被表示为 "特权"的调用者，并且没有上下文自变量，checkPermission方法则将终止检查。如果那个调用者的域具有特定的许可，则不做进一步检查，checkPermission安静地返回，表示那个访问请求是被允许的；如果那个域没有特定的许可，则象通常一样，一个异常被抛出。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">一、"特权"特性的正常使用如下所示：</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">1、如果你不需要从"特权"块内返回一个值，按下列代码去做：</p>somemethod() {<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...normal code here...<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AccessController.doPrivileged(new PrivilegedAction() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object run() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // privileged code goes here, for example:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.loadLibrary("awt");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; returnnull; // nothing to return<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...normal code here...<br /><br />}<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><br />PrivilegedAction是一个接口，它带有一个被称为run的方法，这个方法返回一个Object。上述例子显示了一个用来实现那个接口的匿名内类的创建，并提供了一个run方法的具体实现。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">当做一个doPrivileged调用时，一个PrivilegedAction实现的实例被传递给它。doPrivileged方法在使特权生效后，从PrivilegedAction实现中调用run方法，并返回run方法的返回值以作为doPrivileged的返回值，这一点在本例中被忽略。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">2、如果你需要返回一个值，你可按如下方法去做：</p>somemethod() {<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...normal code here...<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String user = (String) AccessController.doPrivileged(new PrivilegedAction() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object run() {<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; return System.getProperty("user.name");<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; });<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...normal code here...<br /><br />}<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><br />3、如果用你的run方法执行的动作可能扔出一个"检查"的异常（包括在一个方法的throws子句列表中），则你需要使用PrivilegedExceptionAction接口，而不是使用PrivilegedAction接口：</p>somemethod() throws FileNotFoundException {<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...normal code here...<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileInputStream fis = (FileInputStream)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AccessController.doPrivileged(new PrivilegedExceptionAction() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object run() throws FileNotFoundException {<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;&nbsp;&nbsp; returnnew FileInputStream("someFile");<br />&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; });<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (PrivilegedActionException e) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // e.getException() should be an instance of<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // FileNotFoundException,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // as only "checked" exceptions will be "wrapped" in a<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // PrivilegedActionException.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw (FileNotFoundException) e.getException();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...normal code here...<br /><br />}<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">有关被授予特权的一些重要事项：<br />首先，这个概念仅存在于一个单独线程内。一旦特权代码完成了任务，特权将被保证清除或作废。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">第二，在这个例子中，在run方法中的代码体被授予了特权。然而，如果它调用无特权的不可信代码，则那个代码将不会获得任何特权；只有在特权代码具有许可并且在直到checkPermission调用的调用链中的所有随后的调用者也具有许可时, 一个许可才能被准予。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">二、使用事例：</p>final String name = MyClass.class.getName();<br />String className = AccessController.doPrivileged(new PrivilegedAction&lt;String&gt;() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public String run() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return System.getProperty(name);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />});关于AccessController.doPrivileged- -<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&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 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">来自不同的位置的代码可以由一个CodeSource对象描述其位置和签名证书。根据代码的CodeSource的不同，代码拥有不同的权限。例如所有Java SDK自带的代码都具有所有的权限，而Applet中的代码则具有非常受限的权限，用户编写的代码可以自己定制权限（通过SecurityManager）。<br />当执行一段代码时，这段代码的StackTrace包含了从Main开始所有正在被调用而且没有结束的方法。在这个调用过程中，很有可能出现跨多个不同的CodeSource的调用序列。由于CodeSource不同，这些代码通常拥有不同的权限集。只有所有途经的CodeSource都具有对应的权限集合时，当前正在运行的代码才能存取某个Resource。<br />而doPrivileged方法是对这个规则的一种补充。他类似于Unix中的setuid程序。Unix中的login程序必须访问password文件从而获得用户授权信息，但是用户不能随意的访问password文件。因此，login程序具有setuid位，它不管被哪个用户所调用，都具有root的权限。<br />调用doPrivileged的方法不管其StackTrace中其他方法的权限，而仅仅根据当前方法的权限来判断用户是否能访问某个resource。也即可以规定用户只能用某种预定的方式来访问其本来不能访问的resource。<br />使用doPrivileged方法和使用setuid位都有需要注意的地方，例如仅执行必要的操作。否则，可能带来安全上的问题。</p></span><img src ="http://www.blogjava.net/DLevin/aggbug/390637.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2012-11-02 01:04 <a href="http://www.blogjava.net/DLevin/archive/2012/11/02/390637.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring中集合定义</title><link>http://www.blogjava.net/DLevin/archive/2012/02/14/369971.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Tue, 14 Feb 2012 10:16:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2012/02/14/369971.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/369971.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2012/02/14/369971.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/369971.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/369971.html</trackback:ping><description><![CDATA[<p>习惯了把集合定义在一个类的字段中，今天遇到想重用集合的定义，竟然不知道单独的集合Bean应该怎么定义了，记之，以备后用。<br /><br />对Map来说，有一种比较搓的方法，就是直接用Map的构造函数：</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">SymbolMap</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">java.util.HashMap</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">constructor</span><span style="color: #000000">-</span><span style="color: #000000">arg</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">map</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">key</span><span style="color: #000000">&gt;&lt;</span><span style="color: #000000">value</span><span style="color: #000000">&gt;&lt;!</span><span style="color: #000000">[CDATA[us;djia]]</span><span style="color: #000000">&gt;&lt;/</span><span style="color: #000000">value</span><span style="color: #000000">&gt;&lt;/</span><span style="color: #000000">key</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">value</span><span style="color: #000000">&gt;&lt;!</span><span style="color: #000000">[CDATA[us</span><span style="color: #000000">&amp;</span><span style="color: #000000">dji]]</span><span style="color: #000000">&gt;&lt;/</span><span style="color: #000000">value</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">entry</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">map</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">constructor</span><span style="color: #000000">-</span><span style="color: #000000">arg</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">10</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">11</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span></div>
<p>另一种稍微简单的方法：</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">&nbsp;1</span><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">bean&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">emails</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">org.springframework.beans.factory.config.MapFactoryBean</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">property&nbsp;name</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">sourceMap</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">map</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">pechorin</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">pechorin@hero.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">raskolnikov</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">raskolnikov@slums.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">stavrogin</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">stavrogin@gov.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">porfiry</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">porfiry@gov.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">map</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">property</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">10</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">bean</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">11</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span></div>
<p>对这种方法，Sping还提供了ListFactoryBean, SetFactoryBean等类，这貌似是Spring的一个可扩展框架，可以待以后进一步研究这个框架的实现方式。<br />最简单的一种方式就是直接用spring中提供的util包：</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">util:map&nbsp;id</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">emails</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">2</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">pechorin</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">pechorin@hero.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">3</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">raskolnikov</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">raskolnikov@slums.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">4</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">stavrogin</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">stavrogin@gov.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">5</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">entry&nbsp;key</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">porfiry</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;value</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">porfiry@gov.org</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">6</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">util:map</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;&nbsp;<br /></span><span style="color: #008080">7</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span></div>
<p>使用改方法时，xml文件头需要使用：</p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080">1</span><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;xmlns:util</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/util</span><span style="color: #000000">"</span><span style="color: #000000"><br /></span><span style="color: #008080">2</span><span style="color: #000000"><img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;xsi:schemaLocation</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">http://www.springframework.org/schema/beans&nbsp;http://www.springframework.org/schema/beans/spring-beans.xsd</span><span style="color: #000000"><br /></span><span style="color: #008000">3<img align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http:</span><span style="color: #008000">//</span><span style="color: #008000">www.springframework.org/schema/util&nbsp;</span><span style="color: #008000; text-decoration: underline">http://www.springframework.org/schema/util/spring-util-2.5.xsd</span><span style="color: #008000">"&gt;</span></div>
<p><br />引用：<br /><a href="http://macrochen.iteye.com/blog/392616">http://macrochen.iteye.com/blog/392616</a><br /><a href="http://springindepth.com/book/in-depth-ioc-collections.html">http://springindepth.com/book/in-depth-ioc-collections.html</a><br /><br /><br />&nbsp;</p><img src ="http://www.blogjava.net/DLevin/aggbug/369971.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2012-02-14 18:16 <a href="http://www.blogjava.net/DLevin/archive/2012/02/14/369971.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[多问几个为什么]为什么匿名内部类中引用的局部变量和参数需要final而成员字段不用？</title><link>http://www.blogjava.net/DLevin/archive/2011/11/23/364599.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Tue, 22 Nov 2011 17:49:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/11/23/364599.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/364599.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/11/23/364599.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/364599.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/364599.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 昨天有一个比较爱思考的同事和我提起一个问题：为什么匿名内部类使用的局部变量和参数需要final修饰，而外部类的成员变量则不用？对这个问题我一直作为默认的语法了，木有仔细想过为什么（在分析完后有点印象在哪本书上看到过，但是就是没有找到，难道是我的幻觉？呵呵）。虽然没有想过，但是还是借着之前研究过字节码的基础上，分析了一些，感觉上是找到了一些答案，分享一下；也希望有大牛给指出一些不足的地方。假如我们有...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2011/11/23/364599.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/364599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-11-23 01:49 <a href="http://www.blogjava.net/DLevin/archive/2011/11/23/364599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>历程杂技</title><link>http://www.blogjava.net/DLevin/archive/2011/09/08/358246.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Wed, 07 Sep 2011 17:15:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/09/08/358246.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/358246.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/09/08/358246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/358246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/358246.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-size: 13px; line-height: 19px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif"> 
<h2 style="margin-top: 10px; font-size: 1em"><a id="ctl02_TitleUrl" style="color: #0066aa; text-decoration: none" href="http://www.cnblogs.com/wmj/archive/2010/06/21/1761961.html">为什么会抛出IllegalMonitorStateException？</a></h2></span><span class="Apple-style-span" style="font-size: 13px; line-height: 19px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif">
<p style="margin: 5px auto; text-indent: 0px"><span class="Apple-tab-span" style="line-height: 19px; white-space: pre"></span>在使用java线程的时候，我们有时候要调用wait，notifyAll，notify来等待或者唤醒线程，如果这几个方法没有包含在synchronized块中，将抛出IllegalMonitorStateException异常，并且当前线程被中断，为什么？</p>
<p style="margin: 5px auto; text-indent: 0px"><span class="Apple-tab-span" style="line-height: 19px; white-space: pre"></span>为什么？因为wait，notifyAll，notify被调用的时候，都要使用到对象的监视器（锁），但是，如果这些方法不被包含在synchronized块中，那么当前线程就获取不到对象的锁，那么当我们wait的时候，wait根本不知道该释放哪个锁，所以就会抛出不合法的锁异常。</p>
<p style="margin: 5px auto; text-indent: 0px"><span class="Apple-tab-span" style="line-height: 19px; white-space: pre"></span>为什么？sleep不需要&nbsp;被包含在synchronized块中呢？因为sleep不要释放锁，所以也就不抛出异常。</p></span><span class="Apple-style-span" style="font-size: 12px; line-height: 18px; font-family: Helvetica, Tahoma, Arial, sans-serif">
<h3 style="padding-right: 0px; padding-left: 0px; font-size: 16px; padding-bottom: 0px; margin: 0px 0px 0.5em; color: black; line-height: 1.5em; padding-top: 10px"><a style="color: #108ac6; text-decoration: underline" href="http://aoyi.iteye.com/blog/1151757">"Could not resolve placeholder"解决方案</a></h3></span><span class="Apple-style-span" style="line-height: 25px; font-family: Helvetica, Tahoma, Arial, sans-serif">　　除去properites文件路径错误、拼写错误外，出现"Could not resolve placeholder"很有可能是使用了多个PropertyPlaceholderConfigurer或者多个&lt;context:property-placeholder&gt;的原因。</span><br /><span class="Apple-style-span" style="line-height: 25px; font-family: Helvetica, Tahoma, Arial, sans-serif">在Spring 3.0中，可以写： 
<div style="display: inline-block"></div></span><span class="Apple-style-span" style="font-size: 12px; line-height: 25px; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace">
<ol class="dp-xml" style="border-right: #d1d7dc 1px solid; padding-right: 0px; border-top: #d1d7dc 1px solid; padding-left: 0px; font-size: 1em; padding-bottom: 2px; margin: 0px 0px 1px; border-left: #d1d7dc 1px solid; line-height: 1.4em; padding-top: 2px; border-bottom: #d1d7dc 1px solid; list-style-type: decimal; background-color: #ffffff"><li style="padding-right: 0px; padding-left: 10px; font-size: 1em; padding-bottom: 0px; margin: 0px 0px 0px 38px; border-left: #d1d7dc 1px solid; line-height: 18px; padding-top: 0px; background-color: #fafafa"><span class="tag" style="font-weight: bold; color: #006699">&lt;</span><span class="tag-name" style="font-weight: bold; color: #006699">context:property-placeholder</span><span style="color: black">&nbsp;</span><span class="attribute" style="color: red">location</span><span style="color: black">=</span><span class="attribute-value" style="color: blue">"xxx.properties"</span><span style="color: black">&nbsp;</span><span class="attribute" style="color: red">ignore-unresolvable</span><span style="color: black">=</span><span class="attribute-value" style="color: blue">"true"</span><span class="attribute-value">&nbsp;</span><span class="Apple-style-span" style="color: #000000"><span class="tag" style="font-weight: bold; color: #006699">/&gt;</span><span style="color: black">&nbsp;&nbsp;</span></span></li></ol></span><span class="Apple-style-span" style="line-height: 25px; font-family: Helvetica, Tahoma, Arial, sans-serif">在Spring 2.5中，&lt;context:property-placeholder&gt;没有ignore-unresolvable属性，此时可以改用PropertyPlaceholderConfigurer。其实&lt;context:property-placeholder location="xxx.properties"&nbsp;<span style="color: #ff0000">ignore-unresolvable="true"</span>&nbsp;/&gt;与下面的配置是等价的<br /></span><span class="Apple-style-span" style="font-size: 12px; line-height: 25px; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Consolas, 'Courier New', monospace">
<ol class="dp-j" style="border-right: #d1d7dc 1px solid; padding-right: 0px; border-top: #d1d7dc 1px solid; padding-left: 0px; font-size: 1em; padding-bottom: 2px; margin: 0px 0px 1px; border-left: #d1d7dc 1px solid; color: #2b91af; line-height: 1.4em; padding-top: 2px; border-bottom: #d1d7dc 1px solid; list-style-type: decimal; background-color: #ffffff"><li style="padding-right: 0px; padding-left: 10px; font-size: 1em; padding-bottom: 0px; margin: 0px 0px 0px 38px; border-left: #d1d7dc 1px solid; line-height: 18px; padding-top: 0px; background-color: #fafafa"><span style="color: black"><span style="color: black">&lt;bean&nbsp;id=</span><span class="string" style="color: blue">"随便"</span><span style="color: black">&nbsp;</span><span class="keyword" style="font-weight: bold; color: #7f0055">class</span><span style="color: black">=</span><span class="string" style="color: blue">"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"</span><span style="color: black">&gt;&nbsp;&nbsp;</span></span></li><li style="padding-right: 0px; padding-left: 10px; font-size: 1em; padding-bottom: 0px; margin: 0px 0px 0px 38px; border-left: #d1d7dc 1px solid; line-height: 18px; padding-top: 0px; background-color: #fafafa"><span style="color: black">&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=<span class="string" style="color: blue">"location"</span><span style="color: black">&nbsp;value=</span><span class="string" style="color: blue">"xxx.properties"</span><span style="color: black">&nbsp;/&gt;&nbsp;&nbsp;</span></span></li><li style="padding-right: 0px; padding-left: 10px; font-size: 1em; padding-bottom: 0px; margin: 0px 0px 0px 38px; border-left: #d1d7dc 1px solid; line-height: 18px; padding-top: 0px; background-color: #fafafa"><span style="color: black">&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name=<span class="string" style="color: blue">"ignoreUnresolvablePlaceholders"</span><span style="color: black">&nbsp;value=</span><span class="string" style="color: blue">"true"</span><span style="color: black">&nbsp;/&gt;&nbsp;&nbsp;&nbsp;</span></span></li><li style="padding-right: 0px; padding-left: 10px; font-size: 1em; padding-bottom: 0px; margin: 0px 0px 0px 38px; border-left: #d1d7dc 1px solid; line-height: 18px; padding-top: 0px; background-color: #fafafa"><span style="color: black">&lt;/bean&gt; &nbsp;</span></li></ol><br /><strong>用Spring JMS，在主线程退出后，进程没有退出情况：<br /></strong>今天写了一个关于Spring JMS的小程序，发现主线程退出后，但相应的Server进程却没有退出。用jconsole查看内部线程情况，发现还有好多线程并没有结束。如图：<img height="341" alt="" src="http://www.blogjava.net/images/blogjava_net/dlevin/threadinfo.PNG" width="898" border="0" longdesc="" /><br />在网上没有找到相关的资料，无意中看到貌似可以通过ClassPathXmlApplicationContext中的close()方法解决这个问题。对Spring和JMS其实都不算很了解，不知道这个方法是不是合适或者还有更好的方法，先记下，等以后有时间再好好研究研究。</span> <br /><br /><strong>Spring获取插入数据库时自增字段的值：<br /></strong>代码如下： 
<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"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;insertSubscriberRecord(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;websiteId,&nbsp;<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&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;String&nbsp;firstName,&nbsp;<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&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;String&nbsp;lastName,&nbsp;<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&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;String&nbsp;password,&nbsp;<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&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;String&nbsp;email)<br /><img id="Codehighlighter1_255_896_Open_Image" onclick="this.style.display='none'; Codehighlighter1_255_896_Open_Text.style.display='none'; Codehighlighter1_255_896_Closed_Image.style.display='inline'; Codehighlighter1_255_896_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_255_896_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_255_896_Closed_Text.style.display='none'; Codehighlighter1_255_896_Open_Image.style.display='inline'; Codehighlighter1_255_896_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"></span><span id="Codehighlighter1_255_896_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_255_896_Open_Text"><span style="color: #000000">{<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;Subscriber&nbsp;subscriber&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Subscriber(websiteId,&nbsp;firstName,&nbsp;lastName,&nbsp;password,&nbsp;email);<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;String&nbsp;insertFileString&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">INSERT&nbsp;INTO&nbsp;subscribers&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000"><br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">(website_id,&nbsp;first_name,&nbsp;last_name,&nbsp;password,&nbsp;email_address)&nbsp;VALUES&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000"><br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">(:websiteId,&nbsp;:firstName,&nbsp;:lastName,&nbsp;:password,&nbsp;:emailAddress)&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">;<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;see&nbsp;</span><span style="color: #008000; text-decoration: underline">http://static.springframework.org/spring/docs/2.5.x/reference/jdbc.html</span><span style="color: #008000"><br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;SqlParameterSource&nbsp;fileParameters&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;BeanPropertySqlParameterSource(subscriber);<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;KeyHolder&nbsp;keyHolder&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GeneratedKeyHolder();<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;getNamedParameterJdbcTemplate().update(insertFileString,&nbsp;fileParameters,&nbsp;keyHolder);<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;keyHolder.getKey().intValue();<br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br /><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div>参考：<a href="http://www.devdaily.com/blog/post/jdbc/spring-jdbc-insert-auto-generated-key">http://www.devdaily.com/blog/post/jdbc/spring-jdbc-insert-auto-generated-key</a> <br /><br />
<div class="" style="margin-top: 10px; margin-left: 10px; font-family: Arial, Helvetica, sans-serif; " hasbox="2"><font class="Apple-style-span" color="#ff6600" style="font-weight: bold; "><span>Print the Stack Trace of the Exception to a String
</span></font><div style="color: #ff6600; border-right-color: #cccccc; border-right-width: 1px; border-right-style: solid; padding-right: 5px; border-top-color: #cccccc; border-top-width: 1px; border-top-style: solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left-color: #cccccc; border-left-width: 1px; border-left-style: solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom-color: #cccccc; border-bottom-width: 1px; border-bottom-style: solid; background-color: #eeeeee; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff; ">import</span><span style="color: #000000; ">&nbsp;java.io.PrintWriter;<br /></span><span style="color: #008080; ">&nbsp;2</span><span style="color: #000000; "><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="color: #0000ff; ">import</span><span style="color: #000000; ">&nbsp;java.io.StringWriter;<br /></span><span style="color: #008080; ">&nbsp;3</span><span style="color: #000000; "><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" alt="" />&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;String&nbsp;getStackTrace(Throwable&nbsp;t)<br /></span><span style="color: #008080; ">&nbsp;4</span><span style="color: #000000; "><img id="Codehighlighter1_113_318_Open_Image" onclick="this.style.display='none'; Codehighlighter1_113_318_Open_Text.style.display='none'; Codehighlighter1_113_318_Closed_Image.style.display='inline'; Codehighlighter1_113_318_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_113_318_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_113_318_Closed_Text.style.display='none'; Codehighlighter1_113_318_Open_Image.style.display='inline'; Codehighlighter1_113_318_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_113_318_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif" alt="" /></span><span id="Codehighlighter1_113_318_Open_Text"><span style="color: #000000">{<br /></span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringWriter&nbsp;sw&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;StringWriter();<br /></span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrintWriter&nbsp;pw&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;PrintWriter(sw,&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">);<br /></span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.printStackTrace(pw);<br /></span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pw.flush();<br /></span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sw.flush();<br /></span><span style="color: #008080">10</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;sw.toString();<br /></span><span style="color: #008080">11</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000; "><br /></span><span style="color: #008080; ">12</span><span style="color: #000000; "><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" alt="" /></span></div><font class="Apple-style-span" color="#ff6600"><strong>最近在网上看到一个面试题：</strong><br /><div style="background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<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; ">Integer&nbsp;a&nbsp;</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>&nbsp;<span style="color: #000000; ">Integer&nbsp;b&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;a;<br /></span><span style="color: #008080; ">3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000ff; ">int</span><span style="color: #000000; ">&nbsp;c&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;b;<br />What will happen？答案当然是NullPointerException。但是为什么？查看以下代码：<br /><div><div>&nbsp; &nbsp; &nbsp;0 &nbsp;aconst_null</div><div>&nbsp; &nbsp; &nbsp;1 &nbsp;astore_1 [a]</div><div>&nbsp; &nbsp; &nbsp;2 &nbsp;aload_1 [a]</div><div>&nbsp; &nbsp; &nbsp;3 &nbsp;astore_2 [b]</div><div>&nbsp; &nbsp; &nbsp;4 &nbsp;aload_2 [b]</div><div>&nbsp; &nbsp; &nbsp;5 &nbsp;invokevirtual java.lang.Integer.intValue() : int [16]</div><div>&nbsp; &nbsp; &nbsp;8 &nbsp;istore_3 [c]<br />从字节码中我们可以看出，其实对于装箱和拆箱操作，都是编译器在其中做了支持，将int类型转换成Integer类型（调用Integer.valueOf()方法），或将Integer类型转换成int类型（调用Integer.intValue()方法）。</div></div></span></div>类在什么时候加载为题<br /><div style="background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Singleton&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">static</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;Singleton&nbsp;instance&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Singleton();<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">&nbsp;Singleton()&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"Singleton</span><span style="color: #000000; ">()</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;8</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;Singleton&nbsp;getInstance()&nbsp;{<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;instance;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">}<br />然后当我们有以下一句话：<br /><div>Singleton singleton = null;<br />or<br /><div>Singleton singleton;<br />此时类会加载吗？直观点，打印"Singleton()"这句话会被执行吗？答案是不会被执行，对第二句话还是好理解的，因为singleton实例根本没有被用到，若要用，首先要初始化所以编译器会最后忽略这句话，所以singleton变量不会出现在字节吗中。对第一句，singleton实例会出现在字节码中，并且会赋null的值，但是此时Singleton类还是没有被加载，那么此时singleton这个实例是什么类型呢？这点我有点想不通。或者Java的引用在内存中根本是没有类型的，保证类型安全是在编译器端做的，所以在给singleton实例赋null值得时候，只是表明singleton是一个指向null的引用而已，它并没有指向Singleton实例，所以此时Singleton类不需要加载，只有到真正使用到Singleton类的时候才会去加载Singleton类，并实例化instance成员。<br />这样就引出另一个问题：<br />有人说把初始化放在getInstance()方法中，会使instance在用到时才被加载，而不是刚开始程序初始化时就被加载，在C++中，这个确实是这样的，但是在Java中有必要这么做吗？从上述的分析中，我们可以看到，其实Java中根本没有必要，只要像上面一样写就可以了。</div></div></span></div><br /></font></div><img src ="http://www.blogjava.net/DLevin/aggbug/358246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-09-08 01:15 <a href="http://www.blogjava.net/DLevin/archive/2011/09/08/358246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的装箱与拆箱</title><link>http://www.blogjava.net/DLevin/archive/2011/07/20/354743.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Wed, 20 Jul 2011 15:09:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/07/20/354743.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/354743.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/07/20/354743.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/354743.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/354743.html</trackback:ping><description><![CDATA[<div><p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">在</span><span style="font-size:12.0pt">J2SE5.0</span><span style="font-size:12.0pt; font-family:宋体;">后推出了自动装箱和拆箱的功能，以提高我们的开发效率，然而自动装箱和拆箱实际上是通过编译器来支持的（并非语言本身，或者说虚拟机），因而这种支持也隐藏了部分内部实质，再加上某些类的优化（比如</span><span style="font-size:12.0pt">Integer</span><span style="font-size:12.0pt; font-family:宋体;">里面的缓存等，参看<strong>关于缓存</strong>节），就更加容易在特定的环境下产生问题，并且如果不知道原来还无法调试。以下先是简单的介绍了编译器对装箱和拆箱的实现，并根据实现简单介绍一下可能会遇到的几个问题。</span></p>  <h2><span style="font-family:宋体;">装箱和拆箱实现</span></h2>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">以下装箱和拆箱代码：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"></span></font></p><font class="Apple-style-span" face="'Courier New'" size="3"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp; &nbsp; &nbsp; Object&nbsp;value&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;intValue&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(Integer)value;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;newIntValue&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Integer(</span><span style="color: #000000; ">10</span><span style="color: #000000; ">);</span></div></font><p>&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">编译成字节码如下：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;bipush 10</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp; <strong>&nbsp;&nbsp;2&nbsp;invokestatic java.lang.Integer.<span style="background:yellow;">valueOf(int)</span> : java.lang.Integer [20]</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;astore_1 [value]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;aload_1 [value]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;checkcast java.lang.Integer [21]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 10&nbsp;invokevirtual java.lang.Integer<span style="background:yellow;">.intValue()</span> : int [26]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 13&nbsp;istore_2 [intValue]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; <strong>14&nbsp;new java.lang.Integer [21]</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp; &nbsp;17&nbsp;dup</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 18&nbsp;bipush 10</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; <strong>20&nbsp;invokespecial java.lang.Integer(int) [30]</strong></span></p>  <p align="left" style="text-align:left;"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 23&nbsp;astore_3 [newIntValue]</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">从以上字节码可以看到</span><span style="font-size:12.0pt">10</span><span style="font-size:12.0pt; font-family:宋体;">首先调用</span><span style="font-size:12.0pt">valueOf</span><span style="font-size:12.0pt; font-family:宋体;">方法转换为</span><span style="font-size:12.0pt">Integer</span><span style="font-size:12.0pt; font-family:宋体;">实例，再赋值该</span><span style="font-size:12.0pt">value</span><span style="font-size:12.0pt;font-family: 宋体;">，而</span><span style="font-size: 12.0pt">value</span><span style="font-size:12.0pt;font-family:宋体;">强制转换成</span><span style="font-size:12.0pt">Integer</span><span style="font-size:12.0pt; font-family:宋体;">类后，会调用</span><span style="font-size:12.0pt">intValue</span><span style="font-size:12.0pt; font-family:宋体;">方法，后赋值给</span><span style="font-size:12.0pt">intValue</span><span style="font-size:12.0pt; font-family:宋体;">。这就是用编译器来实现装箱和拆箱。</span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <h2><span style="font-family:宋体;">奇怪的</span>NullPointerException</h2>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">查看以下代码：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"></span></font></p><font class="Apple-style-span" face="'Courier New'" size="3"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp; &nbsp; &nbsp; Integer&nbsp;value&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;intValue&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;value;</span></div></font><p>&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">可以编译通过，但是运行的时候却会发生</span><span style="font-size:12.0pt">NullPointerException</span><span style="font-size:12.0pt;font-family:宋体;">。这是由什么引起的呢？依然看一下字节码就可以了：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;aconst_null</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;astore_1 [value]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;aload_1 [value]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;<strong>&nbsp;&nbsp;&nbsp;3&nbsp;invokevirtual java.lang.Integer.<span style="background:yellow;">intValue()</span> : int [20]</strong></span></p>  <p align="left" style="text-align:left;"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;istore_2 [intValue]</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">从字节码中可以看到，从</span><span style="font-size:12.0pt">value</span><span style="font-size:12.0pt; font-family:宋体;">赋值该</span><span style="font-size:12.0pt">intValue</span><span style="font-size:12.0pt; font-family:宋体;">事实上是直接在</span><span style="font-size:12.0pt">value</span><span style="font-size:12.0pt;font-family: 宋体;">实例上调用</span><span style="font-size:12.0pt">intValue</span><span style="font-size:12.0pt; font-family:宋体;">函数。</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">对当前代码，我们可以一眼就看出当前</span><span style="font-size:12.0pt">value</span><span style="font-size:12.0pt; font-family:宋体;">是</span><span style="font-size:12.0pt">null</span><span style="font-size:12.0pt;font-family: 宋体;">的问题，但是如果这个</span><span style="font-size:12.0pt">null</span><span style="font-size:12.0pt;font-family: 宋体;">是在很远以外的地方赋值的呢？或者是间接赋值呢？这个时候遇到这种问题就会比较诡异了。</span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <h2><span style="font-family:宋体;">相等与不相等问题</span></h2>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">查看一下代码：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"></span></font></p><font class="Apple-style-span" face="'Courier New'" size="3"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp; &nbsp; &nbsp; Integer&nbsp;value1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">100</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;value2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">100</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">value1&nbsp;==&nbsp;value2&nbsp;is&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(value1&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;value2));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;value3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">200</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;value4&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">200</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">value3&nbsp;==&nbsp;value4&nbsp;is&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(value3&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;value4));</span></div></font><p>&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">这段代码会是什么结果？</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">value1 == value2 is <span style="background:yellow;">true</span></span></p>  <p align="left" style="text-align:left;"><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;">value3 == value4 is <span style="background:yellow;">false</span></span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">两段代码就是值不一样，其他的都一样，竟然会有区别？这个奥妙就因为装箱过程中调用的是</span><span style="font-size:12.0pt">valueOf</span><span style="font-size:12.0pt; font-family:宋体;">方法，而</span><span style="font-size:12.0pt">valueOf</span><span style="font-size:12.0pt; font-family:宋体;">方法对值在</span><span style="font-size:12.0pt">-128</span><span style="font-size:12.0pt;font-family: 宋体;">到</span><span style="font-size: 12.0pt">127</span><span style="font-size:12.0pt;font-family:宋体;">之间的数值缓存了（参见关于缓存一节），因而</span><span style="font-size:12.0pt">value1</span><span style="font-size:12.0pt; font-family:宋体;">和</span><span style="font-size:12.0pt">value2</span><span style="font-size:12.0pt;font-family: 宋体;">的引用是相同的，而</span><span style="font-size:12.0pt">value3</span><span style="font-size:12.0pt;font-family: 宋体;">和</span><span style="font-size: 12.0pt">value4</span><span style="font-size:12.0pt;font-family:宋体;">的引用是不一样的，而</span><span style="font-size:12.0pt">==</span><span style="font-size:12.0pt; font-family:宋体;">比较的是引用，因而才会出现以上的结果。</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">这确的做法应该是：</span></p>  <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp; &nbsp; &nbsp; Integer&nbsp;value1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">100</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;value2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">100</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">value1&nbsp;==&nbsp;value2&nbsp;is&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(value1.equals(value2)));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;value3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">200</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Integer&nbsp;value4&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">200</span><span style="color: #000000; ">;<br /></span></div><p align="left" style="text-align:left;text-autospace:none"><span class="Apple-style-span" style="font-size: 13px; "><span style="color: #000000; ">&nbsp;&nbsp; &nbsp; &nbsp; System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">value3&nbsp;==&nbsp;value4&nbsp;is&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(value3.equals(value4)));</span></span>&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">这样的结果就是预料的结果了：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">value1 == value2 is true</span></p>  <p align="left" style="text-align:left;"><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;">value3 == value4 is true</span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">所以我们要慎用&#8220;</span><span style="font-size:12.0pt">==</span><span style="font-size:12.0pt; font-family:宋体;">&#8221;操作符。</span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <h2>String<span style="font-family:宋体;">中的相等与不等</span></h2>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">在</span><span style="font-size:12.0pt">String</span><span style="font-size:12.0pt; font-family:宋体;">中也有类似的情况，查看一下代码：</span></p>  <p align="left" style="text-align: left; "><font class="Apple-style-span" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px; "></span></font></p><font class="Apple-style-span" face="'Courier New'" size="3"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp; &nbsp; &nbsp; String&nbsp;str1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">str1&nbsp;==&nbsp;str2&nbsp;is&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(str1&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;str2));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;String(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;str4&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;String(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">str3&nbsp;==&nbsp;str4&nbsp;is&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;(str3&nbsp;</span><span style="color: #000000; ">==</span><span style="color: #000000; ">&nbsp;str4));</span></div></font><p>&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">执行结果：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">str1 == str2 is <span style="background:yellow;">true</span></span></p>  <p align="left" style="text-align:left;"><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;">str3 == str4 is <span style="background:yellow;">false</span></span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">这是因为</span><span style="font-size:12.0pt">str1</span><span style="font-size:12.0pt; font-family:宋体;">和</span><span style="font-size:12.0pt">str2</span><span style="font-size:12.0pt;font-family: 宋体;">使用的是同一个字符串，即在字符常量中的字符串，而</span><span style="font-size:12.0pt">str3</span><span style="font-size:12.0pt; font-family:宋体;">和</span><span style="font-size:12.0pt">str4</span><span style="font-size:12.0pt;font-family: 宋体;">在使用字符常量中的字符为参数又创建出了两个新的字符串对象，因而在引用比较情况下是不等的。我们可以从字节码中得到这些信息（删除打印的代码）：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp; <strong>&nbsp;&nbsp;0&nbsp;ldc &lt;String "abc"&gt; [20]</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp;astore_1 [<span style="background:yellow;">str1</span>]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;ldc &lt;String "abc"&gt; [20]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp;astore_2 [str2]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 6&nbsp;new java.lang.String [22]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;dup</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 10&nbsp;ldc &lt;String "abc"&gt; [20]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 12&nbsp;invokespecial java.lang.<span style="background:yellow;">String(java.lang.String)</span> [24]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 15&nbsp;astore_3 [<span style="background:yellow;">str3</span>]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 16&nbsp;new java.lang.String [22]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 19&nbsp;dup</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp; &nbsp;20&nbsp;ldc &lt;String "abc"&gt; [20]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 22&nbsp;invokespecial java.lang.String(java.lang.String) [24]</span></p>  <p align="left" style="text-align:left;"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 25&nbsp;astore 4 [str4]</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">正确的做法还是调用</span><span style="font-size:12.0pt">equals</span><span style="font-size:12.0pt; font-family:宋体;">方法，而不是使用&#8220;</span><span style="font-size:12.0pt">==</span><span style="font-size:12.0pt;font-family: 宋体;">&#8221;操作符。</span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <h2><span style="font-family:宋体;">关于缓存</span></h2>  <p><span style="font-size:12.0pt;font-family:宋体;">据目前信息，有缓存的类有：</span><span style="font-size:12.0pt">Byte</span><span style="font-size:12.0pt; font-family:宋体;">、</span><span style="font-size:12.0pt">Short</span><span style="font-size:12.0pt;font-family: 宋体;">、</span><span style="font-size: 12.0pt">Integer</span><span style="font-size:12.0pt;font-family:宋体;">、</span><span style="font-size:12.0pt">Long</span><span style="font-size:12.0pt; font-family:宋体;">以及</span><span style="font-size:12.0pt">Boolean</span><span style="font-size:12.0pt; font-family:宋体;">类。而这种缓存也只是在调用</span><span style="font-size:12.0pt">valueOf</span><span style="font-size:12.0pt; font-family:宋体;">（静态）方法的时候才会存在（装箱正是调用了</span><span style="font-size:12.0pt">valueOf</span><span style="font-size:12.0pt; font-family:宋体;">方法）。对整型，缓存的值都是</span><span style="font-size:12.0pt">-128</span><span style="font-size:12.0pt; font-family:宋体;">到</span><span style="font-size:12.0pt">127</span><span style="font-size:12.0pt;font-family: 宋体;">（包括</span><span style="font-size: 12.0pt">-128</span><span style="font-size:12.0pt;font-family:宋体;">和</span><span style="font-size:12.0pt">127</span><span style="font-size:12.0pt; font-family:宋体;">）之间，其他值都不缓存，而对</span><span style="font-size:12.0pt">Boolean</span><span style="font-size:12.0pt; font-family:宋体;">类型只有</span><span style="font-size:12.0pt">true</span><span style="font-size:12.0pt;font-family: 宋体;">和</span><span style="font-size: 12.0pt">false</span><span style="font-size: 12pt; font-family: 宋体; ">值。代码如下：<br /><font class="Apple-style-span" color="#0000FF" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px; "><strong><font class="Apple-style-span" color="#000000" face="宋体" size="4"><span class="Apple-style-span" style="font-size: 16px; font-weight: normal; "></span></font></strong></span></font></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><font class="Apple-style-span" color="#0000FF" face="'Courier New'" size="3"><font class="Apple-style-span" color="#000000" face="宋体" size="4"><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">class</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;Integer&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">extends</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;Number&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">static</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;Integer&nbsp;valueOf(</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">int</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;i)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">if</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">(i&nbsp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&gt;=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">-</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">128</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&amp;&amp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;i&nbsp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&lt;=</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;IntegerCache.high)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">return</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;IntegerCache.cache[i&nbsp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">128</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">else</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">new</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;Integer(i);<br /></span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">}<br /></span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">class</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;Boolean&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">static</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;Boolean&nbsp;valueOf(</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">boolean</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;b)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-size: 8pt; font-family: Verdana; ">return</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;(b&nbsp;</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">?</span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;TRUE&nbsp;:&nbsp;FALSE);<br /></span><span style="color: #000000; font-size: 8pt; font-family: Verdana; ">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #000000; font-size: 8pt; font-family: Arial; "></span><span style="color: #000000; font-size: 8pt; "><br /></span></font></font></div><font class="Apple-style-span" color="#0000FF" face="'Courier New'" size="3"><strong><font class="Apple-style-span" color="#000000" face="宋体" size="4"><br /><br />2011-01-05<br /><br /></font></strong></font><p>&nbsp;</p><p>&nbsp;</p></div><img src ="http://www.blogjava.net/DLevin/aggbug/354743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-07-20 23:09 <a href="http://www.blogjava.net/DLevin/archive/2011/07/20/354743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat中Jsp使用没有命名空间类的问题</title><link>http://www.blogjava.net/DLevin/archive/2011/07/20/354742.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Wed, 20 Jul 2011 15:08:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/07/20/354742.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/354742.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/07/20/354742.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/354742.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/354742.html</trackback:ping><description><![CDATA[<div><p><strong><span style="font-family:宋体;">问题重现：</span></strong></p>  <p><span style="font-family:宋体;">今天一刚开始学</span>Java<span style="font-family:宋体;">的同学在接触</span>Jsp<span style="font-family:宋体;">的时候遇到了一个比较诡异的问题，他在</span>JSP<span style="font-family:宋体;">中始终无法使用自己写的类。简单的演示问题代码：</span></p>  <p align="left" style="text-align:left;text-autospace:none">&nbsp;</p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;">//</span></strong><strong><span style="font-size:10.0pt;font-family:宋体;Courier New&quot;;Courier New&quot;;Courier New&quot;;">没有定义包名</span></strong><strong></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;"> MyDefaultClass {</span></p>  <p><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:black;">}</span></p>  <p>&nbsp;</p>  <p><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;">//index.jsp</span></strong><strong><span style="font-size:10.0pt;font-family:宋体;Courier New&quot;;Courier New&quot;;Courier New&quot;;color:black;">文件</span></strong><strong></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:#BF5F3F;">&lt;%@</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;"> <span style="color:#3F7F7F">page</span> <span style="color:#7F007F">language</span><span style="color:black">=</span><em><span style="color:#2A00FF">"java"</span></em> <span style="color:#7F007F">contentType</span><span style="color:black">=</span><em><span style="color:#2A00FF">"text/html; charset=ISO-8859-1"</span></em></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;">&nbsp;&nbsp;&nbsp; <span style="color:#7F007F">pageEncoding</span><span style="color:black">=</span><em><span style="color:#2A00FF">"ISO-8859-1"</span></em><span style="color:#BF5F3F">%&gt;</span></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:teal;">&lt;!</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">DOCTYPE</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;"> <span style="color:teal">html</span> <span style="color:gray">PUBLIC</span> <span style="color:teal">"-//W3C//DTD HTML 4.01 Transitional//EN"</span> <span style="color:#3F7F5F">"http://www.w3.org/TR/html4/loose.dtd"</span><span style="color:teal">&gt;</span></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:teal;">&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">html</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&gt;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:teal;">&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">head</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&gt;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:teal;">&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">title</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&gt;</span><span style="font-size: 10.0pt;font-family:&quot;Courier New&quot;;color:black;">Insert title here</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&lt;/</span><span style="font-size: 10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">title</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:teal;">&gt;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:teal;">&lt;/</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">head</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&gt;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:teal;">&lt;</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">body</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&gt;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:#BF5F3F;">&lt;%</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp; <strong>MyDefaultClass cls = </strong></span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">new</span></strong><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;"> MyDefaultClass();</span></strong><strong></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:#BF5F3F;">%&gt;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">Load successful</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:teal;">&lt;/</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">body</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&gt;</span></p>  <p><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:teal;">&lt;/</span><span style="font-size: 10.0pt;font-family:&quot;Courier New&quot;;color:#3F7F7F;">html</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:teal;">&gt;</span></p>  <p><strong>&nbsp;</strong></p>  <p><strong><span style="font-family:宋体;">出现的错误提示：</span></strong></p>  <p><strong>type</strong> Exception report</p>  <p><strong>message</strong> </p>  <p><strong>description</strong><span> <u>The server encountered an internal error () that prevented it from fulfilling this request.</u></span></p>  <p><strong>exception</strong> </p>  <p><span>org.apache.jasper.JasperException: Unable to compile class for JSP: </span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">An error occurred at line: 12 in the jsp file: /index.jsp</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">MyDefaultClass cannot be resolved to a type</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">9: &lt;body&gt;</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">10: </span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">11: &lt;%</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">12: &nbsp;&nbsp;&nbsp; MyDefaultClass cls = new MyDefaultClass();</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">13: %&gt;</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">14: </span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">15: Load successful</span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">An error occurred at line: 12 in the jsp file: /index.jsp</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">MyDefaultClass cannot be resolved to a type</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">9: &lt;body&gt;</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">10: </span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">11: &lt;%</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">12: &nbsp;&nbsp;&nbsp; MyDefaultClass cls = new MyDefaultClass();</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">13: %&gt;</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">14: </span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">15: Load successful</span></p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;">&nbsp;</p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">Stacktrace:</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:439)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.compiler.Compiler.compile(Compiler.java:349)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.compiler.Compiler.compile(Compiler.java:327)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.compiler.Compiler.compile(Compiler.java:314)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:592)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:317)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)</span></p>  <p align="left" style="text-align:left;"><span style="font-size:12.0pt;font-family:宋体;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; javax.servlet.http.HttpServlet.service(HttpServlet.java:717)</span></p>  <p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">解决方案：</span></strong></p>  <p><span style="font-family:宋体;">为什么要特别提示他是刚开始接触</span>Java<span style="font-family:宋体;">呢？因为我是想强调一下他没有定义包名的习惯，所以才会出现这个问题，<strong>而在</strong></span><strong>Java</strong><strong><span style="font-family:宋体;">中不定义包名是一个非常不好的编程习惯。</span></strong><span style="font-family:宋体;">这个问题本身是可以通过定义自己的包名，然后在</span>JSP<span style="font-family:宋体;">文件中导入自己的包解决。</span></p>  <p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">问题原因：</span></strong></p>  <p><span style="font-family:宋体;">由于</span>JSP<span style="font-family:宋体;">文件在请求时动态的生成</span>Servlet<span style="font-family:宋体;">类，然后动态的编译新生成的</span>Servlet<span style="font-family:宋体;">类，并加载新编译出的</span>Servlet<span style="font-family:宋体;">的</span>class<span style="font-family:宋体;">文件，运行相应的</span>service<span style="font-family:宋体;">方法，返回结果给客户端。根据栈信息可以知道问题出在了动态编译</span>Servlet<span style="font-family:宋体;">类的时候，而且是说</span>MyDefaultClass<span style="font-family:宋体;">无法被解析。</span></p>  <p><span style="font-family:宋体;">所以我猜测，可能是</span>Tomcat<span style="font-family:宋体;">在解析</span>JSP<span style="font-family:宋体;">文件的时候，没有发现有用户导入的类型（没有使用命名空间，因而无法导入包，也不需要加包名的前缀，导致</span>Tomcat<span style="font-family:宋体;">在解析</span>JSP<span style="font-family:宋体;">文件的时候无法自动感知到当前是引用了用户自定义的类的；也导致在编译的时候却能通过），所以在动态编译的时候没有设置</span>ClassPath<span style="font-family:宋体;">的值，然后导致了这个问题。然而对于这个&#8220;</span>Bug<span style="font-family:宋体;">&#8221;，</span>Tomcat<span style="font-family:宋体;">本身应该不会想不到，何况从逻辑上，默认的把</span>/classes<span style="font-family:宋体;">和</span>/lib<span style="font-family:宋体;">的目录加入到</span>ClassPath<span style="font-family:宋体;">中去编译动态生成的</span>Servlet<span style="font-family:宋体;">类也是合理的，那么</span>Tomcat<span style="font-family:宋体;">为什么要这样做呢？我的猜测可能会有两点吧：</span>1. Tomcat<span style="font-family:宋体;">也认为不定义包名是非常不好的习惯，因而故意留下这个缺陷，以惊醒编程人员。</span>2. <span style="font-family:宋体;">也有可能是出于性能的考虑，如果不加</span>ClassPath<span style="font-family:宋体;">应该是可以提升编译动态生成的</span>Servlet<span style="font-family:宋体;">类的速度的，因而只要不需要</span>ClassPath<span style="font-family:宋体;">的情况下，默认就不加。<br /><br />2010-09-22</span></p></div><img src ="http://www.blogjava.net/DLevin/aggbug/354742.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-07-20 23:08 <a href="http://www.blogjava.net/DLevin/archive/2011/07/20/354742.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse中异常断点问题</title><link>http://www.blogjava.net/DLevin/archive/2011/07/20/354741.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Wed, 20 Jul 2011 15:07:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/07/20/354741.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/354741.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/07/20/354741.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/354741.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/354741.html</trackback:ping><description><![CDATA[<p><span style="font-family:宋体;">之前在</span>.NET<span style="font-family:宋体;">平台下，</span>VS<span style="font-family:宋体;">提供的异常断点的工具给我在工作中帮了不好忙，特别是在出问题调试时，给我节省了不少时间。最近开始用</span>Eclipse<span style="font-family:宋体;">学习</span>Java<span style="font-family:宋体;">，对异常断点的功能很是怀念，也没有在网上找到过相关资料说</span>Eclipse<span style="font-family:宋体;">也提供了类似的功能，很是郁闷。今天这个功能终于被我找到了。</span></p>  <p><strong><span style="font-family:宋体;">在</span>Eclipse</strong><strong><span style="font-family:宋体;">中的&#8220;</span>Run</strong><strong><span style="font-family:宋体;">&#8221;中的&#8220;</span><span>Add Java Exception Breakpoint&#8230;</span></strong><strong><span style="font-family:宋体;">&#8221;项</span></strong><span style="font-family:  宋体;">，选择要断住的抛出异常类型即可。</span></p>  <p><img src="http://www.blogjava.net/images/blogjava_net/dlevin/Exception.png" border="0" alt="" width="558" height="466" /></p>  <p><span style="font-family:宋体;">在这里选择的</span>Exception<span style="font-family:宋体;">类型可以在</span>Breakpoint<span style="font-family:宋体;">窗口中查看或取消：</span></p>  <p><img src="http://www.blogjava.net/images/blogjava_net/dlevin/breakpoints.png" width="324" height="375" alt="" /><br /><br />2010-10-03</p><img src ="http://www.blogjava.net/DLevin/aggbug/354741.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-07-20 23:07 <a href="http://www.blogjava.net/DLevin/archive/2011/07/20/354741.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse中ClassPath问题</title><link>http://www.blogjava.net/DLevin/archive/2011/07/20/354740.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Wed, 20 Jul 2011 15:00:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/07/20/354740.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/354740.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/07/20/354740.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/354740.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/354740.html</trackback:ping><description><![CDATA[<div><p><span style="font-family:宋体;">今天发现把</span>jar<span style="font-family:宋体;">文件或</span>.class<span style="font-family:宋体;">文件放在系统配置的</span>CLASSPATH<span style="font-family:宋体;">目录下，然而在</span>eclipse<span style="font-family:宋体;">的工程中却是无法加载的</span>(<span style="font-family:宋体;">通过</span>ClassLoader<span style="font-family:宋体;">去加载相应的类</span>)<span style="font-family:宋体;">。最后我发现</span>eclipse<span style="font-family:宋体;">应该是重新设置了</span>CLASSPATH<span style="font-family:宋体;">的值了，也正因为这样它才能运行其</span>bin<span style="font-family:宋体;">目录下的文件。如打开工程目录下的</span>.classpath<span style="font-family:宋体;">文件：</span></p>  <p><span>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></p>  <p>&lt;classpath&gt;</p>  <p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="src" path="src"/&gt;</span></p>  <p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/&gt;</span></p>  <p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="/DomainInterfaces/bin"/&gt;</span></p>  <p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="output" path="bin"/&gt;</span></p>  <p>&lt;/classpath&gt;</p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">然而如果加入一下内容：</span></p>  <p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpathentry kind="lib" path="E:\\CodeRepository\\Java\\ExtClassPath" /&gt;</span></p>  <p><span style="font-family:宋体;">重启</span>eclipse<span style="font-family:宋体;">，就可以正确的加载</span>CLASSPATH<span style="font-family:宋体;">中的内容了。</span></p>  <p><br />2011-09-16</p></div><img src ="http://www.blogjava.net/DLevin/aggbug/354740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-07-20 23:00 <a href="http://www.blogjava.net/DLevin/archive/2011/07/20/354740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通过final变量实现条件编译</title><link>http://www.blogjava.net/DLevin/archive/2011/07/20/354670.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Tue, 19 Jul 2011 16:23:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/07/20/354670.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/354670.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/07/20/354670.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/354670.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/354670.html</trackback:ping><description><![CDATA[<div><p><strong><span style="font-family:宋体;">首先来比较两段代码所产生的中间代码：</span></strong></p>  <p>&nbsp;<span class="Apple-style-span" style="font-size: 13px; "><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;AppConfig&nbsp;{</span></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><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; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;debug&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />}<br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;DebugCode&nbsp;{<br />&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 />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(AppConfig.debug)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Some&nbsp;debug&nbsp;information</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div>  <p><strong>DebugCode</strong><strong><span style="font-family:宋体;">的中间代码（部分）：</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">public class org.levin.insidejvm.miscs.DebugCode {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public static void main(java.lang.String[] args);</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;getstatic java.lang.System.out : java.io.PrintStream [16]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 3&nbsp;ldc &lt;String "Some debug information"&gt; [22]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 5&nbsp;invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 8&nbsp;return</span></strong></p>  <p><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">}</span></p>  <p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;AppConfig&nbsp;{<br />&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; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">boolean</span><span style="color: #000000; ">&nbsp;debug&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br />}<br /></span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;ReleaseCode&nbsp;{<br />&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 />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(AppConfig.debug)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Some&nbsp;debug&nbsp;information</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><p>&nbsp;</p>  <p>&nbsp;</p>  <p><strong>ReleaseCode</strong><strong><span style="font-family:宋体;">中间代码（部分）：</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">public class org.levin.insidejvm.miscs.ReleaseCode {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public static void main(java.lang.String[] args);</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;return</span></strong></p>  <p><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">}</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">在上面的代码中，很明显</span>DebugCode<span style="font-family:宋体;">和</span>ReleaseCode<span style="font-family:宋体;">中的代码是一样的，只是</span><strong>AppConfig.debug</strong><strong><span style="font-family:宋体;">的值不一样而已</span></strong><span style="font-family:宋体;">，却产生了不同的中间代码，即编译器在</span>AppConfig.debug<span style="font-family:宋体;">为</span>false<span style="font-family:宋体;">的时候直接忽略了</span>if<span style="font-family:宋体;">中的语句。利用这个特性，我们就可以根据配置来实现条件编译，从而实现不同的条件产生不同的中间代码而不只是不同的运行结果。</span></p>  <p><strong>&nbsp;</strong></p>  <p><strong><span style="font-family:宋体;">然而在这里为什么会出现这样的行为呢？</span></strong></p>  <p><span style="font-family:宋体;">这是因为编译器对</span>final<span style="font-family:宋体;">修饰的基本类型和</span>String<span style="font-family:宋体;">类型的变量，在编译时解析为一个本地拷贝，这样拷贝导致编译器在编译的时候明确的知道</span>ReleaseCode<span style="font-family:宋体;">的那一段</span>if<span style="font-family:宋体;">语句是不会被执行的，因而可以对其做优化。而这种替换的结果也使得用</span>final<span style="font-family:宋体;">修饰的</span>int<span style="font-family:宋体;">变量可以出现在</span>switch-case<span style="font-family:宋体;">语句中。</span></p>  <p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">这种方式的缺陷</span></strong></p>  <p><span style="font-family:宋体;">这种方式的缺陷在于要现实该机制的条件编译，在改变</span>AppConfig.debug<span style="font-family:宋体;">中的值时，需要同时对</span>AppConfig<span style="font-family:宋体;">类和</span>ReleaseCode<span style="font-family:宋体;">类进行编译（即不能只编译</span>AppConfig<span style="font-family:宋体;">类）。</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">参考：《深入</span>Java<span style="font-family: 宋体; ">虚拟机（第二版）》第八章 <br />2010-09-22</span></p></div><img src ="http://www.blogjava.net/DLevin/aggbug/354670.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-07-20 00:23 <a href="http://www.blogjava.net/DLevin/archive/2011/07/20/354670.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>equals方法实现小记</title><link>http://www.blogjava.net/DLevin/archive/2011/06/29/353379.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Wed, 29 Jun 2011 11:05:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/06/29/353379.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/353379.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/06/29/353379.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/353379.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/353379.html</trackback:ping><description><![CDATA[&nbsp;&nbsp; &nbsp;最近做项目，在一次写equals方法时突然悟出了一些心得，小记之，以备后用。在《Effective Java（第二版）》的Item7中提出我们要尽量避免重新equals方法，他同时也列举了几种我们不需要实现equals方法的情况：<br />1）类的每个实例从本质上来说是唯一的，如Thread类的实例。<br />2）我们并不会用到该类的equals方法，如Random类，虽然可以比较两个Random的实例，以判断两个实例是否可以产生相同的随机数，设计者认为这样的需求用到的场合很少，因而就没有重写equals方法。<br />3）父类已经实现了equals方法，并且父类实现方式和子类实现方式是一样的，如大部分的Set实现的equals方法使用AbstractSet类提供的equals方法，List实现则使用AbstractList，Map实现使用AbstractMap的。<br />4）一个private类或package-private类，我们自己可以确保我们不会使用到它们的equals方法。<br />同时书也提出一般只有值类型的类才需要实现equals方法，像Date、Integer、Order（作为bean来使用）等。<br />另外，我们在实现equals方法是也要遵循以下几个原则：<br />1）自反性（reflexive）：x.equals(x)＝＝true<br />2）对称性（symmetric）：x.equals(y)==y.equals(x)<br />3）传递性（transitive）：若x.equals(y)==true, y.equals(z)==true,则x.equals(z)==true。<br />4）一致性（consistent）：多次调用x.equals(y)的结果应该是一样的。<br />5）对任何非null实例x，x.equals(null)＝＝false。<br /><br />根据这些特性，我们可以写出如下代码：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><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;Customer&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Serializable&nbsp;{<br /></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">long</span><span style="color: #000000;">&nbsp;serialVersionUID&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1L</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;id;<br /></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;name;<br /></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;String&nbsp;role;<br /></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Override<br /></span><span style="color: #008080;">&nbsp;9</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;">boolean</span><span style="color: #000000;">&nbsp;equals(Object&nbsp;obj)&nbsp;{<br /></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(obj&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br /></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;obj)&nbsp;{<br /></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<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;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(!(obj&nbsp;</span><span style="color: #0000ff;">instanceof</span><span style="color: #000000;">&nbsp;Customer))&nbsp;{<br /></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Customer&nbsp;other&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(Customer)obj;<br /></span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(ObjectUtils.equals(id,&nbsp;other.id)&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;<br /></span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectUtils.equals(name,&nbsp;other.name)&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;"><br /></span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ObjectUtils.equals(role,&nbsp;other.role));<br /></span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getId()&nbsp;{<br /></span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;id;<br /></span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">31</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;setId(String&nbsp;id)&nbsp;{<br /></span><span style="color: #008080;">32</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.id&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;id;<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;String&nbsp;getName()&nbsp;{<br /></span><span style="color: #008080;">35</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;name;<br /></span><span style="color: #008080;">36</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">37</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;setName(String&nbsp;name)&nbsp;{<br /></span><span style="color: #008080;">38</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.name&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;name;<br /></span><span style="color: #008080;">39</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">40</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;String&nbsp;getRole()&nbsp;{<br /></span><span style="color: #008080;">41</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;role;<br /></span><span style="color: #008080;">42</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">43</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;setRole(String&nbsp;role)&nbsp;{<br /></span><span style="color: #008080;">44</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">.role&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;role;<br /></span><span style="color: #008080;">45</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">46</span>&nbsp;<span style="color: #000000;">}</span></div>其中ObjectUtils类的代码如下：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><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;ObjectUtils&nbsp;{<br /></span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">&nbsp;3</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;4</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Compare&nbsp;whether&nbsp;the&nbsp;left&nbsp;and&nbsp;right&nbsp;is&nbsp;equals<br /></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;It&nbsp;has&nbsp;already&nbsp;considered&nbsp;the&nbsp;null&nbsp;case<br /></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br /></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;left<br /></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;right<br /></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #008000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;"><br /></span><span style="color: #008080;">10</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;">11</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;">boolean</span><span style="color: #000000;">&nbsp;equals(Object&nbsp;left,&nbsp;Object&nbsp;right)&nbsp;{<br /></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(left&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;right&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br /></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(left&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;right&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br /></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<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;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;left.equals(right);<br /></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">}</span></div>在《Effective Java》这本书中，貌似equals实现方法前面没有null、this的判断，因为instanceof可以解决null的问题，而super.equals()方法可以解决this问题，但是我还是喜欢把它们都分出来，这样写的更加明了一些。另外，事实上，这里的实现并没有遵循对称性的原则，因为如果A是B的子类，而这个equals方法在A类中，那么AInstance.equals(BInstance)==false，若B也实现了类似的equals方法，则BInstance.equals(AInstance)==true(当A没有新的比较字段时，或许这个时候A根本就不需要实现equals方法，如本文开头列出的第三条），这是因为AInstance instanceof BInstance ＝＝ true，反之则为false。不过由于这种情况并不常见，所以就不去care了。:)<br /><br />&nbsp;&nbsp;&nbsp; 事实上，这里我之所以要记录这些代码，主要是因为有ObjectUtils类的存在。记得以前在学C#的时候，它的Object类提供了一个静态的Equals方法，我一直对这个方法的存在感到很疑问，直到这次自己写这个equals方法才弄明白，因为虽然在equals方法实现中，最后还要判断类字段是否equals，然后这些字段都有可能是null的，如果没有提供这个静态的equals方法，我们就需要自己来判断每个字段是否为null，然后才可以调用它的equals方法，这样就比较麻烦了，而Object.Equals方法正是对这种行为的封装，我们只要使用一个方法就可以安全的实现类成员的equals。这也是我加ObjectUtils类的意义所在。希望以后能有机会向这个ObjectUtils类填充更多的实用方法。:)<br /><br />PS:如一楼所说在commons中的<span class="Apple-style-span" style="font-family: georgia, verdana, Arial, helvetica, sans-seriff; line-height: 26px; font-size: 12px; ">EqualsBuilder已经实现了相同的功能，而且代码更加完善，有兴趣的可以看看那里的代码，我这里只是对这次新的的记录，代码只是对当前我考虑的场景中使用，并没有考虑其他方面。另外，在《Effective Java》中也是建议equals和hashCode两个方法应该是同时实现的，一楼也有说可以用HashCodeBuider来实现，这个大家也不妨可以去看看里面的源码，最近时间不多，以后回来再看。。。。。。</span><img src ="http://www.blogjava.net/DLevin/aggbug/353379.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-06-29 19:05 <a href="http://www.blogjava.net/DLevin/archive/2011/06/29/353379.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的Bridge方法</title><link>http://www.blogjava.net/DLevin/archive/2011/06/23/352917.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Thu, 23 Jun 2011 15:54:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/06/23/352917.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/352917.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/06/23/352917.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/352917.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/352917.html</trackback:ping><description><![CDATA[<div><p><span style="font-family:宋体;">今天在</span>Java<span style="font-family:宋体;">中字节码的格式的时候，发现</span>method_info<span style="font-family:宋体;">中的</span>access_flags<span style="font-family:宋体;">中竟然定了</span>ACC_BRIDGE<span style="font-family:宋体;">的值。网上搜了一下，大概理解它的意思了，先记之。</span></p>  <p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">首先是在什么情况下会生成</span>bridge</strong><strong><span style="font-family:宋体;">方法（</span>2</strong><strong><span style="font-family:宋体;">）：</span></strong></p>  <p><span><span style="font-size:9.0pt;font-family:&quot;Arial&quot;,&quot;sans-serif&quot;;color:black">bridge method may be created by the compiler when extending a parameterized type whose methods have parameterized arguments.</span></span></p>  <p><span style="font-family:宋体;">这是在网上找到的有人贴出来的一段话，但是感觉这段话说的并不是很明白。首先</span>bridge<span style="font-family:宋体;">方式是由编译器产生的，因而在源代码中也没有</span>bridge<span style="font-family:宋体;">的关键字。然后只有在以具体类型继承自一个泛型类，同时被继承的泛型类包含了泛型方法。比如看以下的例子：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" color="#7F0055" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"><strong></strong></span></font></p><font class="Apple-style-span" color="#7F0055" face="'Courier New'" size="3"><strong><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">abstract</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;A</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">abstract</span><span style="color: #000000; ">&nbsp;T&nbsp;method1(T&nbsp;arg);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">abstract</span><span style="color: #000000; ">&nbsp;T&nbsp;method2();<br />}<br />&nbsp;<br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;B&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;A</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;String&nbsp;method1(String&nbsp;arg)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;arg;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;String&nbsp;method2()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br />&nbsp;<br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;C</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;A</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;T&nbsp;method1(T&nbsp;arg)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;arg;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;T&nbsp;method2()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">null</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div></strong></font><p>&nbsp;</p>  <p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">他们生成的</span>.class</strong><strong><span style="font-family:宋体;">文件如下：</span></strong></p>  <p><strong>A.class</strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">abstract class org.levin.insidejvm.miscs.bridgemethod.A {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public abstract java.lang.Object method1(java.lang.Object arg0);</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public abstract java.lang.Object method2();</span></strong></p>  <p><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">}</span></p>  <p><strong>B.class</strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">class org.levin.insidejvm.miscs.bridgemethod.B extends org.levin.insidejvm.miscs.bridgemethod.A {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;<strong>public java.lang.String method1(java.lang.String arg);</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;aload_1 [arg]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 1&nbsp;areturn</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;<strong>public java.lang.String method2();</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;ldc &lt;String "abc"&gt; [20]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 2&nbsp;areturn</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public bridge synthetic java.lang.Object method2();</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;aload_0 [this]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 1&nbsp;invokevirtual org.levin.insidejvm.miscs.bridgemethod.B.method2() : java.lang.String [23]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 4&nbsp;areturn</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;<strong>&nbsp;public bridge synthetic java.lang.Object method1(java.lang.Object arg0);</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;aload_0 [this]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 1&nbsp;aload_1 [arg0]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 2&nbsp;checkcast java.lang.String [26]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 5&nbsp;invokevirtual org.levin.insidejvm.miscs.bridgemethod.B.method1(java.lang.String) : java.lang.String [28]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 8&nbsp;areturn</span></p>  <p><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">}</span></p>  <p><strong>C.class</strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">class org.levin.insidejvm.miscs.bridgemethod.C extends org.levin.insidejvm.miscs.bridgemethod.A {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;<strong>&nbsp;public java.lang.Object method1(java.lang.Object arg);</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;aload_1 [arg]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 1&nbsp;areturn</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;<strong>public java.lang.Object method2();</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;aconst_null</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 1&nbsp;areturn</span></p>  <p><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">}</span></p>  <p><span style="font-family:宋体;">可以看到</span>B<span style="font-family:宋体;">中生成了两个</span>bridge<span style="font-family:宋体;">方法，而</span>C<span style="font-family:宋体;">中则没有。事实上，由于</span>Java<span style="font-family:宋体;">中泛型有擦除的机制，因而在编译</span>A<span style="font-family:宋体;">类的时候，它里面定义的方法都是以</span>Object<span style="font-family:宋体;">类型来表示了，因而如果没有</span>bridge<span style="font-family:宋体;">方法，</span>B<span style="font-family:宋体;">类根本没有覆盖</span>A<span style="font-family:宋体;">类中的</span>abstract<span style="font-family:宋体;">方法。正因为有</span>bridge<span style="font-family:宋体;">方法的存在，才使得</span>B<span style="font-family:宋体;">类可以编译通过。而</span>C<span style="font-family:宋体;">类由于在编译时所有的泛型也都是通过</span>Object<span style="font-family:宋体;">类来表达的，因而它实现的也是</span>A<span style="font-family:宋体;">类中的</span>abstract<span style="font-family:宋体;">方法，因而不用再生成</span>bridge<span style="font-family:宋体;">方法了。</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">事实上</span>B<span style="font-family:宋体;">类中的</span>bridge<span style="font-family:宋体;">方法在调用也有一些区别：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"></span></font></p><font class="Apple-style-span" face="'Courier New'" size="3"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&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 />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;b&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;B();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b.method1(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">String</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;a&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;B();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a.method1(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">abc</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div></font><p>&nbsp;</p>  <p><span style="font-family:宋体;">这段方法的字节码如下：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;new org.levin.insidejvm.miscs.bridgemethod.B [16]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;dup</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;invokespecial org.levin.insidejvm.miscs.bridgemethod.B() [18]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp;astore_1 [b]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;aload_1 [b]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;ldc &lt;String "abc"&gt; [19]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 11&nbsp;invokevirtual org.levin.insidejvm.miscs.bridgemethod.B.method1(java.lang.String) : java.lang.String [21]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 14&nbsp;pop</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 15&nbsp;new org.levin.insidejvm.miscs.bridgemethod.B [16]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 18&nbsp;dup</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 19&nbsp;invokespecial org.levin.insidejvm.miscs.bridgemethod.B() [18]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 22&nbsp;astore_2 [a]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 23&nbsp;aload_2 [a]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 24&nbsp;ldc &lt;String "abc"&gt; [19]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 26&nbsp;invokevirtual org.levin.insidejvm.miscs.bridgemethod.A.method1(java.lang.Object) : java.lang.Object [25]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 29&nbsp;pop</span></p>  <p><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 30&nbsp;return</span></p>  <p><span style="font-family:宋体;">以上的代码可以看出</span>b<span style="font-family:宋体;">变量调用的</span>method1(String)<span style="font-family:宋体;">的方法，而</span>a<span style="font-family:宋体;">变量调用的却是</span>method1(Object)<span style="font-family:宋体;">方法。这种区别也正式因为</span>bridge<span style="font-family:宋体;">方法提供的支持才实现的。</span></p>  <p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">事实上，</span>bridge</strong><strong><span style="font-family:宋体;">方法还会在另外一种情况下产生（</span>2</strong><strong><span style="font-family:宋体;">）：</span></strong></p>  <p><span style="font-family:宋体;">在</span>Java 1.4<span style="font-family:宋体;">中，子类若要重写父类某个方法，那么子类的方法和父类的方法签名必须完全一致，包括方法名、参数类型以及返回值；而到</span>Java 1.5<span style="font-family:宋体;">中，该机制变成，如果子类中某个方法的方法名和参数类型和父类某方法一致，并且子类该方法的返回值是父类相应方法返回值的类型或其子类型，那么该子类方法也可以重写父类中相应的方法。参看以下例子：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" color="#7F0055" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"><strong></strong></span></font></p><font class="Apple-style-span" color="#7F0055" face="'Courier New'" size="3"><strong><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;E&nbsp;{<br />&nbsp;&nbsp;&nbsp;<br />}<br />&nbsp;<br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;F&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;E&nbsp;{<br />&nbsp;&nbsp;&nbsp;<br />}<br />&nbsp;<br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;X&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;E&nbsp;getE()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;E();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br />&nbsp;<br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;Y&nbsp;</span><span style="color: #0000FF; ">extends</span><span style="color: #000000; ">&nbsp;X&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;F&nbsp;getE()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;F();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div></strong></font><p>&nbsp;</p>  <p><span style="font-family:宋体;">以上代码是可以编译通过的。让我们再来查看一下</span>Y<span style="font-family:宋体;">的字节码：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">class org.levin.insidejvm.miscs.bridgemethod.Y extends org.levin.insidejvm.miscs.bridgemethod.X {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;<strong>&nbsp;public org.levin.insidejvm.miscs.bridgemethod.F getE();</strong></span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;new org.levin.insidejvm.miscs.bridgemethod.F [16]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 3&nbsp;dup</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 4&nbsp;invokespecial org.levin.insidejvm.miscs.bridgemethod.F() [18]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 7&nbsp;areturn</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public bridge synthetic org.levin.insidejvm.miscs.bridgemethod.E getE();</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 0&nbsp;aload_0 [this]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 1&nbsp;invokevirtual org.levin.insidejvm.miscs.bridgemethod.Y.getE() : org.levin.insidejvm.miscs.bridgemethod.F [20]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 4&nbsp;areturn</span></p>  <p><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">}</span></p>  <p><span style="font-family:宋体;">从字节码上，我们可以看出语法本身事实上并没有发生变化，变化的只是编译器做的支持，它为重载方法重新生成了一个返回</span>E<span style="font-family:宋体;">而不是</span>F<span style="font-family:宋体;">的</span>bridge<span style="font-family:宋体;">方法。</span></p>  <p><span style="font-family:宋体;">从调用的字节码上可以更加明显的看出语法没有发生变化这一点：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"></span></font></p><font class="Apple-style-span" face="'Courier New'" size="3"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&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 />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Y();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x.getE();<br />&nbsp;&nbsp;&nbsp;&nbsp;}</span></div></font><p>&nbsp;</p>  <p><span style="font-family:宋体;">字节码如下：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public static void main(java.lang.String[] args);</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;new org.levin.insidejvm.miscs.bridgemethod.Y [16]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;dup</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;invokespecial org.levin.insidejvm.miscs.bridgemethod.Y() [18]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;astore_1 [x]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp;aload_1 [x]</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;invokevirtual org.levin.insidejvm.miscs.bridgemethod.X.getE() : org.levin.insidejvm.miscs.bridgemethod.E [19]</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;&nbsp;&nbsp; 12&nbsp;pop</span></p>  <p style="text-indent:17.25pt"><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">13&nbsp;return</span></p>  <p><span style="font-family:宋体;">该字节码中</span>x.getE()<span style="font-family:宋体;">方法事实上调用的就是生成的</span>bridge<span style="font-family:宋体;">方法（</span>E getE()<span style="font-family:宋体;">）方法，而不是用户定义的</span>F getE()<span style="font-family:宋体;">方法。</span></p>  <p><span style="font-family:宋体;">这种重载机制在某些，不同子类某个函数的返回值是不一样的，但是他们都需要重写父类中方法，以可以在某个点上通过父类实例统一调用。只是这种机制就需要返回值必须是继承于同一个类。事实上，这种方式在没有引入这种重写机制的时候也是可以实现的，只是现在</span>Java<span style="font-family:宋体;">在编译器层面上提供了支持。<br /><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; &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;于2010年10月3日<br />注：这些文章都是前些时候写的，之前博客很乱，也都是随便贴一些自己写的或转载的，还有一些则是没有贴出来过的。现在打算好好整理一下，完整的记录自己的一些学习历程，而每次看到过去的时间，则让我想起以前的日子，因而我对时间一直是很重视的，所以每篇都著名写的日期，直到最先的文章出现。:)<br /><br /></span></p></div><img src ="http://www.blogjava.net/DLevin/aggbug/352917.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-06-23 23:54 <a href="http://www.blogjava.net/DLevin/archive/2011/06/23/352917.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java接口中的字段</title><link>http://www.blogjava.net/DLevin/archive/2011/06/23/352916.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Thu, 23 Jun 2011 15:51:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/06/23/352916.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/352916.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/06/23/352916.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/352916.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/352916.html</trackback:ping><description><![CDATA[<div><p align="left" style="text-align:left"><strong>Java</strong><strong><span style="font-family:宋体;">接口中的字段默认都是<span style="background: yellow;">静态</span><span style="background:lime;">常量</span>，不管在编码的时候有没有显示的指定</span>static</strong><strong><span style="font-family:宋体;">或者</span>final</strong><strong><span style="font-family:宋体;">。</span></strong></p>  <p align="left" style="text-align:left"><strong>&nbsp;</strong></p>  <p align="left" style="text-align:left"><span style="font-family: 宋体;">如以下接口：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><font class="Apple-style-span" color="#7F0055" face="'Courier New'" size="3"><span class="Apple-style-span" style="font-size: 13px;"><strong></strong></span></font></p><font class="Apple-style-span" color="#7F0055" face="'Courier New'" size="3"><strong><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">interface</span><span style="color: #000000; ">&nbsp;AccessFlag&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;a&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">;<br />&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;b&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">20</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;c&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">30</span><span style="color: #000000; ">;<br />&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; ">final</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;d&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">40</span><span style="color: #000000; ">;<br />}</span></div></strong></font><p>&nbsp;</p>  <p align="left" style="text-align:left"><span style="font-family: 宋体;">它编译生成的二进制代码如下：</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:9.0pt;font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;;">public abstract interface org.levin.classfilereader.AccessFlag {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public static final int a = 10;</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public static final int b = 20;</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public static final int c = 30;</span></strong></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:9.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">&nbsp;public static final int d = 40;</span></strong></p>  <p align="left" style="text-align:left"><span style="font-size: 9pt; font-family: 微软雅黑, sans-serif; ">}<br /><div><span style="font-family: 宋体; font-size: 14px; ">&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;于2010年9月4日<br />注：这些文章都是前些时候写的，之前博客很乱，也都是随便贴一些自己写的或转载的，还有一些则是没有贴出来过的。现在打算好好整理一下，完整的记录自己的一些学习历程，而每次看到过去的时间，则让我想起以前的日子，因而我对时间一直是很重视的，所以每篇都著名写的日期，直到最先的文章出现。:)</span></div></span></p></div><img src ="http://www.blogjava.net/DLevin/aggbug/352916.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-06-23 23:51 <a href="http://www.blogjava.net/DLevin/archive/2011/06/23/352916.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Static变量和实例变量的初始化顺序问题</title><link>http://www.blogjava.net/DLevin/archive/2011/06/20/352691.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 20 Jun 2011 14:53:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/06/20/352691.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/352691.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/06/20/352691.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/352691.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/352691.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 问题重现  让我们先来看一下以下的程序：  Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->&nbsp;1&nbsp;public&nbsp;class&nbsp;StaticInitSequence&nbsp;{&nbsp;2&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.blogjava.net/DLevin/archive/2011/06/20/352691.html'>阅读全文</a><img src ="http://www.blogjava.net/DLevin/aggbug/352691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-06-20 22:53 <a href="http://www.blogjava.net/DLevin/archive/2011/06/20/352691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Void类的用法</title><link>http://www.blogjava.net/DLevin/archive/2011/06/20/352690.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 20 Jun 2011 14:48:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/06/20/352690.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/352690.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/06/20/352690.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/352690.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/352690.html</trackback:ping><description><![CDATA[<div><p><span style="font-family:宋体;">今天在看</span>ClassLoader<span style="font-family:宋体;">源码的时候，突然发现里面有一个叫</span>Void<span style="font-family:宋体;">的类使用，代码看起来挺新颖的，摘下来，以备后用。</span></p>  <p align="left" style="text-align:left;text-autospace:none"><strong><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#7F0055;">public</span></strong> <strong><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#7F0055;">abstract</span></strong> <strong><span style="font-size:10.0pt; font-family:&quot;Courier New&quot;;color:#7F0055;">class</span></strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;"> ClassLoader {<br /></span><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp; &nbsp;</span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">private</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">static</span></strong><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;"> <span style="background:yellow;">Void</span> checkCreateClassLoader() {<br /></span><span class="Apple-style-span" style="font-family: 'Courier New'; font-size: 13px; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;...<br /></span><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;background: yellow;">return</span></strong> <strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055; background:yellow;">null</span></strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black; background:yellow;">;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp; }</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">private</span></strong><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;"> ClassLoader(<span style="background:yellow;">Void unused</span>, ClassLoader parent) {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">this</span></strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:black;">.</span><span style="font-size: 10.0pt;font-family:&quot;Courier New&quot;;color:#0000C0;">parent</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;"> = parent;</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp; }</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">protected</span></strong><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;"> ClassLoader(ClassLoader parent) {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;background: yellow;">this</span></strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black; background:yellow;">(<em>checkCreateClassLoader</em>(), parent);</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp; }<br /></span><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp; &nbsp;</span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;">protected</span></strong><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;"> ClassLoader() {</span></p>  <p align="left" style="text-align:left;text-autospace:none"><span style="font-size:10.0pt;font-family: &quot;Courier New&quot;;color:black;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:#7F0055;background: yellow;">this</span></strong><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black; background:yellow;">(<em>checkCreateClassLoader</em>(), <em>getSystemClassLoader</em>());</span></p>  <p style="text-indent:21.0pt"><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;color:black;">}</span></p>  <p><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;; color:black;">}</span></p>  <p>checkCreateClassLoader()<span style="font-family:宋体;">方法用返回</span>Void<span style="font-family:宋体;">类型，该函数返回</span>null<span style="font-family:宋体;">，然后它就可以在其他函数的参数中调用了，只要该参数也是</span>Void<span style="font-family:宋体;">类型的。</span></p>  <p><span style="font-family:宋体;">这种方式绕开了</span>Java<span style="font-family:宋体;">中不能在函数参数中使用</span>void<span style="font-family:宋体;">类型的局限。</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">可以作为部分参考吧。呵呵。</span></p>  <p>&nbsp;<span class="Apple-style-span" style="font-family: 宋体; ">&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;于2010年9月15日</span></p><div><span style="font-family: 宋体; ">注：这些文章都是前些时候写的，之前博客很乱，也都是随便贴一些自己写的或转载的，还有一些则是没有贴出来过的。现在打算好好整理一下，完整的记录自己的一些学习历程，而每次看到过去的时间，则让我想起以前的日子，因而我对时间一直是很重视的，所以每篇都著名写的日期，直到最先的文章出现。:)</span></div></div><img src ="http://www.blogjava.net/DLevin/aggbug/352690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-06-20 22:48 <a href="http://www.blogjava.net/DLevin/archive/2011/06/20/352690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>List或数组到String的转换</title><link>http://www.blogjava.net/DLevin/archive/2011/06/20/352657.html</link><dc:creator>DLevin</dc:creator><author>DLevin</author><pubDate>Mon, 20 Jun 2011 05:27:00 GMT</pubDate><guid>http://www.blogjava.net/DLevin/archive/2011/06/20/352657.html</guid><wfw:comment>http://www.blogjava.net/DLevin/comments/352657.html</wfw:comment><comments>http://www.blogjava.net/DLevin/archive/2011/06/20/352657.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/DLevin/comments/commentRss/352657.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/DLevin/services/trackbacks/352657.html</trackback:ping><description><![CDATA[在编程过程中偶尔会遇到需要将List或数组以某个字符间隔的形式将其拼接成一个字符串，比如在发送邮件时，to列表是以分号分割的字符串，然而在程序中我们可能会一List&lt;String&gt;或String[]的形式存在，此时就需要做List或数组到String的转换。<br />在C#中，String类提供了一个叫Join的方法，因而我们使用一句代码就可以完成这样的工作：<br /><div><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><span style="color: #0000ff;">string</span><span style="color: #000000;">&nbsp;result&nbsp;</span><span style="color: #000000;">=</span>&nbsp;<span style="color: #0000ff;">string</span><span style="color: #000000;">.Join(</span><span style="color: #000000;">"</span><span style="color: #000000;">;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">,&nbsp;toList.ToArray());</span></div></div>但是在Java中貌似没有提供类似的方法（至少我还没有找到），既然没有提供，我们就可以自己来写一个：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;StringUtils&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;StringUitls类中的方法都是静态的，<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;阻止其创建实例，以引起一些误解。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;另一种做法是将其变为abstract类，<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;但是这样也会引起一些误解，<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;因为abstract类的意思就是可以继承的，<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;然而该类却不应该由其他类来继承。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;因而abstract类个人感觉不是一种好的做法。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;StringUtils()&nbsp;{&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;将array中的内容以delimiter为间隔拼接字符串<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;array<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;delimiter<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />&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;String&nbsp;join(Object[]&nbsp;array,&nbsp;String&nbsp;delimiter)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(array&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;IllegalArgumentException();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(array.length&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">""</span><span style="color: #000000;">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder&nbsp;builder&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;StringBuilder();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(Object&nbsp;item&nbsp;:&nbsp;array)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;builder.append(item.toString()&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;delimiter);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;builder.delete(builder.length()&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">&nbsp;delimiter.length(),&nbsp;builder.length());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;builder.toString();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;将list中的内容以delimiter为间隔拼接字符串<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;list<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;delimiter<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;@SuppressWarnings(</span><span style="color: #000000;">"</span><span style="color: #000000;">unchecked</span><span style="color: #000000;">"</span><span style="color: #000000;">)<br />&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;String&nbsp;join(List&nbsp;list,&nbsp;String&nbsp;delimiter)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(list&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;IllegalArgumentException();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;join(list.toArray(),&nbsp;delimiter);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><br />测试代码如下：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Test<br /></span><span style="color: #008080;">&nbsp;2</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;testListToString()&nbsp;{<br /></span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br /></span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">Item1</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">Item2</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">Item3</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;expected&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">[Item1,&nbsp;Item2,&nbsp;Item3]</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(expected,&nbsp;list.toString());<br /></span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;@Test<br /></span><span style="color: #008080;">14</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;testListToString2()&nbsp;{<br /></span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;list&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ArrayList</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">String</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">();<br /></span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">Item1</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">Item2</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.add(</span><span style="color: #000000;">"</span><span style="color: #000000;">Item3</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br /></span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;expected&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">Item1;Item2;Item3</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br /></span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertEquals(expected,&nbsp;StringUtils.join(list,&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">;</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br /></span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br /><img src ="http://www.blogjava.net/DLevin/aggbug/352657.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/DLevin/" target="_blank">DLevin</a> 2011-06-20 13:27 <a href="http://www.blogjava.net/DLevin/archive/2011/06/20/352657.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>