所以我的泛型代码有问题。我创建了类Person,Student扩展了Person。当我试图比较两个学生时,它突然认为它是一个人,甚至没有包括组号。这是我的Person类
public class Person implements Comparable<Person>{...
public int compareTo(Person o) {
if(this.name.compareTo(o.name) > 0 )
return 1;
else if(this.name.compareTo(o.name) < 0)
return -1;
else{
if(this.age > o.age)
return 1;
else if(this.age < o.age)
return -1;
else{
return 0;}
}
}
我的学生,其中compareTo似乎非常相似,但附加了组ID
public class Student extends Person implements Comparable<Person>{
public int compareTo(Student s) {
if(this.name.compareTo(s.name) > 0 ){
System.out.println(this + " > " + s);
return 1;}
else if(this.name.compareTo(s.name) < 0){
System.out.println(this + " < " + s);
return -1;}
else{
if(this.age > s.age){
System.out.println(this + " > " + s);
return 1;}
else if(this.age < s.age){
System.out.println(this + " < " + s);
return -1;}
else{
if(groupId > s.groupId){
System.out.println(this + " > " + s);
return 1;
}
else if(groupId < s.groupId){
System.out.println(this + " < " + s);
return -1;}
else{
System.out.println(this + " = " + s);
return 0;}
}
}
}
最后是一个Box类,它使用泛型来查找这些类和其他类型的最大值和最小值。
public class Box<T extends Comparable> extends ArrayList<T> {
public T min() {
T t = get(0);
for(int i = 0; i < this.size(); i++){
if(t.compareTo(get(i)) > 0)
t = super.get(i);
}
return t;
}
}
我没有向您展示整个代码,但我认为这已经足够了。我已经制作了Box对象,但仍将它们作为Person而不是Student进行比较。 谁能解释一下这里的问题是什么? 编辑:我的数组
Box<Student> bst = new Box<>();
bst.add(new Student("Nowacka", 24, 100));
bst.add(new Student("Nowacka", 24, 300));
bst.add(new Student("Nowacka", 24, 200));
bst.print();
System.out.println(bst.max()); // Student: Nowacka, 24, 300
答案应该是300,但是是100并且在人的比较中我已经添加了一些System.out.println以查看它正在使用的方法
答案 0 :(得分:1)
让我们分析Comparable<T>
实际需要和做的事情。如果SomeClass implements Comparable<T>
,您将被迫实施方法public int compareTo(T other)
。 T
将在一秒钟内变得重要,保持在他的脑后。这就是您对Person
- 类所做的事情:
public class Person implements Comparable<Person> {
// ...
public int compareTo(Person o) {
if (this.name.compareTo(o.name) > 0 ) {
return 1;
} else if (this.name.compareTo(o.name) < 0) {
return -1;
}
else {
if (this.age > o.age) {
return 1;
} else if (this.age < o.age) {
return -1;
} else {
return 0;
}
}
}
现在,让我们检查Student
- 类:
public class Student extends Person implements Comparable<Person>{
public int compareTo(Student s) {
...
}
}
我们实施Comparable<Person>
,但我们没有public int compareTo(Person p)
,我们只有public int compareTo(Student s)
。那为什么要编译呢?因为我们从public int compareTo(Person p)
继承Person
。方法public int compareTo(Student s)
实际上从未使用过,至少在Comparable<Person>
接口的上下文中没有使用过。
那么,让我们public class Student extends Person implements Comparable<Student>
!遗憾的是,编译器不喜欢这样。我们不能使用不同的类型参数多次实现相同的通用接口。我们被卡住。只要在对象层次上实现Comparable
,我们就无法重新实现它。
很有可能覆盖compareTo(...)
方法。但是,这将违反Comparable
:
实施者必须确保所有
sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
和x
y
。 (这意味着如果x.compareTo(y)
抛出异常,y.compareTo(x)
必须抛出异常。)实现者还必须确保关系具有传递性:
(x.compareTo(y) > 0 && y.compareTo(z) > 0)
隐含x.compareTo(z) > 0
。最后,实施者必须确保
x.compareTo(y) == 0
隐含所有sgn(x.compareTo(z)) == sgn(y.compareTo(z))
的{{1}}。
让我们尽量不破坏合同。 z
类的可能实现可能如下所示:
Student
但是这个解决方案也打破了// CAUTION! This implementation is BROKEN! Keep reading to learn why.
public class Student extends Person {
@Override
public int compareTo(Person that) {
int comp = super.compareTo(that);
if (comp == 0 && that instanceof Person == true) {
Student thatStuden = ((Student) that);
comp = ...
}
return comp;
}
}
合同的一部分:
最后,实施者必须确保
Comparable
隐含所有x.compareTo(y)==0
的{{1}}。
以不太正式的方式说,如果sgn(x.compareTo(z)) == sgn(y.compareTo(z))
和z
两件事相等(x
),那么我是否比较{{1}并不重要或y
或其他内容,结果必须相同(x.compareTo(y) == 0
1 )。&#34;
我们怎样才能打破它?我们假设我们有两个x
s y
和x.compareTo(z) == y.compareTo(z)
Student
。让我们进一步假设我们有s1
人s2
和s1.compareTo(s2) != 0
。由于p3
和p3.compareTo(s1) == 0
,合同要求p3.compareTo(2) == 0
。这是一个矛盾。
Comparator<T>
的形式有另一种选择。您将排序条件与实际对象分开。
对于您的示例,它可能如下所示:
p3.compareTo(s1) == 0
<强>确认强>
我最初认为应该可以以不违反合同的方式转发p3.compareTo(s2) == 0
。但@ user2357112教我相反=)。谢谢你指出我的两个错误!
1 为了便于阅读,我忽略了s1.compareTo(s2) == 0
。
答案 1 :(得分:0)
我认为它们将它们比作Person
,因为您已在Comparable<Person>
类中实施Student
:
public class Student extends Person implements Comparable<Person>
尝试替换
public class Student extends Person implements Comparable<Student>