1. ==操作符:
== 比较的是 变量(栈)内存中存放的对象的(堆)内存地址,用来 判断两个对象的地址是否相同,即 是否是指相同一个对象。比较的是真正意义上的指针操作。a、比较的是操作符两端的操作数 是否是同一个对象。
b、两边的操作数必须是 同一类型的(可以是父子类之间)才能编译通过。
c、比较的是地址,如果是具体的阿拉伯数字的比较, 值相等则为true,如:
int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。
2. 对equals分析源码有:
a. 在Object中有:
public boolean equals(Object obj) {
return (this == obj);
}
b. 在String中有:
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; //String 中使用private final char value[];存储字符串
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
可以看出,不论是Object.equals( )或者Srting.equals( )中,方法参数都是一个obj,即对象,此时有equals不能用于基本数据类型的判断。
c. 对包装类,以Integer为例,有:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
可以看出,实际上,Object和Integer实际上仍是值的比较(基本数据类型或是否是同一对象),而String 的equals不仅仅含有值的比较(是否是同一对象),还有字符串内容(两个字符串内容是否相同(仅限同一类型的(可以是父子类之间)))的比较。
3. 特殊情形:(String s="abce";和String s = new String("abcd");)
String s="abce"是一种非常特殊的形式,和new 有本质的区别。它是java中唯一不需要new 就可以产生对象的途径。以String s="abce";形式赋值在java中叫直接量,它是在常量池中而不是像new一样放在堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象,如果有,就会把它赋给当前引用。即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个"abcd",下一次如果有String s1 = "abcd";又会将s1指向"abcd"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象。
String s1 = "chance";
String s2 = "chance";
System.out.println(s1 == s2); //true
System.out.println(s1.equals(s2)); //true
而String s = new String("abcd"); 和其它任何对象一样,每调用一次就产生一个对象,只要它们调用。
String s3 = new String("chance");
String s4 = new String("chance");
System.out.println(s3 == s4); //false
System.out.println(s3.equals(s4)); //true
![](https://i-blog.csdnimg.cn/blog_migrate/e0b4b97ff631d73ae52db973242286c3.png)
4. int与Integer:
Java的8种基本类型(Byte, Short, Integer, Long, Character, Boolean, Float, Double), 除Float和Double以外, 其它六种都实现了常量池, 但是它们只在大于等于-128并且小于等于127时才使用常量池。
a. 两个通过new生成的Integer变量永远是不相等的:
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false
因为new生成的是两个对象,其内存地址不同。
b. Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true:
Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); //true
因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较。
c. 对于两个非new生成的Integer对象(存在常量池中),进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false
java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100)。而java API中对Integer类型的valueOf的定义如下,对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了。
d. 非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。
Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false
因为非new生成的Integer变量指向的是java常量池中的对象(-128到127之间),而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同。
参考博客:
1. https://www.cnblogs.com/Eason-S/p/5524837.html
2. https://blog.csdn.net/chance2015/article/details/51427304
3. https://blog.csdn.net/chenliguan/article/details/53888018
4. https://blog.csdn.net/shw2004/article/details/5678703