1.前言
在Java中,需要比较对象是否相等。则需要用到“equals”和“==”。一般来说比较基础数据类型值相等用“==”,比较引用数据类型值相等用“equals”。
2.基础数据类型
数据的值直接存储在内存的栈空间,没有“引用”的概念。
基础数据类型 | 所占字节数 | 值类型 |
---|---|---|
byte | 1 | 数值型整数 |
boolean | 1 | 布尔型 |
char | 1 | 字符型 |
short | 2 | 数值型整数 |
int | 4 | 数值型整数 |
long | 8 | 数值型整数 |
float | 4 | 数值浮点类型 |
double | 8 | 数值浮点类型 |
3.引用数据类型
都是Object的子类,引用对象的首地址存储在内存中的栈空间,而对象的值存储在内存的堆空间。
4."=="
- 基础数据类型,比较的是基础数据类型的值。
- 引用数据类型,比较的是引用数据的引用地址。所以引用数据类型通常不使用“==”比较。
示例
public class MyTest {
public static void main(String[] args) {
int a = 0;
int b = 0;
MyTest test1 = new MyTest();
MyTest test2 = new MyTest();
System.out.println(a == b);
System.out.println(test1 == test2);
}
}
运行结果
上面的结果已经很明显了,a和b比较,由于都是基本数据类型,所以比较的是值,返回为true。而test1和test2,比较的是引用地址,这里是new了2个对象,在堆上开辟了2个不同的空间,所以地址不同,返回为false。
5.equals
其实在equals的默认比较中也是比较的引用地址。除非去重写equals方法。默认都是继承Object类中的equals。
public boolean equals(Object obj) {
return (this == obj);
}
基础数据类型的包装类和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;
}
6.相关面试题
1.下面程序的运行结果?
public class MyTest {
public static void main(String[] args) {
String a = "123";
String b = "123";
String c = new String("123");
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a == c);
System.out.println(a.equals(c));
}
}
运行结果
-
a=b 返回true 和 a.equals(b) 返回true
字符串缓冲池:程序在运行的时候会创建一个字符串缓冲池,当使用 a = “123”这样的表达式创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象。a先被放到了池中,所以在b被创建的时候,程序找到了具有相同值的 a,将b引用a所引用的对象”123”.
故a,b指向同一个内存区域,所以==和equals比较结果都是true. -
a==c 返回false
这里的c,new了一个新的对象,所以地址肯定和a不同 - 题外话
- "c创建对象"的方式会影响程序的性能
- "a==c"这种比较方式也会建议用equals()取代
- 这些在Android Studio都会被lint检测,进行提示,不建议使用。
网友评论