1.问题的提出
我们给定下面这样一段代码,拟定一副扑克牌,然后让它们之间进行比较
代码示例:
class Card {
public int rank;//数值
public String suit;//花色
public Card (int rank,String suit) {
this.rank = rank;
this.suit =suit;
}
}
public class TestDemo1 {
public static void main(String[] args) {
Card card1 = new Card(1,"♥");
Card card2 = new Card(2,"♥");
System.out.println(card1.equals(card2));
}
}
之前在学习基本类型的时候,我们知道比较两个基本数据类型大小关系的时候,直接可以使用我们的运算符来(>,<,==)进行比较,但是对于我们上面的自定义类型来说,要比较 card1 和 card2 的大小关系我们可不可以直接用运算符来比较他们呢?
答案肯定是不行,因为我们知道 card1 和 card2 他们两个属于引用类型,按照我们人的思想来说 card2 肯定是大于 card1的,因为我们人的大脑通过比较两个牌的数值去判断它们的大小,但是在Java中我们直接使用大于或者小于号去比较编译器会直接报错,如果使用等于号去进行比较,那么比较的只是两个引用所保存的内存地址而已,那么我们应该怎么去进行比较呢?
我们可以回想一下之前在学习String类型的时候有一个方法叫作 equals 方法,那么我们现在试着用equals方法来对 card1和card2来进行比较
2.对象的比较
2.1 基于equals比较
public static void main(String[] args) {
Card card1 = new Card(1,"♥");
Card card2 = new Card(1,"♥");
System.out.println(card1.equals(card2));
}
我此时想要的结果是得到一个 true,但是真正当我们运行的时候,结果却是一个false,那么这是为什么呢?
false
我们先来定义两个字符串
String s1 = "hello";
String s2 = new String("hello");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
我们肯定知道输出结果为 false 和 true,但是为什么刚刚在我们使用equals比较自定义类型的时候没有达到我们的预期结果,我们可以通过CTRL+鼠标左键点击String的equals方法来看看它到底是怎么实现的
我们可以看到String里面的equals方法它是通过将两个字符串拆成一个个字符来进行比较的,那么有的小伙伴可能会说,之所以我们自定义类型不能通过equals来进行比较是因为他们不是String类型,这种说法是错误的,我们也可以通过同样的方法来看看我们自定义类型使用的equals是什么样子
我们可以看到我们自定义类型所使用的equals方法是Object中的,它此时所比较的也是两个对象的引用,这也就是为什么我们会得到false的原因了,而我们已经知道我们所有的类都是默认继承于我们Object类,那么这也就是说,我们可以用过重写Object类中equals方法来为我们的自定义类型服务,具体我们可以借鉴String中重写的equals方法
代码示例:
@Override
public boolean equals(Object obj) {
//引用同一个对象
if (this == obj) return true;
//obj instanceof Card obj是否为Card的实例
//obj可以是Card的子类,也可以是本身
if (obj == null || !(obj instanceof Card)) return false;
Card card = (Card) obj;
if (this.rank == card.rank && this.suit.equals(card.suit)) {
return true;
}
return false;
}
现在我们再来运行刚刚的代码,就能得到我们想要的结果 true
true
因此我们可以总结出一点:如果自定义类型要进行equals比较的时候,必须要记得重写equals方法,当然在后面的学习里我们还要重写一个方法,具体在后面讲
2.2 基于Comparable接口类的比较
刚刚我们讲了通过重写equals方法来判断两个自定义类型是否相等,如果要进行大于小于的比较呢?我们之前讲过一个接口 Comparable,我们可以通过实现它来进行我们所需要的比较
代码示例:
class Card implements Comparable<Card> {
public int rank;
// 数值
public String suit;
// 花色
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
//返回值等于0 相等
//返回值大于0 this大
//返回值小于0 o大
@Override
public int compareTo(Card o) {
return this.rank - o.rank;
}
}
public static void main(String[] args) {
Card card1 = new Card(1,"♥");
Card card2 = new Card(5,"♥");
Card card3 = new Card(1,"♥")
System.out.println(card1.compareTo(card2));
System.out.println(card2.compareTo(card1));
System.out.println(card1.compareTo(card3));
}
运行结果:
-4
4
0
此时大于就是返回一个大于0的数字,小于返回一个小于0的数字,等于就返回一个0
我们再自定义一个学生类
代码示例:
class Student {
public int age;
public String name;
public double score;
public Student(int age, String name, double score) {
this.age = age;
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", score="