﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-Java Space</title><link>http://www.blogjava.net/raulangcn/</link><description>我学习Java的空间,记录Java历程的点滴!</description><language>zh-cn</language><lastBuildDate>Sat, 20 Jun 2026 19:28:46 GMT</lastBuildDate><pubDate>Sat, 20 Jun 2026 19:28:46 GMT</pubDate><ttl>60</ttl><item><title>Java基础之 与equals()如影随行的hashCode()</title><link>http://www.blogjava.net/raulangcn/articles/165135.html</link><dc:creator>raulang</dc:creator><author>raulang</author><pubDate>Tue, 04 Dec 2007 04:54:00 GMT</pubDate><guid>http://www.blogjava.net/raulangcn/articles/165135.html</guid><wfw:comment>http://www.blogjava.net/raulangcn/comments/165135.html</wfw:comment><comments>http://www.blogjava.net/raulangcn/articles/165135.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raulangcn/comments/commentRss/165135.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raulangcn/services/trackbacks/165135.html</trackback:ping><description><![CDATA[&nbsp;
<p style="text-indent: 24.65pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">上一篇文章我们谈到了</span><span style="font-size: 12pt; line-height: 150%">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的重写，接下来我们说说与</span><span style="font-size: 12pt; line-height: 150%">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">关系紧密的</span><span style="font-size: 12pt; line-height: 150%">hashCode()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，这从标题就可窥见一斑。</span></p>
<p style="text-indent: 24.65pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%">hashCode()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">返回该对象的哈希码值，该值通常是一个由该对象的内部地址转换而来的整数，它的实现主要是为了提高哈希表</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的性能。在每个重写了</span><span style="font-size: 12pt; line-height: 150%">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法的类中，你必须也要重写</span><span style="font-size: 12pt; line-height: 150%">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法。如果不这样做的话，就会违反</span><span style="font-size: 12pt; line-height: 150%">Object.hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的通用约定，从而导致该类无法与所有基于散列值</span><span style="font-size: 12pt; line-height: 150%">(hash)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的集合类结合在一起正常运作。</span></p>
<p style="text-indent: 24.65pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">下面是</span><span style="font-size: 12pt; line-height: 150%">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">约定的内容，来自</span><span style="font-size: 12pt; line-height: 150%">java.lang.Object</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的规范：</span></p>
<p style="margin-left: 45.65pt; text-indent: -21pt; line-height: 150%; tab-stops: list 35.15pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">l</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">在一个Java应用程序执行期间，如果一个对象的equals方法做比较所用到的信息没有被修改的话，那么，对该对象调用hashCode方法多次，它必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中，这个整数可以不同。</span></p>
<p style="margin-left: 45.65pt; text-indent: -21pt; line-height: 150%; tab-stops: list 35.15pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">l</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果两个对象根据equals(Object)方法是相等的，那么对这两个对象中的每一个对象调用hashCode方法都必须生成相同的整数结果。</span></p>
<p style="margin-left: 45.65pt; text-indent: -21pt; line-height: 150%; tab-stops: list 35.15pt"><span style="font-size: 12pt; line-height: 150%; font-family: Wingdings">l</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果两个对象根据equals(Object)方法是不相等的，那么调用这两个对象中任一个对象的hashCode方法，不要求必须产生不同的整数结果。然而，程序员应该意识到这样的事实，对于不相等的对象产生截然不同的整数结果，有可能提高散列表的性能。</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">下面我们仍然用上一篇文章&#8220;</span><span style="font-size: 12pt; line-height: 150%">(override)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">重写</span><span style="font-size: 12pt; line-height: 150%">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法&#8221;中所用的例子，来详细解释上面约定的内容：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public class ColorPoint{</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; private Point point;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; private Color color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public ColorPoint(int x, int y, Color color){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point = new Point(x, y);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.color = color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; //</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">返回一个与该有色点在同一位置上的普通</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Point</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">对象</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public Point asPoint(){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return point;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public boolean equals(Object o){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;if(o == this)</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!(o instanceof ColorPoint))</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ColorPoint cp = (ColorPoint)o;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return cp.point.equals(point)&amp;&amp;</span></p>
<p style="layout-grid-mode: char; text-indent: 162pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">cp.color.equals(color);</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">假设你试图将这个类与</span><span style="font-size: 12pt; line-height: 150%">HashMap</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">一起使用：</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public class Test{</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public static void main(String[] args){</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Map m = new HashMap();</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">m.put(new ColorPoint(1,2,Color.RED),&#8221;red&#8221;);</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">System.out.println(m.get(</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　　　　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">new ColorPoint(1,2,Color.RED)));</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">这时候，你可能会期望程序返回并输出</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&#8221;red&#8221;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，但是实际的运行结果是：</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">null</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。为什么呢？因为这里涉及到两个</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">ColorPoint</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">实例：第一个被用于插入到</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">HashMap</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">中，第二个实例与第一个相等，被用于</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">试图</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">检索。由于</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">ColorPoint</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类没有重写</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法，从而导致两个相等的实例具有不相等的散列码，违反了</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的约定。因此，要想解决这个问题</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">,</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">只需为</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">ColorPoint</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类提供一个适当的</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法既可。</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如何编写一个适当的</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法呢？下面是我从《</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Effective Java</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">》一书中摘抄而来的&#8220;诀窍&#8221;：</span></p>
<p style="margin-left: 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 10.45pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">把某个非零常数值，比如说</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">17</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，保存在一个</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">int</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的变量</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">中。</span></p>
<p style="margin-left: 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 20.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">对于对象中每个关键域</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">f(</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">指</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法中考虑的每个域</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，完成以下步骤：</span></p>
<p style="margin-left: 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 41.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">A.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">为该域计算</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">int</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的散列码</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">c:</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; line-height: 150%; tab-stops: list 62.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">a.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果该域是</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">boolean</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型，则计算</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(f ? 0 : 1)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; line-height: 150%; tab-stops: list 62.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">b.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果该域是</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">byte</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">、</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">char</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">、</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">short</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">或</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">int</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型，则计算</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(int)f</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; line-height: 150%; tab-stops: list 62.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">c.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果该域是</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">long</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型，则计算</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(int)(f ^ (f &gt;&gt;&gt; 32))</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; line-height: 150%; tab-stops: list 62.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">d.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果该域是</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">float</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型，则计算</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Float.floatToIntBits(f)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; line-height: 150%; tab-stops: list 62.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">e.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果该域是</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">double</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型，则计算</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Double.doubleToLongBits(f)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">得到一个</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">long</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的值，然后按照步骤</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">2.A.c </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，对该</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">long</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">型值计算散列值。</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; line-height: 150%; tab-stops: list 62.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">f.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果该域是一个对象引用，并且该类的</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法通过递归调用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的方式来比较这个域，则同样对该域递归调用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 63pt; text-indent: -21pt; line-height: 150%; tab-stops: list 62.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">g.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果该域是一个数组，则把每一个元素当做一个单独的域来处理。也就是说，递归地应用上述规则，对每个重要的元素计算散列值。</span></p>
<p style="margin-left: 42pt; text-indent: -21pt; line-height: 150%; tab-stops: list 41.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">B.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">按照下面的公式，把步骤</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">A</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">中计算得到的散列码</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">c</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">组合到</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">中</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">:</span></p>
<p style="margin-left: 21pt; text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result = 37*result + c;</span></p>
<p style="margin-left: 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 20.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 21pt; text-indent: -21pt; line-height: 150%; tab-stops: list 20.95pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">写完了</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法之后，问自己&#8220;是否相等的实例具有相等的散列码&#8221;。如果不是的话，请找出原因，并修正错误。</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">现在，我们把这种方法用到</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">ColorPoint</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类中。它有两个关键域，都是对象引用类型。根据上面的步骤，很直接地会得到下面的散列函数：</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public int hashCode(){</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">int result = 17;</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result = 37*result + point.hashCode();</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result = 37*result + color.hashCode();</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">return result;</span></p>
<p style="text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="margin-left: -24.05pt; text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">接下来还要为</span><span style="font-size: 12pt; line-height: 150%">Point</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类重写</span><span style="font-size: 12pt; line-height: 150%">hashCode</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法，它有两个关键域，都是</span><span style="font-size: 12pt; line-height: 150%">int</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型，添加如下代码：</span></p>
<p style="margin-left: -24.05pt; text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public int hashCode(){</span></p>
<p style="margin-left: -24.05pt; text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">　　</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">int result = 17;</span></p>
<p style="margin-left: -24.05pt; text-indent: 48pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result = 37*result + x;</span></p>
<p style="margin-left: -24.05pt; text-indent: 48pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">result = 37*result + y;</span></p>
<p style="margin-left: -24.05pt; text-indent: 48pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">return result;</span></p>
<p style="margin-left: -24.05pt; text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="margin-left: -24.05pt; text-indent: 24pt; line-height: 150%"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">最后，我们再次运行上面的</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Test</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类，看看实际的运行结果是否和我们期望的一样。亲爱的朋友们，你们的运行结果怎样？请用留言的方式来告诉我。</span></p>
<img src ="http://www.blogjava.net/raulangcn/aggbug/165135.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raulangcn/" target="_blank">raulang</a> 2007-12-04 12:54 <a href="http://www.blogjava.net/raulangcn/articles/165135.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java基础之　(override)重写equals()方法</title><link>http://www.blogjava.net/raulangcn/articles/164841.html</link><dc:creator>raulang</dc:creator><author>raulang</author><pubDate>Mon, 03 Dec 2007 05:11:00 GMT</pubDate><guid>http://www.blogjava.net/raulangcn/articles/164841.html</guid><wfw:comment>http://www.blogjava.net/raulangcn/comments/164841.html</wfw:comment><comments>http://www.blogjava.net/raulangcn/articles/164841.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raulangcn/comments/commentRss/164841.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raulangcn/services/trackbacks/164841.html</trackback:ping><description><![CDATA[&nbsp; <span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 宋体">什么时候需要重写equals()?</span>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">我们知道每一个java类都继承自Object类，equals()是Object类中提供的方法之一。那么，让我们先来看看Object#equals()在Java中的原代码：</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><strong><span style="font-size: 12pt; color: #7f0055; line-height: 150%; font-family: 'Courier New'">public</span></strong><strong><span style="font-size: 12pt; color: #7f0055; line-height: 150%; font-family: 'Courier New'">boolean</span></strong><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 'Courier New'"> equals(Object obj) </span><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 'Courier New'">{</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp; </span><strong><span style="font-size: 12pt; color: #7f0055; line-height: 150%; font-family: 'Courier New'">return</span></strong><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 'Courier New'"> (</span><strong><span style="font-size: 12pt; color: #7f0055; line-height: 150%; font-family: 'Courier New'">this</span></strong><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 'Courier New'"> == obj);</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; color: black; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">可以看出，只有当一个实例等于它本身的时候，</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">才会返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">值。通俗地说，此时比较的是两个引用是否指向内存中的同一个对象，也可以称做是否实例相等。而我们在使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">来比较两个指向值对象的引用的时候，往往希望知道它们逻辑上是否相等，而不是它们是否指向同一个对象。在这样的情况下，如果超类也没有重写</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">以实现期望的行为，这时我们就需要重写</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法。而且这样做也使得这个类的实例可以被用做映射表</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(map)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的键，或者集合</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(set)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的元素，并使映射表或者集合表现出预期的行为。</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 宋体">怎样重写</span><span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 'Courier New'">equals()</span><span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 宋体">方法？</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">重写</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法看起来非常简单，但是有许多改写的方式会导致错误，并且后果非常严重。要想正确改写</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals()</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法，你必须要遵守它的通用约定。下面是约定的内容，来自</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">java.lang.Object</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">的规范：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法实现了等价关系</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(equivalence relation):</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">1.&nbsp;</span><strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">自反性</span></strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">：对于任意的引用值</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x.equals(x)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">一定为</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">2.&nbsp;</span><strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">对称性</span></strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">：对于任意的引用值</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">和</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'"> y</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，当</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x.equals(y)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">时，</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">y.equals(x)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">也一定返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">3.&nbsp;</span><strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">传递性</span></strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">：对于任意的引用值</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">、</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">y</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">和ｚ，如果</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x.equals(y)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，并且</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">y.equals(z)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">也返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，那么</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x.equals(z)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">也一定返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">4.&nbsp;</span><strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">一致性</span></strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">：对于任意的引用值</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x </span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">和</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'"> y</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，如果用于</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">比较的对象信息没有被修改的话，那么，多次调用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x.equals(y)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">要么一致地返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，要么一致地返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">false</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">5.&nbsp;</span><strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">非空性</span></strong><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">：对于任意的非空引用值</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">x.equals(null)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">一定返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">false</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">接下来我们通过实例来理解上面的约定。我们首先以一个简单的非可变的二维点类作为开始：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public class Point{</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; private final int x;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; private final int y;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public Point(int x, int y){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.x = x;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.y = y;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public boolean equals(Object o){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!(o instanceof Point))</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Point p = (Point)o;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return p.x == x &amp;&amp; p.y == y;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &#8230;&#8230;&#8230;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">假设你想要扩展这个类，为一个点增加颜色信息：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public class ColorPoint extends Point{</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; private Color color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public ColorPoint(int x, int y, Color color){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(x, y);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.color = color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; //override equasl()</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public boolean equals(Object o){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!(o instanceof ColorPoint))</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ColorPoint cp = (ColorPoint)o;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.equals(o) &amp;&amp; cp.color==color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; &#8230;&#8230;&#8230;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">我们重写了</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法，只有当实参是另一个有色点，并且具有同样的位置和颜色的时候，它才返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。可这个方法的问题在于，你在比较一个普通点和一个有色点，以及反过来的情形的时候，可能会得到不同的结果：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public static void main(String[] args){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; Point p = new Point(1, 2);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; ColorPoint cp=new ColorPoint(1,2, Color.RED);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; System.out.println(p.equals(cp));</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; System.out.println(cp.eqauls(p));</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">运行结果：</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left; tab-stops: 59.45pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true&nbsp;&nbsp;&nbsp; </span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left; tab-stops: 59.45pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">false</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">这样的结果显然违反了对称性，你可以做这样的尝试来修正这个问题：让</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">ColorPoint.equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">在进行&#8220;混合比较&#8221;的时候忽略颜色信息：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public boolean equals(Object o){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; if(!(o instanceof Point))</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; //</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">o</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">是一个普通点，就忽略颜色信息</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; if(!(o instanceof ColorPoint))</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return o.equals(this);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; //</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">o</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">是一个有色点，就做完整的比较</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; ColorPoint cp = (ColorPoint)o;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; return super.equals(o) &amp;&amp; cp.color==color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">这种方法的结果会怎样呢？让我们先来测试一下：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public static void main(String[] args){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; ColorPoint p1=new ColorPoint(1,2, Color.RED);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; Point p2 = new Point(1, 2);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; ColorPoint p3=new ColorPoint(1,2, Color.BLUE);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; System.out.println(p1.equals(p2));</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; System.out.println(p2.equals(p1));</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; System.out.println(p2.equals(p3));</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; System.out.println(p1.eqauls(p3));</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">运行结果：</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">false</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">这种方法确实提供了对称性，但是却牺牲了传递性</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">按照约定，</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">p1.equals(p2)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">和</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">p2.eqauals(p3)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">都返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">p1.equals(p3)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">也应返回</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">true)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">。要怎么解决呢？事实上，这是面向对象语言中关于等价关系的一个基本问题。要想在扩展一个可实例化的类的同时，既要增加新的特征，同时还要保留</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">约定，没有一个简单的办法可以做到这一点。新的解决办法就是不再让</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">ColorPoint</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">扩展</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Point</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，而是在</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">ColorPoint</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">中加入一个私有的</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Point</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">域，以及一个公有的视图</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(view)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法：</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">public class ColorPoint{</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; private Point point;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; private Color color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public ColorPoint(int x, int y, Color color){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; point = new Point(x, y);</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.color = color;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; //</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">返回一个与该有色点在同一位置上的普通</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Point</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">对象</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public Point asPoint(){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return point;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp; public boolean equals(Object o){</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(o == this)</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!(o instanceof ColorPoint))</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ColorPoint cp = (ColorPoint)o;</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return cp.point.equals(point)&amp;&amp;</span></p>
<p style="layout-grid-mode: char; text-indent: 162pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">cp.color.equals(color);</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">}</span></p>
<p style="layout-grid-mode: char; text-indent: 24pt; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">还有另外一个解决的办法就是把</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Point</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">设计成一个抽象的类</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(abstract class)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">，这样你就可以在该抽象类的子类中增加新的特征，而不会违反</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">约定。因为抽象类无法创建类的实例，那么前面所述的种种问题都不会发生。</span></p>
<p style="layout-grid-mode: char; line-height: 150%; text-align: left" align="left"><span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 宋体">重写</span><span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; color: blue; line-height: 150%; font-family: 宋体">方法的诀窍：</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">1.&nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">==</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">操作符检查&#8220;实参是否为指向对象的一个引用&#8221;。</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">2.&nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">instanceof</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">操作符检查&#8220;实参是否为正确的类型&#8221;。</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">3.&nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">把实参转换到正确的类型。</span></p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; margin-right: 0px; text-align: left; tab-stops: list 42.0pt" align="left"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">4.&nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">对于该类中每一个&#8220;关键&#8221;域，检查实参中的域与当前对象中对应的域值是否匹配。对于既不是</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">float</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">也不是</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">double</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的基本类型的域，可以使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">==</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">操作符进行比较；对于对象引用类型的域，可以递归地调用所引用的对象的</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法；对于</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">float</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的域，先使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Float.floatToIntBits</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">转换成</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">int</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的值，然后使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">==</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">操作符比较</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">int</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的值；对于</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">double</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的域，先使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">Double.doubleToLongBits</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">转换成</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">long</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的值，然后使用</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">==</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">操作符比较</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">long</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">类型的值。</span><span style="font-size: 12pt; font-family: 宋体">&nbsp; </p>
<p style="margin-left: 42pt; layout-grid-mode: char; text-indent: -18pt; line-height: 150%; tab-stops: list 42.0pt"><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">5.&nbsp;</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">当你编写完成了</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法之后，应该问自己三个问题：它是否是对称的、传递的、一致的？</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">(</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">其他两个特性通常会自行满足</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">)</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">如果答案是否定的，那么请找到这些特性未能满足的原因，再修改</span><span style="font-size: 12pt; line-height: 150%; font-family: 'Courier New'">equals</span><span style="font-size: 12pt; line-height: 150%; font-family: 宋体">方法的代码。</span></p>
</span>
<img src ="http://www.blogjava.net/raulangcn/aggbug/164841.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raulangcn/" target="_blank">raulang</a> 2007-12-03 13:11 <a href="http://www.blogjava.net/raulangcn/articles/164841.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA基础之 详细解析抽象类和接口的区别</title><link>http://www.blogjava.net/raulangcn/articles/164022.html</link><dc:creator>raulang</dc:creator><author>raulang</author><pubDate>Thu, 29 Nov 2007 08:18:00 GMT</pubDate><guid>http://www.blogjava.net/raulangcn/articles/164022.html</guid><wfw:comment>http://www.blogjava.net/raulangcn/comments/164022.html</wfw:comment><comments>http://www.blogjava.net/raulangcn/articles/164022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/raulangcn/comments/commentRss/164022.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/raulangcn/services/trackbacks/164022.html</trackback:ping><description><![CDATA[　　abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制，正是由于这两种机制的存在，才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性，甚至可以相互替换，因此很多开发者在进行抽象类定义时对于abstract class和interface的选择显得比较随意。其实两者之间还是有很大的区别的，对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析，试图给开发者提供一个在二者之间进行选择的依据。<br />
<br />
<font size="2"><strong><font face="arial,helvetica,sans-serif">理解抽象类</font>&nbsp;</strong></font>
<p dir="ltr" style="margin-right: 0px" align="left"><font face="Arial" size="2">　　abstract和interface在Java语言中都是用来进行抽象类定义的，那么什么是抽象类，使用抽象类能为我们带来什么好处呢？</font><font face="times new roman,times,serif" size="3"><font size="2"><strong><br />
</strong></font></font></p>
<p dir="ltr" style="margin-right: 0px" align="left"><font face="Arial"></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif"></font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif"><strong>　　</strong>在面向对象的概念中，我们知道所有的对<font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">象都是通过类来描绘的，但是反过来却不是</font></font></font><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">这样</font></font></font></font></font></font><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">并不是所有的类都是用来描绘对象的，如果一个类中没有包含足够的信息来描绘一个具体的对象，这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念，是对一系列看上去不同，但是本质上相同的具体概念的抽象。比如：如果我们进行一个图形编辑软件的开发，就会发现问题领域存在着圆、三角形这样一些具体概念，它们是不同的，但是它们又都属于形状这样一个概念，形状这个概念在问题领域是不存在的，它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念，所以用以表征抽象概念的抽象类是不能够实例化的。&nbsp;<br />
<br />
　　在面向对象领域，抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽</font></font></font><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">象描述，但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类，而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体，因此它可以是不允许修改的；同时，通过从这个抽象体派生，也可扩展此模块的行为功能。熟悉OCP的读者一定知道，为了能够实现面向对象设计一个最核心的原则OCP(Open-Closed Principle)，抽象类是其中的关键所在。 <br />
<br />
<strong>从语法定义层面看abstract class和interface</strong>&nbsp;</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif"></font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　在语法层面，Java语言对于abstract class和interface给出了不同的定义方式，下面以定义一个名为Demo的抽象类为例来说明这种不同。 <br />
<br />
使用abstract class的方式定义Demo抽象类的方式如下： <br />
abstract class Demo ｛&nbsp;<br />
　　abstract void method1();&nbsp;<br />
　　abstract void method2();&nbsp;<br />
　　&#8230; <br />
｝ <br />
<br />
使用interface的方式定义Demo抽象类的方式如下：<br />
interface Demo {&nbsp;<br />
　　void method1();&nbsp;<br />
　　void method2();&nbsp;<br />
　　&#8230; <br />
}&nbsp;</font></font></font></p>
<p><font face="Arial" size="2"></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　在abstract class方式中，Demo可以有自己的数据成员，也可以有非abstarct的成员方法，而在interface方式的实现中，Demo只能够有静态的不能被修改的数据成员(也就是必须是static</font></font></font><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">&nbsp;final的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。从某种意义上说，interface是一种特殊形式的abstract class。&nbsp;<br />
</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　从编程的角度来看，abstract class和interface都可以用来实现"design by contract"的思想。但是在具体的使用上面还是有一些区别的。&nbsp;<br />
</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　首先，abstract class在Java语言中表示的是一种继承关系，一个类只能使用一次继承关系。但是，一个类却可以实现多个interface。也许这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。&nbsp;<br />
</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　其次，在abstract class的定义中，我们可以赋予方法的默认行为。但是在interface的定义中，方法却不能拥有默认行为，为了绕过这个限制，必须使用委托，但是这会增加一些复杂性</font></font></font><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">，</font></font></font><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">有时会造成很大的麻烦。&nbsp;<br />
</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　在抽象类中不能定义默认行为还存在另一个比较严重的问题，那就是可能会造成维护上的麻烦。因为如果后来想修改类的界面（一般通过abstract class或者interface来表示）以适应新的情况（比如，添加新的方法或者给已用的方法中添加新的参数）时，就会非常的麻烦，可能要花费很多的时间（对于派生类很多的情况，尤为如此）。但是如果界面是通过abstract class来实现的，那么可能就只需要修改定义在abstract class中的默认行为就可以了。&nbsp;<br />
</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　同样，如果不能在抽象类中定义默认行为，就会导致同样的方法实现出现在该抽象类的每一个派生类中，违反了"one rule，one place"原则，造成代码重复，同样不利于以后的维护。因此，在abstract class和interface间进行选择时要非常的小心。<br />
<br />
<strong>从设计理念层面看abstract class和interface</strong>&nbsp;</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif"></font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　上面主要从语法定义和编程的角度论述了abstract class和interface的区别，这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面：abstract class和interface所反映出的设计理念，来分析一下二者的区别。作者认为，从这个层面进行分析才能理解二者概念的本质所在。&nbsp;<br />
</font></font></font></p>
<p><font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">　　前面已经提到过，abstarct class在Java语言中体现了一种继承关系，要想使得继承关系合理，父类和派生类之间必须存在"is a"关系，即父类和派生类在概念本质上应该是相同的。对于interface来说则不然，并不要求interface的实现者和interface定义在概念本质上是一致的，仅仅是实现了interface定义的契约而已。</font></font></font></p>
<font face="times new roman,times,serif" size="3"><font size="2"><font face="arial,helvetica,sans-serif">
<p dir="ltr" style="margin-right: 0px" align="left">
<p dir="ltr" style="margin-right: 0px" align="left">　　考虑这样一个例子，假设在我们的问题领域中有一个关于Door的抽象概念，该Door具有执行两个动作open和close，此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型，定义方式分别如下所示： <br />
<br />
使用abstract class方式定义Door： <br />
abstract class Door {&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　abstract void open();&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　abstract void close()； <br />
}&nbsp;<br />
&nbsp; <br />
使用interface方式定义Door：<br />
interface Door {&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void open();&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void close(); <br />
}&nbsp;&nbsp;&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢？下面将罗列出可能的解决方案，并从设计理念层面对这些不同的方案进行分析。 <br />
<br />
<strong>解决方案一：</strong> <br />
<br />
简单的在Door的定义中增加一个alarm方法，如下： <br />
abstract class Door {&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　abstract void open();&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　abstract void close()；&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　abstract void alarm(); <br />
}&nbsp;&nbsp; <br />
或者 <br />
interface Door {&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void open();&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void close();&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void alarm(); <br />
}&nbsp;<br />
&nbsp; <br />
那么具有报警功能的AlarmDoor的定义方式如下：<br />
class AlarmDoor extends Door {&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void open() { &#8230; }&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void close() { &#8230; }&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void alarm() { &#8230; } <br />
}&nbsp;&nbsp; <br />
或者 <br />
class AlarmDoor implements Door ｛&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void open() { &#8230; }&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void close() { &#8230; }&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void alarm() { &#8230; } <br />
｝&nbsp;<br />
</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　&nbsp;这种方法违反了面向对象设计中的一个核心原则ISP(Interface Segregation Priciple),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在一起。这样引起的问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变（比如：修改alarm方法的参数）而改变。 <br />
<br />
<strong>解决方案二：</strong>&nbsp;　　</p>
<p dir="ltr" style="margin-right: 0px" align="left">
<p dir="ltr" style="margin-right: 0px" align="left">
<p dir="ltr" style="margin-right: 0px" align="left">　　既然open、close和alarm属于两个不同的概念，根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有：这两个概念都使用abstract class方式定义；两个概念都使用interface方式定义；一个概念使用abstract class方式定义，另一个概念使用interface方式定义。&nbsp;<br />
</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　显然，由于Java语言不支持多重继承，所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的，但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理, 我们一一来分析、说明。&nbsp;<br />
</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　如果两个概念都使用interface方式来定义，那么就反映出两个问题：1、我们可能没有理解清楚问题领域，AlarmDoor在概念本质上到底是Door还是报警器？2、如果我们对于问题领域的理解没有问题，比如：我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的，那么我们在实现时就没有能够正确的揭示我们的设计意图，因为在这两个概念的定义上（均使用interface方式定义）反映不出上述含义。&nbsp;<br />
</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　如果我们对于问题领域的理解是：AlarmDoor在概念本质上是Door,，同时它有具有报警的功。我们该如何设计实现来明确的反映出我们的意思呢?前面已经说过abstract class在Java语言中表示一种继承关系，而继承关系在本质上是"is a"关系。所以对于Door这个概念，我们应该使用abstarct class方式来定义。另外AlarmDoor又具有报警功能，说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义. 如下所示：<br />
abstract class Door {&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　abstract void open();&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　abstract void close()； <br />
} <br />
interface Alarm {&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void alarm(); <br />
} <br />
class AlarmDoor extends Door implements Alarm {&nbsp;<br />
　　void open() { &#8230; }&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void close() { &#8230; }&nbsp;</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　void alarm() { &#8230; } <br />
}&nbsp;<br />
</p>
<p dir="ltr" style="margin-right: 0px" align="left">　　这种实现方式基本上能够明确的反映出我们对于问题领域的理解，正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系，interface表示的是"like a"关系，大家在选择时可以作为一个依据，当然这是建立在对问题领域的理解上的，比如：如果我们认为AlarmDoor在概念本质上是报警器，同时又具有Door的功能，那么上述的定义方式就要反过来了。</p>
<p>
<p><strong>结论</strong></p>
<p>　　abstract class和interface是Java语言中的两种定义抽象类的方式，它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理，因为它们表现了概念间的不同的关系（虽然都能够实现需求的功能）。这其实也是语言的一种的惯用法，希望读者朋友能够细细体会。</font></font></font></p>
<img src ="http://www.blogjava.net/raulangcn/aggbug/164022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/raulangcn/" target="_blank">raulang</a> 2007-11-29 16:18 <a href="http://www.blogjava.net/raulangcn/articles/164022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>