java 中的 equals 和 ==
本文的文章结构如下,尽可能让大家对 equals 和 == 掌握通透,如有错误之处,欢迎在评论区指出:
一、Java 的数据类型分类(简)
一、equals 和 == 区别
二、String 的 equals 和 ==
三、Integer 的 equals 和 ==
一、java 的数据类型(简)
Java 中的数据类型分为【基本数据类型(原始数据类型8种)】和【引用数据类型】
基本数据类型:byte、short、char、int、long、float、double、boolean
引用数据类型:继承于Object,如String等
二、equals 和 == 区别
==:
- 可用于基本数据类型的变量,也可比较引用类型的变量
- 作用于基本数据类型的变量,直接比较存储的“值”是否相等
- 作用于引用类型的变量,比较的是所指向对象的地址是否相等,确切地说:是堆内存地址。
equals:
- 只用于引用类型的变量,不能用于基本数据类型的变量
- 是根据 Object 的equals() 方法来进行比较,如果没有对 equals 方法进行重写,比较的是引用类型的变量所指向的对象的地址
这是因为:
Object 的 equals() 方法如下,所以
public boolean equals(Object obj) {
return (this == obj);
}
综上,equals 比较主要是调用对象的 equals() 方法,所以我们只需要看对象类的 equals() 是怎么写的即可知道,后文我们分别从 Integer 和 String 两种对象来看 equals() 的结果。
三、String 的 equals 和 ==
String 的 equals() 方法重写为:比较字符串的内容
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = length();
if (n == anotherString.length()) {
int i = 0;
while (n-- != 0) {
if (charAt(i) != anotherString.charAt(i))
return false;
i++;
}
return true;
}
}
return false;
}
所以,对于 String 来说:
- ==:比较的是两个字符串内存地址(堆内存)的数值是否相等,数据数值比较;
- equals():比较的是两个字符串的内容,数据内容比较
大家可以判断以下代码的输出结果吧:
String str1 = "Hello";
String str2 = new String("Hello");
String str3 = str2; // 引用传递
System.out.println(str1 == str2); // false
System.out.println(str1 == str3); // false
System.out.println(str2 == str3); // true
System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals(str3)); // true
System.out.println(str2.equals(str3)); // true
另外一个相关的知识点(不常用),intern() 方法,是一个 native 的实现。
String s1 = "Hello";
String s2 = new String("Hello");
s2 = s2.intern();
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
intern() 的返回值是字符串"Hello",它内部的判断为:检查常量池中是否存在“Hello”字符串,如果存在,返回常量池的“Hello”的引用,如果不存在,会将“Hello”添加到常量池中,再返回它的引用,因此经过 intern() 操作后,s2 和 s1 的引用相等。
四、Integer 的 equals 和 ==
Integer 的情况是怎么样呢?我们去看 Integer 的 equals() 方法。
/**
* The value of the {@code Integer}.
*
* @serial
*/
private final int value;
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
/**
* Returns the value of this {@code Integer} as an
* {@code int}.
*/
public int intValue() {
return value;
}
Interger 的 equals() 方法返回其基本类型变量的值,intValue() 方法返回的是 Integer 的值。
另外需要注意的是:如果 obj 为一个基本数据类型,则编译器会自动将 obj 装箱进行比较,比如:i.equals(5); 5 -> new Integer(5) (??? 这里的装箱应该不是新建一个实例?那内部是怎么样呢?)
若直接入参是非相同类型的对象,则直接会返回 false。
基本类型的包装类型 equals() 总结:
1. equals() 参数为基本数据类型,则编译器会进行自动装箱为包装类型,0-> 默认为 Integer,而不是 Long,注意!。
2. equals() 参数为包装类型,则先比较是否为同类型,非同类型直接返回 false,同类型再比较值。
练习:
new Long(0).equals(0);//false, 参数 int ,装箱为 Integer 类型,不同类型直接返回false
new Integer(500).equals(500);// true,相同类型,比较值相等
Integer a = new Integer(500);
Integer b = new Integer(500);
a.equals(b);//true
基本数据类型及其包装类型的 == :
1. 基本类型==包装类型
1) 同类型,编译器自动拆箱,比较值:如Integer 与int,Long与long进行==比较时,会自动拆箱为基本类型
2) 不同类型,会自动拆箱且向上转型比较值(低级向高级是隐式类型转换如byte<short<int<long<float<double,高级向低级必须强制类型转换,可能会有溢出)
3. 两边都是包装类型,比较引用地址,注意 IntegerCache 除外。IntegerCache 用于 Integer.valueOf() 方法,若是 -128-127 的大小,会返回相同的对象,而不是新建对象。
// IntegerCache.low = -128,IntegerCache.high = 127
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
好了,我们用这几条规则做一下这几道题吧。
Integer a = 59;
Integer b = Integer.valueOf(59);
Integer c = new Integer(59);
System.out.println(a == b); //true 因为59位于缓存区间直接从缓存中获取
System.out.println(a == c); //false
System.out.println(b == c); //false
Integer a1 = 200;
Integer b1 = Integer.valueOf(200);
Integer c1 = new Integer(200);
System.out.println(a1 == b1); //false 因为200超出缓存区间从新创建对象
System.out.println(a1 == c1); //false
System.out.println(b1 == c1); //false
以上就是 Java 中的 equals() 和 == 的比较。