以下为 Jean 学习笔记和习题整理,供学习和参考
# ==
1. 判断对象地址是否相等。eg:Integer 和 Integer
这里注意一下:IntegerCache 缓存
JAVA 的 Integer 有 IntegerCache 会缓存 - 128~127 之间的对象。
Integer 类型在 - 128-->127 范围之间是被缓存了的,也就是每个对象的内存地址是相同的,赋值就直接从缓存中取,不会有新的对象产生,而大于这个范围,将会重新创建一个 Integer 对象,也就是 new 一个对象出来,当然地址就不同了,也就!=;
Integer a = 1; | |
Integer b = 1; | |
Integer c = 500; | |
Integer d = 500; | |
System.out.print(a == b); // true | |
System.out.print(c == d); // false |
2. 基本数据类型比较的是值。
eg:byte,short,char,int,long,double,boolean 用(==)、(!=)比较的都是值。
3. 引用数据类型比较的是内存地址。eg:Integer
总结:
1. 无论如何,Integer 与 new Integer 不会相等。不会经历拆箱过程,因为它们存放内存的位置不一样。
2. 两个都是非 new 出来的 Integer,如果数在 - 128 到 127 之间,则是 true, 否则为 false。
3. 两个都是 new 出来的,则为 false。
4.int 和 integer (new 或非 new) 比较,都为 true,因为会把 Integer 自动拆箱为 int,其实就是相当于两个 int 类型比较。
# equals
1. 判断两个对象是否相等
2. 类没有覆盖 equals 方法,等价于 “==” 比较两个对象。
注意:String 的 equals 是被重写过的 (hashCode 也被重写),Object 的 equals 是比较对象内存地址,String 创建对象时,JVM 在常量池中查找该对象,有无对应值,相同 -- 赋给当前值,不相同 -- 重新创建一个 String 对象
String str1="abc"; | |
String str2="abc"; | |
System.out.println(str1==str2); | |
System.out.println(str1.equals(str2)); | |
// 结果都为 true,因为 str1 创建时在堆中开辟了一块新的内存,存储 abc,str 则保存在栈中,而 str2 在创建时,由于 abc 已经 | |
// 存在,所以直接把内存地址给 str2,而没有重新开辟新的内存地址,所以,打印结果都是 true | |
String str3=new String("def"); | |
String str4=new String("def"); | |
System.out.println(str3==str4); | |
System.out.println(str3.equals(str4)); | |
//== 打印的是 false,equals 打印的是 true, 因为 new String 不管之前的内容是否在内存中已经存在 | |
// 在新定义时,都会重新开辟一块内存来存储这块内容,从而 str3 和 str4 的内存地址是不同的。 |
new String () 的源码可以看出,new String () 会更改 hash 值,因为重新 new 出来的对象是会在堆中开辟内存来存储新对象的,内存地址不同,== 所返回的值肯定是不同的。
如果 hashcode 相等,equals 也一定相等。
3. 类覆盖了 equals 方法,内容相等,则返回 true
# ❓测试
# 1. 比较判断
@Test | |
public void testEquals() { | |
int int1 = 12; | |
int int2 = 12; | |
Integer integer1 = new Integer(12); | |
Integer integer2 = new Integer(12); | |
Integer integer3 = new Integer(127); | |
Integer a1 = 127; | |
Integer a2 = 127; | |
Integer a = 128; | |
Integer b = 128; | |
System.out.println("int1 == int2 -> " + (int1 == int2)); | |
System.out.println("int1 == integer1 -> " + (int1 == integer1)); | |
System.out.println("integer1 == integer2 -> " + (integer1 == integer2)); | |
System.out.println("integer3 == a1 -> " + (integer3 == a1)); | |
System.out.println("a1 == a2 -> " + (a1 == a2)); | |
System.out.println("a == b -> " + (a == b)); | |
} |
答案:
1、 int1 == int2 -> true | |
2、 int1 == integer1 -> true | |
//nteger 是 int 的封装类,当 Integer 与 int 进行 == 比较时,Integer 就会拆箱成一个 int 类型,所以还是相当于两个 int 类型进行比较,这里的 Integer, 不管是直接赋值,还是 new 创建的对象,只要跟 int 比较就会拆箱为 int 类型,所以就是相等的。 | |
3、 integer1 == integer2 -> false // 两个都是对象类型比较的是地址 | |
4、 integer3 == a1 -> false | |
//integer3 是一个对象类型,而 a1 是一个常量它们存放内存的位置不一样,所以也不等 | |
5、 a1 == a2 -> true | |
6、 a == b -> false | |
// 看起来是一模一样的为什么一个是 true,一个是 false,这是因为 Integer 作为常量时,对于 - 128 到 127 之间的数,会进行缓存,也就是说 int a1 = 127 时,在范围之内,这个时候就存放在缓存中,当再创建 a2 时,java 发现缓存中存在 127 这个数了,就直接取出来赋值给 a2,所以 a1 == a2 的。当超过范围就是 new Integer () 来 new 一个对象了,所以 a、b 都是 new Integer (128) 出来的变量,所以它们不等。 |
# 2. 如何判断两个对象是否相等。
我们比较对象常用 equals(Object 的方法),你会发现,如果 User 类,使用默认的 equals () 方法判断 user1 和 user2 两个对象,得到的结果是 false。
public class User{ private String name; private int age;// ...getter & setter
}
可以看一下 Object 的 equals 方法:
public boolean equals(Object obj) { | |
return (this == obj); | |
} |
因为默认的 equals 方法是判断两个对象的内存地址,在没有重写 equals 方法时调用的就是对象的 ==,即内存地址。在上面我们说到 == 比较两个引用对象比较的是地址。
User user1 = new User("小明",18); | |
User user2 = new User("小明",18); | |
System.out.println(user1.equals(user2));//false |
那怎么判断 user1 就是 user2 呢?
如果要让 equals 比较的不是内存地址而是两个对象的内容就要对 equals 方法进行重写
@Override | |
public int hashCode() { | |
final int prime = 31; | |
int result = 1; | |
result = prime * result + age; | |
result = prime * result + ((name == null) ? 0 : name.hashCode()); | |
return result; | |
} | |
@Override | |
public boolean equals(Object obj) { | |
if (this == obj) | |
return true; | |
if (obj == null) | |
return false; | |
if (getClass() != obj.getClass()) | |
return false; | |
User other = (User) obj; | |
if (age != other.age) | |
return false; | |
if (name == null) { | |
if (other.name != null) | |
return false; | |
} else if (!name.equals(other.name)) | |
return false; | |
return true; | |
} |
User user1 = new User("小明",18); | |
User user2 = new User("小明",18); | |
System.out.println(user1.equals(user2));//true | |
System.out.println(user1==user2);//false | |
System.out.println(user1.hashCode()); // 456789 | |
System.out.println(user2.hashCode()); // 456789 |
equals 被重写时,有必要重写 hashCode, 以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。