结论:
对“==”而言:
1、基本数据类型:比较的是他们的值是否相等;
2、引用数据类型:比较的是两个对象的地址是否一致。
对“equels”而言:
默认情况下,和“==”一样,比较的是地址值,但是如果重写了equels()方法就按重写的来比较,比如:String类,Integer类,它们都重写了各自的equels()方法,所以比较的是两个对象的值是否相等。
举例:
一、关于int及其包装类integer的“==”比较
public static void main(String[] args) {
int i1 = 127;
int i2 = 127;
Integer i3 = 127;
Integer i4 = 127;
Integer i5 = 128;
Integer i6 = 128;
Integer i7 = new Integer(127);
Integer i8 = new Integer(127);
System.out.println("i1 == i2结果:" + (i1 == i2));
System.out.println("i1 == i3结果:" + (i1 == i3));
System.out.println("i1 == i7结果:" + (i1 == i7));
System.out.println("i3 == i4结果:" + (i3 == i4));
System.out.println("i5 == i6结果:" + (i5 == i6));
System.out.println("i3 == i7结果:" + (i3 == i7));
System.out.println("i7 == i8结果:" + (i7 == i8));
}
运行结果:
i1 == i2结果:true // 原因不再赘述;
i1 == i3结果:true // 因为Integer与int比较时,包装类都会自动拆箱,所以就相当于两个int类型在比较;
i1 == i7结果:true // 同上;
i3 == i4结果:true // 当两个不是new的Integer对象的值在-128~127之间时,系统会自动进行缓存,所以这两个对象的地址相同;
i5 == i6结果:false // 同上,当超过这个范围时,不会进行缓存,对象的地址就不一样了;
i3 == i7结果:false // 前者指向常量池,后者指向堆,所以地址不一样;
i7 == i8结果:false // 原因不再赘述;
二、关于String的比较
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2);
}
运行结果:
true // String类型常量放在常量池中,所以s1和s2地址相同
public static void main(String[] args) {
String str1 = "Hello";
String str2 = new String("Hello");
String str3 = str2;
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str2 == str3);
System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));
System.out.println(str2.equals(str3));
}
运行结果:
false // 前者在常量池中,后者在堆上,两者指向的地址不同
false // 同上
true // 二者都指向堆上同一个地址
true // 只比较值是否相等
true // 同上
true // 同上
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "He" + "llo";
final String str3 = "He";
final String str4 = "llo";
String str5 = str3 + str4;
String str6 = "He";
String str7 = str6 + "llo";
System.out.println(str1 == str2);
System.out.println(str1 == str5);
System.out.println(str1 == str7);
}
运行结果:
true // 编译器会直接合并为str2 =”abc”,所以两者都指向常量池
true // final修饰的str3,str4相当于是一个常量,常量相加在编译后会直接替换成对应的值,所以与上述相同
false // 变量相加实际上是使用StringBuilder.append来完成,在堆上新生成一个对象,所以指向地址不同