程序如下:
import java.util.*;
class Test2{
int i; Test2(int i)
{
this.i=i;
} int geti()
{
return i;
} public String toString()
{
return Integer.toString(i);
} public boolean equals(Test2 p)
{
return p.geti()==this.i;
}
}
class Test
{
public static void main(String [] args){
ArrayList <Test2> strList=new ArrayList<Test2>();
Test2 pp=new Test2(0);
strList.add(new Test2(1));
strList.add(new Test2(2));
strList.add(new Test2(3));
strList.add(pp);
System.out.println(pp.equals(new Test2(0)));
System.out.println(strList.indexOf(new Test2(1)));
System.out.println(strList.indexOf(pp));
System.out.println(strList);
}
}问题:红色的两行代码,为什么第一行能够返回true,而第二行不能返回index值?equals方法重载后想实现以值来比较两个对象是否相等,这样写对吗?
import java.util.*;
class Test2{
int i; Test2(int i)
{
this.i=i;
} int geti()
{
return i;
} public String toString()
{
return Integer.toString(i);
} public boolean equals(Test2 p)
{
return p.geti()==this.i;
}
}
class Test
{
public static void main(String [] args){
ArrayList <Test2> strList=new ArrayList<Test2>();
Test2 pp=new Test2(0);
strList.add(new Test2(1));
strList.add(new Test2(2));
strList.add(new Test2(3));
strList.add(pp);
System.out.println(pp.equals(new Test2(0)));
System.out.println(strList.indexOf(new Test2(1)));
System.out.println(strList.indexOf(pp));
System.out.println(strList);
}
}问题:红色的两行代码,为什么第一行能够返回true,而第二行不能返回index值?equals方法重载后想实现以值来比较两个对象是否相等,这样写对吗?
test2 tt = new test2(1);
System.out.println(strList.indexOf(tt));
Test2 t1 = new Test2(1);
Test2 t2 = new Test2(2);
List list = new ArrayList();
list.add(t1);
list.add(t2);
Test2 t3 = new Test2(2);
System.out.println(list.indexOf(t1));刚才试了一下,这样好像能找到原因可能是因为NEW一个对象后,已是一个新的对象引用了。。
在运行期只是Object,equals比较没法相等。
你看看object的equals方法的参数是什么,是object而不是Test2,你只是
重载了该方法。
返回:
(o==null ? get(i)==null : o.equals(get(i)))
因为你没有重写equals,所以这里调用的依然是
object的equals方法,所以没有该值!
怎么会有类型擦除没有关系?这完全就是类型擦除引起的。
因为list中的元素在运行时失去了Test2类型,而变成了Object类型。
所以indexOf时调用的equals(Object o)而不是equals(Test2 t).
而没有重新实现的equals(Object o)仅比较句柄相同,new对象肯定不相等,所以indexOf返回-1而本楼的代码因为在运型期有确定的类型,所以调用的是equals(Test2 t)所以能找到。这根本就是因为泛型在运行期失去了原始类型引起的,竟然叫没有关系?
{
if(this==p){
return true;
}
if(p==null){
return false;
}
if(p.getClass()==this.getClass()){
Test2 t=(Test2)p;
return t.geti()==this.i;
}else{
return false;
}
}
true
0
3
[1, 2, 3, 0]
public boolean equals(Object p)
{
Test2 uu=(Test2)p;
return uu.geti()==this.i;
}
顺便问一下,那个hashcode跟equals联系很紧密吗?
10楼和11楼都是高手
但这里他没有控制储参数类型的匹配,把失去原始类型的对象传进去了。
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;
}
即覆盖Object的实现。和楼主的主题不是一回事了。只是为了防止类型丢失时也能正确工作,在重载equals时要将原来的equals和重载后的euqals有共同的行为。
但重在一个强类型的equals在有时是必要的,在强类型下可以获得较大的性能。
语句为什么得到Test2这个结果呢?这说明list里面的对象没有丢失自己的类型啊,应该调用我重载的equals方法啊,也就是楼上说的强类型的equals方法啊,否则怎么防止类型丢失?最好写出来代码看看啊
即在容器中其实是list中其实是Object o1 = new Test2();
所以调用了你的equals(Object o)的版本的方法。
但在一个对象上调用方法时,是动态绑定的,也就是多态性在保证它getClass()的方法是实际对象的。其实你只要在外面试一下就行了:Object o = new Test2(100);Test2 t = new Test2(100);
t.equals(o);//调用原始版本。
o.equals(t);调用你的重载版。
至于如何保证类型在泛型中不丢失?没有方法,泛型 就是在编译期实现的,运行期被擦除了。除非你用数组,
它是协变类型的。