1,== 和equals
基本数据类型,保存在栈中,用==进行数值判断。
而引用数据类型比如Object,对象实体保存在堆中,对象引用地址保存在栈中,则==用来比较地址是否相等,而equals通过看底层源码发现
/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(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;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
默认也是比较对象的地址是否相等,String类型的可以比较对对象的内容是否相等,equals和hashcode是子类可以重写的方法,子类可以根据自己的具体业务重写达到业务的需求。String类型的数据会涉及到jvm编译时优化问题比如下列
package com.sparkhuu.base;
public class StringTest {
public static void main(String[] args) {
String s1 = "a" + "b" + 1; // 编译时自动优化为:"ab1"
String s2 = "ab1";
// == 当比较基本数据类型时,比较数值,当比较引用数据类型时,比较引用地址
System.out.println(s1 == s2);
// equals 默认比较对象的地址, 可被重写,String已经重写了equals方法
System.out.println(s1.equals(s2));
String a = "1";
final String testA = "1";
String b = a + "2" + 3; // 编译时不会优化 b,c不是同一个对象,但b,c值相同 String重写了equals方法
String c = "123";
String testB = testA + "2" + 3;
System.out.println(testB == c);
System.out.println(testB.equals(c));
System.out.println(b == c);
System.out.println(b.equals(c));
String eString = "a";
String fString = eString + "b";
String gString = "ab";
String hString = new String(gString);// 通过new的都只有在运行时才能确定
System.out.println(fString == gString);
System.out.println(hString == gString);
System.out.println(hString.intern() == gString.intern());
}
}
结果为
true
true
true
true
false
true
false
false
true
2,基本数据类型的封装类
int –> Integer
char –> Character
double –>Double等
这里会涉及到装包和拆包
如下测试
package com.sparkhuu.base;
public class BaseNumberTest {
public static void main(String[] args) {
Integer a = 1;
Integer b = 1;
Integer e = -127;
Integer f = -127;
// Integer.valueOf(); [-128 127]之前是被cache的 所以是同一个对象 而其他范围会new Integer() 所以不是同一个对象
Integer c = 200;
Integer d = 200;
System.out.println(a == b);
System.out.println(e == f);
System.out.println(c == d);
char x = '中';
char x1 = 'a';
byte y = 'a';
Boolean tr = true;
Boolean shBoolean = true;
System.out.println(tr == shBoolean);
}
}
结果为
true
true
false
true
主要原因是基本数据类型转化为封装类的时候会调用封装类的init,而封装类的部分代码进行了cache,
Integer,Short,Long的cache范围是-128到127,其中Integer可以通过配置修改范围,而Short和Long则不行。
Boolean 的cache范围是true, false,
Characher全部缓存
Double,Float没有缓存。