详解Java中==和equals()的区别
作者:Code花卷
1. ==
== 是运算符,用来判断两个值是否相等,==可以使用在基本数据类型变量和引用数据类型变量中
1.1 基本数据类型
Java基本数据类型共有八种,可以分为三类
- 字符类型char
- 布尔类型boolean
- 数值类型byte、short、int、long、float、double
这里有个例外,boolean不参与数值运算
int a1 = 10; int a2 = 10; System.out.println(a1==a2); //true float a3 = 5.0f; float a4 = 5.0f; System.out.println(a3==a4); //true ……
上面给出几组示例,相同数据类型可以相互比较不用多说了,那么不同数据类型呢?
int a1 = 10; byte b1 = 10; System.out.println(a1==b1); //true char c1 = 'A'; int c2 = 65; System.out.println(c1 == c2); //true int a1 = 10; double d1 = 10.0d; System.out.println(a1==d1); //true int a1 = 10; char e1 = 10; System.out.println(a1==e1); //true
可以看到,在基本数据类型的范围内,不同数据类型也是可以直接比较的
如果比较的是基本数据类型,就是判断两个保存的数据是否相同(不一定类型相同)
1.2 引用数据类型
这里先写一个Student类,用于参考
public class Student { public String name; public int age; public Student(){} public Student(String name, int age){ this.name = name; this.age = age; } }
实例化两个Student对象,判断是否相等
Student student1 = new Student("Tom", 18); Student student2 = new Student("Tom", 18); System.out.println(student1==student2); //false
注意,这里出现了示例中的第一个false。可以看到,即使赋的值是相同的,但使用==判断的结果为false,这是因为两个对象在内存中不指向同一地址。
如果比较的是引用类型,就是比较两个变量是否代表同一对象实体,也就是是否指向同一地址
1.3 小结
==是运算符
可以使用在基本数据类型变量和引用数据类型变量中
如果比较的是基本数据类型,就是判断两个保存的数据是否相同,不一定类型相同
如果比较的是引用类型,就是比较两个变量是否代表同一对象实体,也就是是否指向同一地址
2. equals
equals()是方法,只能用于引用数据类型
还是使用上面介绍到的Student对象,如果使用equals比较,那么?
Student student1 = new Student("Tom", 18); Student student2 = new Student("Tom", 18); System.out.println(student1.equals(student2)); //false
答案还是false,我们可以看一下在此处使用的equals的源码
使用的正是Object中的equals()方法(继承),而Object中的equals()方法也是使用的==进行的比较
Object类中equals()和==的作用相同
诶,部分同学可能想说了,这个equals()和我们平时用的不太一样啊,平时用的equals()好像是用来比较数值的。这里我们拿String类来举例。
String str1 = new String("cun"); String str2 = new String("cun"); System.out.println(str1==str2); //false System.out.println(str1.equals(str2)); //true
使用==比较,不出意外是false。而这里使用equals(),得到的结果是true。我们看一下这里的equals()源码(Java8版本)
可以看到,String类中的equals()重写了Object类中的equals(),这里侧重于具体的数值比较(我们日常使用中也是更希望比较具体的数值)。分析一下源码,这里先使用==进行比较,然后判断是否为String的一个示例,判断长度是否相等,最后挨个判断字符是否相等。
源码的大部分程序都比较好理解,有些人比较迷惑这里的强制转换(如下图),既然前一句判断了是否为String类的实例,后一句为什么还要强转?这是因为,在Java中,代码从编写到执行要经历两个过程——编译和执行,在执行时,程序判断了实参是否为String类的实例对象,之后不再需要强转;但是在编译中,即使经历了instanceof判断,编译器还是会始终把传进来的参数当作Object类型,而Object类型是没有value属性的,会直接报错。所以在这里如果不强转,编译都通不过,更不用说执行了。
类似的,我们可以写出Student类中重写的equals()方法。
不过现在因为类使用的非常多,一方面是因为每个类都添加比较繁琐,另一方面我们可能写的可能不够健壮,这里提供两种方式自动提供equals()的重写
IDEA编译器的快捷键“alt + insert”,选择如下图的选项
选择需要添加到equals()的属性
可以看到自动生成的程序
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); }
导入lombok包,加入Data注解
@Data public class Student { public String name; public int age; public Student(){} public Student(String name, int age){ this.name = name; this.age = age; } }
可以看到重写了Object类中的equals()方法
3. 总结
/** * ==是运算符,equals是方法 * 1. == * 可以使用在基本数据类型变量和引用数据类型变量中 * 如果比较的是基本数据类型,就是判断两个保存的数据是否相同,不一定类型相同 * 如果比较的是引用类型,就是比较两个变量是否代表同一对象实体,也就是是否指向同一地址 * * 2. equals * 只能适用于引用数据类型 * Object类中equals()和==的作用相同 * 像String、Data、File、包装类等中的equals都是重写了Object类中的equals()方法,比较的是实体内容是否相同 */
到此这篇关于Java中==和equals()的区别的文章就介绍到这了,更多相关Java ==和equals()区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!