在Java中有两种用来判断两个变量是否相等的方式:== 和 equals(),一个是操作符一个是Object类的方法,所以使用上有很多的区别
==
当使用==判断两个变量是否相等时,根据变量类型分为两种情况:如果是基本数据类型,且都是数值类型(也就是除了boolean型)(不一定要求数据类型严格相等),则只要两个变量的相等,就将返回true.
如果是引用类型,则只有两个变量的内存地址相等,也就是两个变量指向同一个变量时,才会返回true.==不能比较没有继承关系的两个对象
常量池
当使用"测试" 字符串直接量创建字符串时,JVM会使用常量池来管理这些字符串;当使用new String("测试")则是在运行时重新创建的String对象,并被保存在运行时内存区(堆内存);
常量池专门用来管理在编译时就被确定并被保存在已编译的.class文件中的一些数据.它包括了类、方法、接口中的常量,当然也包括字符串常量。
class StringTest {
public static void main(String[] args) {
String s1 = "今天天气不错";
String s2 = "今天";
String s3 = "天气不错";
//s4的值在编译时就确定下来,所以引用常量池中的"今天天气不错"
String s4 = "今" + "天天气不错";
//s4的值在编译时不能确定下来,所以不能引用常量池中的值
String s5 = s2 + s3;
//使用构造器创建字符串,引用指向堆内存中的新创建的String对象
String s6 = new String("今天天气不错");
System.out.println(s1 == s4); //true
System.out.println(s1 == s5); //fals
System.out.println(s1 == s6); //false
}
}
equals()
equals是Object类的方法;源码如下:
public boolean equals(Object obj) {
return (this == obj);
}
但在很多时候出于我们的需要都会重写equals(),实际上JDk中,String、Math等封装类都对equals()方法进行了重写。
下面是String的equals()重写:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
通常来说,正确的重写equals()应该满足以下条件:
自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。
对于上面几个规则,我们在使用的过程中最好遵守,否则会出现意想不到的错误。
在重写equals()时最好使用getClass()进行类型判断
对于instanceof,当前面的对象是后面的对象的类的实例或者对面对象的类的子类的实例时都会返回true。而我们在重写equals时,更多的是希望比较同一个类型的对象,所以最好使用getClass()
---------------------
原文:https://blog.csdn.net/dora_310/article/details/77253192