泛型类型中的方法冲突问题

heartraid86 2009-12-16 08:29:44
class Pair<T>{
//数据域
private T first=null;
//构造器
Pair(T fir){
this.first=fir;
}
//equals方法
public boolean equals(T value){ //错误所在,T如果改成Object或者换一个equals名字就没问题了
return first.equals(value);
}
}


编译器一直认为equals(T value)有错误:Name clash: The method equals(T) of type Pair<T> has the same erasure as equals(Object) of type Object but does not override it

我查了一些资料,<Core Java edit 7 Volume 1 中文版>P672说这是因为类型擦除引起的。

我知道编译器会用Object类替代Pair<T>中的类型变量T,这样equals方法实际上就变成了:
public boolean equals(Object value){
return first.equals(value);
}

而且Object类中的equals方法 boolean equals(Object o)也是相同的方法签名和返回类型。

这不正好Pair<T>可以覆盖Object类中的equals方法吗,为什么会出现方法冲突呢????

而且为什么编译器报错认为,Pair<T>中的equals(T)方法擦除后与Object类型中的equals(Object)相同但却没有覆盖呢?
...全文
336 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
heartraid86 2009-12-19
  • 打赏
  • 举报
回复
楼上的有的道理

本来equals(T value)逻辑上也说不通
拿Pair<T>对象 equals T对象 -》 牛头 对比 马嘴 哈哈
shine333 2009-12-17
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 bayougeng 的回复:]
是一个很有意思的问题。
你应该明确你的目的,是想重写还是不想重写。
如果想重写的话,那类型必须与Object的equals方法保持一致。
如果不想重写的话,那类型必须严格的与Object类的equals的参数区分开来(比如,让你的T extends Integer)。
类型擦除应该发生在重载上,而不是重写上。
[/Quote]
正解。

覆盖(Override)父类的方法,必须保证子类方法的可访问性>=父类方法的可访问性,也就是按照父类的方法签名来访问子类
Parent p = new Child(); p.foo();
,一定可以成功,比如一下例子是合法的:
class A {
void foo() throws Exception;
}
class B extends A {
// IOE是Exception的子类,任何针对Exception的catch处理、throws声明都对IOE有效
void foo() throws IOException;
}
class C extends A {
// 通过default类型方式能够访问,必然能够通过public访问
public void foo();
}


而你的代码假如能够编译成功:
Object o = "abcd";
o.equals(new Date()); // false,
Object p = new Pair<String>();
p.equals(new Date()); // 无法运行
poFate 2009-12-17
  • 打赏
  • 举报
回复
好像和泛型的擦除有点关系,你去看看这方面的资料的吧,这块还不是太熟悉
njzdl 2009-12-17
  • 打赏
  • 举报
回复

这不正好Pair <T>可以覆盖Object类中的equals方法吗,为什么会出现方法冲突呢????

<T>是泛型, 不是特定的类, 和Object类不同
bayougeng 2009-12-17
  • 打赏
  • 举报
回复
是一个很有意思的问题。
你应该明确你的目的,是想重写还是不想重写。
如果想重写的话,那类型必须与Object的equals方法保持一致。
如果不想重写的话,那类型必须严格的与Object类的equals的参数区分开来(比如,让你的T extends Integer)。
类型擦除应该发生在重载上,而不是重写上。
  • 打赏
  • 举报
回复
楼主这个是你发的么
http://www.javaeye.com/topic/549509
heartraid86 2009-12-17
  • 打赏
  • 举报
回复
顶一下,都看不见了。
yjailj 2009-12-17
  • 打赏
  • 举报
回复
个人觉得应该是 JVM 编译时的[color=#003300] 顺序 导致的错误[/color]

JVM 在编译 java 文件时,先检查语法. 发现有 equals(T) 方法,此时 T 还没有被擦除成 Object. 与父类的 equals(Object) 不同

所以 JVM 认为此方法是 重载

然后泛型在擦除过程中 T 被转换成了 Object .此时 JVM 就开始混乱,因为之前是当成方法重载来处理 equals 方法.这样会导致对象在调用 equals() 时不明确应该调用谁的

JVM 为确保代码安全, 所以报错

这觉得这里应该这样写:
public boolean equals(Pair<T> value){
return first.equals(value);
}


能够确保 Pair<T> 一定是一个 Object
heartraid86 2009-12-17
  • 打赏
  • 举报
回复
感谢大家,特别是3#,6#的朋友。
受教了,自己原来是知道要覆盖父类方法,方法签名一定要一样。只是觉得泛型擦除会帮助我们使得方法签名一样。结果编译器并不这么认为,哈哈。可以结贴了。

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧