Java中==比较的是两个对象是否是同一个引用(即比较内存地址)
equals 对于从写了equals方法的类来说是比较值,没有重写仍然比较地址;
Integer 和 int
public class IntegerAndString {
@Test
public void test1(){
int i1=5;
Integer i2=5;
System.out.println(i1==i2); //true
Integer i3=5;
Integer i9=new Integer(5);
Integer i4=new Integer(5);
System.out.println(i3==i4); //false
System.out.println(i9==i4);//false
Integer i5=20;
Integer i6=20;
System.out.println(i5==i6); //true
Integer i7=129;
Integer i8=129;
System.out.println(i7==i8); //false
int a=new Integer(10);
Integer b=10;
System.out.println(a==b);//true
}
int (是面向对象的残留) 当int 和Integer 数据类型进行比较时Integer会进行自动拆箱操作,所以只会比较实际的值,所以i1==i2 a==b
Integer是int的封装类,一般来说基础变量(int)赋值给Integer对象将自动装箱(Auto Boxing)并为Integer对象分配堆空间。因此即使基础变量值一样,封装类对象指向不同地址
当用Integer i=new Integer(6)创建对象时则是在堆区从新划分一个内存空间,把地址给i,所以i4==i9是false
由于因为JDK 的自动装箱操作可以用Integer i2=5来声明变量,Java在编译的时候会执行将代码封装成Integer i2=Integer.valueOf(5);通过查看源码发现
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
也就是说这种方式声明一个Integer对象时,JVM首先会在Integer对象的缓存池中查找有木有值为20的对象,如果有直接返回该对象的引用;如果没有,则使用创建一个对象,并返回该对象的引用地址。),i5和i6都是引用的同一个对象结果为”true“ 且地址值都在常量池中,所以 i3==i4是false
而它维护的常量池从-128~127 当超出这个范围时就返回new Integer(129); 在堆区创建对象,返回地址值,所以i7==i8是false
String
public void test2(){
String str1="hello";
String str2="hello";
System.out.println(str1==str2); //true
String str3=new String("hello");
System.out.println(str1==str3);//false
String str4="ab";
String str6="abc";
String str5=str4+"c";
System.out.println(str6==str5);//false
String s1="a"+"b"+"c";
String s2="abc";
System.out.println(s1==s2);//true
/*在java中有常量优化机制,byte=4+3
* (在编译时会判断将3+4=7在bytede 范围内)是对的,
* 同理在编译时也变成了三个字符串abc
* */
}
String 的机制是String s=”hello” 创建对象时同样是现在常量池中找,若没有就创建,若有则返回地址引用,所以str1==str2
String str3=new String(“hello”),也会去常量池去找,没有就创建,创建完毕后会将这个字符串拷贝到堆区,在堆内存中再创建一个对象,然后将堆的地址返回 所以str3==str1是false
会先在常量池中创建str4和str6字符串对象,对于使用了+将变量str4和“c”相连接,首相会在堆区创建一个Stringbuffer对象,通过方法将其加在一起,产生一个地址值,然后调用它的toString方法转换成一个字符串并创建对象,产生一个地址值并返回,