<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    讀《effective java》學習筆記三

    第六條 在改寫equals的時候請遵守通用規定
      有一種“值類”可以不要求改寫equals方法,類型安全枚舉類型,因為類型安全枚舉類型保證每一個值之多只存在一個對象,所有對于這樣的類而言,Object的queals方法等同于邏輯意義上的equals方法。
     
      在改寫equals方法的時候,要遵循的規范: 
            1,自反性。對任意的引用值x,x.equals(x)一定是true
            2,對稱性。對于任意的引用值x和y,當且僅當y.equals(x)返回true時,x.equals(y)也一定返回true.
            3,傳遞性。對于任意的引用值x,y和z,如果x.equals(y)==true and y.equals(z)==true,so x.equals(z)==true.
            4,一致性。對于任意的引用值x和y,如果用于equals比較的對象信息沒有被修改的話,那么,多次調用x.equals(y)要么一致地返回true,要么一致地返回false.
            5,非空性。對于任意的非空引用值x,x.equals(null)一定返回false.
            
      自反性:要求一個對象必須等于其自身。一個例子:你把該類的實例加入到一個集合中,則該集合的contains方法
    將果斷地告訴你,該集合不包含你剛剛加入的實例. 

      對稱性:
      例如:
         public final class CaseInsensitiveString{
               private String s;
               public CaseInsensitiveString(String s){
                  if(s==null)   throw new NullPointerException();
                  this.s=s;
               }
               public boolean equals(Object o){
                  if(o instanceof CaseInsensitiveString)
                     return s.equalsIgnoreCase(((CaseInsensitiveString)o).s);
                  if(o instanceof String)
                     return s.equalsIgnoreCase((String)o);
                   return false;
                }
              }
    調用:
       CaseInsensitiveString cis=new CaseInsensitiveString("Polish");
           String s="polish";
    正如我們期望的:cis.equals(s)==true but s.equals(cis)==false
    這就違反了對稱性的原則.為了解決這個問題,只需把企圖與String互操作的這段代碼從equals方法中去掉舊可以了.這樣做之后,你可以重構代碼,使他變成一條返回語句:
    public boolean equals(Object o){
       return o instanceof CaseInsensitiveString && ((CaseInsensitiveString)o).s.equalsIgnoreCase(s);
    }

     

    傳遞性---即如果一個對象等于第二個對象,并且第二個對象又等于第三個對象,則第一個對象一定等于第三個對象。
    例如:
           public class Point{
               private final int x;
               private final int y;
               public Point(int x,int y){
                    this.x=x;
                    this.y=y;
              }
              public boolean equals(Object o){
                 if(!(o instanceof Point))
                  return false;
                 Point p=(Point)o;
                 return p.x==x&&p.y==y;
              }
         }
    現在我們來擴展這個類,為一個點增加顏色信息:
       public class ColorPoint extends Point{
          private Color color;
          public ColorPoint(int x,int y,Color color){
              super(x,y);
              this.color=color;
          }
       }
    分析: equals方法會怎么樣呢?如果你完全不提供equals方法,而是直接從Point繼承過來,那么在equals座比較的時候顏色信息會被忽略掉。如果你編寫一個equals方法,只有當實參是另一個有色點,并且具有同樣的位置和顏色的時候,它才返回true:
           public boolean equals(Object o){
              if(!(o instanceof ColorPoint)) return false;
              ColorPoint cp=(ColorPoint)o;
              return super.equals(o) && cp.color==color;
           }
    分析:這個方法的問題在于,我們在比較一個普通點和一個有色點,以及反過來的情形的時候,可能會得到不同的結果。前一種比較忽略了顏色信息,而后一種比較總是返回false,因為實參的類型不正確。例如:
         Point p=new Point(1,2);
         ColorPoint cp=new ColorPoint(1,2,Color.RED);
    然后:p.equals(cp)==true but cp.equals(p)==false

    修正:讓ColorPoint.equals在進行“混合比較”的時候忽略顏色信息:
       public boolean equals(Object o){
           if(!(o instanceof Point)) return false;
           if(!(o instanceof ColorPoint)) return o.equals(this);
           ColorPoint cp=(ColorPoint)o;
           return super.equals(o) && cp.color==color;
       }
    這種方法確實提供了對稱性,但是卻犧牲了傳遞性:
       ColorPoint p1=new ColorPoint(1,2,Color.RED);
       Point p2=new Point(1,2);
       ColorPoint p3=new ColorPoint(1,2,Color.BLUE);
    此時:p1.equals(p2)==true and p2.equals(p3)==true but p1.equals(p3)==false很顯然違反了傳遞性。前兩個比較不考慮顏色信息,而第三個比較考慮了顏色信息。

    結論:要想在擴展一個可實例華的類的同時,既要增加新的特征,同時還要保留equals約定,沒有一個簡單的辦法可以做到這一點。根據"復合優于繼承",這個問題還是有好的解決辦法:我們不讓ColorPoint擴展Point,而是在ColorPoint中加入一個私有的Point域,以及一個公有的視圖方法,此方法返回一個與該有色 點在同一位置上的普通Point對象:
        public class ColorPoint{
           private Point point;
           private Color color;
           public ColorPoint(int x,int y,Color color){
             point=new Point(x,y);
             this.color=color;
           }
           public Point asPoint(){
               return point;
           }
         
           public boolean equals(Object o){
               if(!(o instanceof ColorPoint)) return false;
               ColorPoint cp=(ColorPoint)o;
               return cp.point.equals.(point) && cp.color.equals(color);
           }
        }
       
    注意,你可以在一個抽象類的子類中增加新的特征,而不會違反equals約定。

     

    一致性:
     如果兩個對象相等的話,那么它們必須始終保持相等,除非有一個對象被修改了。由于可變對象在不同的時候可以與不同的對象相等,而非可變對象不會這樣,這個約定沒有嚴格界定。
     


    非空性:沒什么好說的。

    1,使用==操作符檢查“實參是否為指向對象的一個應用”。如果是的話,則返回true。
           2,使用instanceof操作符檢查“實參是否為正確的類型”。如果不是的話,則返回false。
           3,把實參轉換到正確的類型。
           4,對于該類中每一個“關鍵(significant)”域,檢查實參中的域與當前對象中對應的域值是否匹配
         if (!(this.field == null ? o.field == null : this.equals(o.field)))
         //或者寫成 if(!(this.field == o.field || (this.field != null && this.field.equals(o.field)))) 對于this.field和o.field通常是相同的對象引用,會更快一些。
           return false;
         //比較下一個field
         //都比較完了
         return true;
         
    5.最后還要確認以下事情
       5.1)改寫equals的同時,總是(必須)要改寫hashCode方法(見【第8條】),這是極容易被忽略的,有極為重要的
       5.2)不要企圖讓equals方法過于聰明
       5.3)不要使用不可靠的資源。如依賴網絡連接
       5.4)不要將equals聲明中的Object對象替換為其他類型。
             public boolean equals(MyClass) 這樣的聲明并不鮮見,往外使程序員數小時搞不清楚為什么不能正常工作
             原因是這里是重載(overload)而并不是改寫(override)(或稱為覆蓋、重寫)
             相當于給equals又增加了一個實參類型為MyClass的重載,而實參為Object的那個equals并沒有被改寫,依然還是從Object繼承來的最初的那個equals,所總是看不到程序員想要的效果。因為類庫或其他人寫的代碼都是調用實參為Object型的那個equals方法的(別人又如何在事前知曉你今天寫的MyClass呢?)

    posted on 2009-07-28 20:30 胡鵬 閱讀(220) 評論(0)  編輯  收藏 所屬分類: 讀《effective java》筆記

    導航

    <2009年7月>
    2829301234
    567891011
    12131415161718
    19202122232425
    2627282930311
    2345678

    統計

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    agile

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产成人va亚洲电影| 亚洲福利一区二区| 色www永久免费视频| 四虎影在线永久免费观看| 中文字幕在亚洲第一在线| 成人一级免费视频| 亚洲精品和日本精品| 亚洲视频国产视频| 亚洲大片免费观看| 日本高清免费网站| 亚洲激情黄色小说| 久久午夜免费视频| 久久亚洲国产成人影院网站 | 免费看黄网站在线看| 亚洲国产精品狼友中文久久久| 亚洲高清中文字幕| 97国产免费全部免费观看| 91在线亚洲综合在线| 国产免费午夜a无码v视频| 一区二区三区AV高清免费波多| 久久影视综合亚洲| 伊人久久免费视频| 亚洲国产精品13p| 三上悠亚在线观看免费| 91亚洲导航深夜福利| 日本一线a视频免费观看| fc2免费人成在线视频| 国产女高清在线看免费观看| 一区二区在线视频免费观看| 亚洲av无码片在线播放| 中文字幕无码不卡免费视频| 亚洲无删减国产精品一区| 9久9久女女免费精品视频在线观看| 精品亚洲成A人在线观看青青| 亚洲一区二区三区偷拍女厕 | 国产亚洲成av人片在线观看 | 国产极品美女高潮抽搐免费网站| 人妻巨大乳hd免费看| 亚洲第一页中文字幕| 免费va人成视频网站全| 亚洲精品人成网线在线播放va |