母鸡孵出小鸭子 --说说List的contains(Object o)方法.
母鸡孵出小鸭子
说说List的contains(Object o)方法.
在编码时遇到这样一个问题:
?? ?Excel文件中有如下记录:
?? ??? ?Title?? ??? ?Name?? ?Note
?? ??? ?Manager?? ??? ?Lincon?? ?afjdksal
?? ??? ?Coder?? ??? ?Clinton?? ?arueiwqo
?? ??? ?Designer?? ?Wend?? ?zmvcx
?? ??? ?......?? ??? ???????? ..........?? ?..........
?? ??? ?......?? ??? ???????? ..........?? ?..........
?? ?对应的文件结构是这样的:
?? ?--parentfolder:
?? ??? ?--folder1:
?? ??? ??? ?manager&Lincon.mid
?? ??? ??? ?coder&clinton.mid
?? ??? ??? ?designer&wend.mid
?? ??? ??? ?.......................
?? ??? ?--folder2:
?? ??? ??? ?manager&Lincon.mp3
?? ??? ??? ?coder&clinton.mp3
?? ??? ??? ?designer&wend.mp3
?? ??? ??? ?.......................
?? ??? ?--folder3:
?? ??? ??? ?manager&Lincon.rm
?? ??? ??? ?coder&clinton.rm
?? ??? ??? ?designer&wend.rm
?? ??? ??? ?.......................
要求通过对excel文件的解析,判断出一条记录在三个子文件中有否有对应的audio文件存在.
先写了两个类来描述这两种现象:ExcelRecord和FileName
这怎么来判断呢?......后来边想边写,总不能自己用多层循环来查找吧.......后来突然想到用List这个接口里的contains()方法了,但以住用这个contains()方法里,所判断可都是同一个类有对象呀.于是想到让这两个类都继承自同一个父类NameInfo.这样在定义List对象时用List<NameInfo>,调用contains时就达到以前所常见的那种情景了.
?
?? (期间想过让这个两个类ExcelRecord和FileName实现一个接口,如INameInfo,在定义List时这样写List<INameInfo>,似乎也可以达到那种效果.可后来一想,这里用contains是最终想利用覆盖Object类的那个equals来判断,可INameInfo接口又不能覆盖Object的equals方法,就没有往下多想就否掉了这个想法.不过,这样的一个念头让我想起了Serializable这样标签接口的应用.)
有了以上的想法就开始往下写了,在定义List<NameInfo> records时,想着让它里面放进去ExcelRecord类的对象,这样只要覆盖了ExcelRecord类的equals()方法可以达到判的效果了.
写完后没有用JUnit手动地写一个main来测试,发现不行!这是怎么回事?用Debug来跟踪代码的执行情况,有了惊天大发现:
?? ?public boolean contains(Object o) {
?? ??? ?return indexOf(o) >= 0;
?? ?}
?? ?public int indexOf(Object o) {
?? ??? ?if (o == null) {
?? ??? ???? for (int i = 0; i < size; i++)
?? ??? ??? ?if (elementData[i]==null)
?? ??? ??? ???? return i;
?? ??? ?} else {
?? ??? ???? for (int i = 0; i < size; i++)
?? ??? ??? ?if (o.equals(elementData[i]))
?? ??? ??? ???? return i;
?? ??? ?}
?? ??? ?return -1;?? ?
?? ?}
原来contains在调用eqauls方法时是这样调用的:o.equals(elementData[i])的,而不是以前所想像的那样elementData[i].equals(o)!
这样就根本没有必要让这个两个类(ExcelRecord,FileName)继承同一个父类NameInfo了.再进一步想,也就是说只要FileName类很好地覆盖了Object类的equals方法,ExcelRecord的List里就认可了FileName的存在.
(转而一想,当初Sun的设计师在设计这个contains方法的实现时是很随意在设计成现在的o.equals(elementData[i])这样呢,还是以前已有前车之鉴了呢?越来越感受到高手的伟大了.)
也就是说只要DuckEgg这个类很好地覆盖Object的equals方法,hen(hen为List<HenEgg>的实例)在调用contains时就会认为DuckEgg与HenEgg是一样的,小鸭子就可以由母鸡来孵出了.
?? ?
1 楼 steven_cheng 2008-03-26 我倒....
equals方法必须满足对称性,也即是说:
o.equals(elementData[i])等价于elementData[i].equals(o)
你是可以让母鸡孵出小鸭子,但是有可能造成鸡飞蛋打:),因为这样做违反了java语言关于equals方法的约束