1、equals 和 ==区别
实验:
//基本数据类型的比较
int num1 = 10;
int num2 = 10;
System.out.println(num1 == num2); //true
//引用数据类型的比较
String s1 = "chance";
String s2 = "chance";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
//String类中==与equals的比较
String s3 = new String("chance");
String s4 = new String("chance");
System.out.println(s3 == s4); //false
System.out.println(s3.equals(s4)); //true
//非String类中==与equals类型的比较
Scanner scanner = new Scanner(System.in);
Scanner scanner2 = new Scanner(System.in);
System.out.println(scanner.equals(scanner2)); //false
Scanner sc = scanner;
System.out.println(scanner.equals(sc)); //true
比较基本数据类型
“==
” 属于关系运算符,一般认为,比较的是两个基本数据类型的值是否相等.
//基本数据类型的比较
int num1 = 10;
int num2 = 10;
System.out.println(num1 == num2); //true
class B{
B(int a) this.a = a;
}
B t1 = new B(3);
B t2 = new B(3);
System.out.println(t1.a == t2.a); //true
在引用数据类型中的比较
1、在String类中的比较
1)不使用new String("fan")
方式时:
String s1 = "chance";
String s2 = "chance";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
首先在引用数据类型中==
比较的是引用的对象是否相等,即是否引用了同一个对象
比较过程:
当执行String s1 = “chance”;
这条语句时,会在堆中的字符常量池里找”chance”
这个字符串,若没有找到,则将”chance”
这个字符串放入字符串常量池中.而在栈中开辟一块名为s1
的空间存放”chance”
,这块空间的引用.
当执行String s2 = “chance”;
这条语句时,会在堆中的字符串常量池里找”chance”
这个字符串,很显然,可以找到,于是便把字符常量池里”chance”
这个字符串的引用地址赋给s2
,因此s1
与s2
存放的都是堆中字符常量池中的同一个”chance”
的引用
接着System.out.println(s1.equals(s2));
这里的equals
在String类中被重写过,用来比较两个字符串的实际内容是否相等,即每一个字符是否相等,重写方法末尾会另做说明!!!因为比较的是字符串内容,s1,s2内容都是chance当然是相等的。
'String类中被重写的equals方法'
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
该方法将两个String
对象拆分成字符数组,然后通过遍历字符数组中的每一个字符是否都相等,若相等,则返回true
否则返回false;
2)new String类时的比较
String s3 = new String("chance");
String s4 = new String("chance");
System.out.println(s3 == s4); //false
System.out.println(s3.equals(s4)); //true
每new
一次都会在堆中开辟一个新的空间来存储新new的对象。
因此,在执行前两句时候,java开辟了两块不同的地址空间,用于存放"change"这个字符串。
System.out.println(s3 == s4); //false
s3和s4中存放的是两个不同对象的引用,自然,s3和s4所在地址空间内存放的内容不相同。System.out.println(s3 == s4);
返回的是false;
然而由于String中的equals方法被重写了,因此equals
方法比较的还是字符串中内容是否相等,即每个字符是否相等。可见s3和s4这两个对象中中存放都是”chance”,自然每个字符都相等.
2、不在String中的比较
class A
{
A obj1 = new A();
A obj2 = new A();
}
obj1==obj2 //结果为false
obj1.equals(obj2)//是false
可见,Object类的equals()
和==
运算符几乎一样,也是要求两个引用类型变量指向同一个对象时才会返回true;
结论
可见在非String类中, ==和equals的作用都是一样的(比较是否是指向同一对象),只不过在String类中重写了equals方法,才会变得这么复杂
==用法:
1、 判断基本类型变量是否相等,且都是数值类型(不一定要求数据类型严格相同),只要两个变量的值相等,就返回true
2、对于两个引用类型变量,只有当他们指向同一个对象时,判断才会返回true。且不能用于比较类型上没有父子关系的两个变量
equals用法
1、 equals()是Object类提供的一个示例方法,因此所有的引用类型变量都能用它来判断是否和其他的引用类型变量相等。
2、Object类的equals()和==
运算符几乎一样,也是要求两个引用类型变量指向同一个对象时才会返回true;
3、string类的equals()已经进行了重写,所以str1.euqals(str2)比较的是str1和str2的内容,而不是比较引用类型变量指向的对象
此外:
基本类型的包装类型,比如Boolean、Character、Byte、Shot、Integer、Long、Float、Double等的引用变量,==是比较地址的,而equals是比较内容的。
补充:
public boolean equals(Object obj){
return (obj instanceof Float)&&(floatToIntBits(((Float)obj).value)==floatToIntBits(value))
}
Float有一个静态方法floatToIntBits().将flaot的二进制表示看作int。需要注意的是只有两个float的二进制表示完全一样的时候,equals才会返回true。
如:
Float f1 = 0.01f;
Float f2 = 0.1f*0.1f;
System.out.println(f1.equals(f2));
System.out.println(Float.floatToIntBits(f1));
System.out.println(Float.floatToIntBits(f2));
'结果:'
false
1008981770
1008981771
也就是两个浮点数不一样,可以将二进制看作整数也不一样,相差为1.
Double的equals方法与Float类似,他有一个doubleToLongBits,将double的二进制表示看long,然后再按照long比较。