基本数据类型和对象的比较、存储的简记

1)“==”:用于比较基本数据类型时比较的是值,用于比较引用类型时比较的是引用指向的地址。而object中的equals()(String类重写了equal()),用来检测两个对象是否相等/两个对象的内容是否相等(区分大小写),而不是指在堆内存中的地址。【String是覆盖了equal方法,如果不覆盖的话,则相当于通过“==”比较】

2)地址比较是通过计算对象的哈希值来比较的,hashcode属于Object的本地方法,对象相等(地址相等),hashcode相等;对象不相等,hashcode()可能相等【HashCode采用的其实是一种杂凑算法,既然是凑出来的那么就有一种情况就是两个不同的对象返回相同的hashCode,并且这种算法越糟糕返回相同的概率越大】

3)java中的变量和基本类型的值存放在栈内存中,指向对象的引用也是存放于堆内存中;而new出来的对象本身存放在堆内存中。

4)栈内存的一个特点是数据共享,这样的设计是为了减少内存的消耗。假设定义了:i=1;那么i和1都在栈内存内,如果再定义一个j=1,此时将j放入栈内存,然后查找栈内存中是否有1,如果有则j指向1。如果再给j赋值2,则在栈内存中查找是否有2,如果没有就在栈内存中放一个2,然后j指向2。也就是如果常量在栈内存中,就将变量指向该常量,如果没有就在该栈内存增加一个该常量,并将变量指向该常量。另外,假设定义了:String·s=“HelloWorld”,此时HelloWorld也是存放在栈内存中的,而new出来的字符串对象(即String对象)是存放在堆内存中。

5)堆内存中没有数据共享的特点,每次new出来的对象都在堆内存中开辟新的存储空间,即使对象的内容一样。

6)编译器优化:对于字符串常量的相加,在编译时直接将字符串合并,而不是等到运行时再合并。也就是说:String a = "tao" + "bao" ;和String a="taobao";编译出的字节码是一样的。所以等到运行时,根据上面说的栈内存是数据共享原则,两者指向的是同一个字符串。但是,假如b = ‘tao’,c = ‘bao’ ,(b+c)只能等到运行时才能判定是什么字符串,编译器不会优化:运行时b+c计算出来的"taobao"和栈内存里已经有的"taobao"不是同一个。b+c计算出来的"taobao"应该是放在堆内存中的String对象(一个在栈中一个在堆中)。【Java对String的相加是通过StringBuffer实现的,先构造一个StringBuffer里面存放”tao”,然后调用append()方法追加”bao”,然后将值为”taobao”的StringBuffer转化成String对象。StringBuffer对象在堆内存中,那转换成的String对象理所应当的也是在堆内存中。就算是:(b+c).intern(),调用intern(),结果还是在堆内存中的。只是intern()会先检测栈内存中是否存在相同的字符串常量,有的话比较的结果就跟上面的不一样了。但是不影响(b+c)运行后的对象存储--堆内存中。】

猜你喜欢

转载自www.cnblogs.com/yangrongkuan/p/12028614.html