1. 在Java中,万物皆对象,但是仍可以分为基本类型和非基本类型。
因为对于int 这些数据对象,并不需要多大的空间,为了提高效率,就将这些int、double、float、bool等基本类型直接按值存放在栈中。而非基本类型的实际值则是存放在堆中。
下面我们结合上面提到的数据类型再讨论一下==和equals的问题。
我们知道Java中都是以引用方式来操作实际对象的,而引用则是存在于栈中。而对于基本类型和非基本类型,其也有差别。下面举个例子。
//基本类型,其在栈区中的引用a、b直接存放的就是值3
int a = 3;
int b = 3;
system.out.print(a==b) //true
//非基本类型,其在栈区中的引用a存放的是实际obj对象在堆中的地址
//比如栈区中的,引用a:30001(实际Integer对象的地址) -> 堆:30001地址存放:21
//引用b:30002(实际Integer对象的地址) -> 堆:30002地址存放:21
Integer a = Integer(21);
INteger b = Integer(21);
system.out.print(a==b) //false
system.out.print(a.equals(b)) //true,因为Integer中默认重写了equals方法
//equals方法默认是比较引用的,所以下面输出false
class obj{
int value;
}
obj a = new obj();
obj b = new obj();
a.value =1;
b.value = 2;
system.out.print(a.equals(b)) //false
从上面例子我们知道,像==这种关系操作符,它比较的是引用中存放的值。所以基本类型比较使用==没关系,因为他们引用中存放的就是实际值。而非基本类型则不行,因为他们引用中存放的是实际对象在堆中的地址。
另外就是equals方法,equals方法就可以用来弥补这种只比较引用的不足的,但是在根类Object对象中默认是比较引用的,所以想要实现比较自定义类型对象的值时,就需要重写equals方法。
2.享元模式与自动拆箱
-
当Integer的值在-128到127之间,则其分配在常量池中,a b持有同一个引用,所以相等
Integer a = 3; Integer b = 3; System.out.println(a==b); print:true
-
当超出这个范围,则其分配在堆中,a、b持有的是不同对象的引用,所以==判断时不相等
Integer a = 333; Integer b = 333; System.out.println(a==b); print:false
-
当使用运算符时,Integer会完成自动拆箱成int的工作,所以相等
Integer a = 333; Integer b = 333; Integer c = 666; System.out.println(a+b==c); print:true