关于变量之间的比较,可以分为基础类型变量的比较和对象之间的比较。
对于基本类型来说,他们存储在jvm的栈中,因此比较的是变量的内容,也就是比较的变量的值。
对于引用类型来说,因为对象内容存储在jvm的堆中,栈中只是存储对象的引用(地址),无论是==还是equals比较的都是栈中的内容,即对象的引用,也就是比较的是两个对象的地址。但根据创建对象的方式不同可以分为两种情况:
1. 使用表达式创建对象:
2.使用new方法创建对象:
这里会引入两个新的问题:
1.为什么表达式创建和new创建,会让==比较产生不同的结果。
这是因为jvm在程序运行的时候会创建一个缓冲池,当使用表达式创建的时候,程序会在缓冲池中寻找相同值的对象,如果找到,就把这个对象的地址赋给当前创 建的对象,因此,c和d实际上都指向了c的引用。因此在使用==时会返回true。
当用new创建对象时,是在堆中重新分配内存,因此栈中的引用是不相同的,所以,a和b引用的是值相同的不同对象。所以a==b返回false
2.既然equals比较的是引用,那么a.equals(b)为什么返回true。这是因为在Integer里,重写了equals方法!
我们可以自己创建一个类,并验证。
1.当自定义Value类中没有重写equals方法时,调用equals方法返回结果为false。说明此时equals比较的并不是内容。
2.重写equals方法。
总结:
比较分为两种情况,基本数据类型没有 equals方法,equals方法是Object类的一个方法,比较equals和==就引用数据类型来说。
正常来说,对于引用数据类型来说,equals和==都是比较内存地址是否相同。
但是由于jvm运行时会创建一个缓存池,使用表达式创建,会在jvm缓存池中寻找相同的值的对象,在栈中同时引用这个对象,那么,现在引用的是缓存池中的同一个对象,所以使用表达式创建,equals和==都为true值相同。
使用new创建对象,会在java堆中创建两个不同的对象,栈中引用这两个对象,结果一定是不同的,所以正常来说,equals和==结果都为false。
但是由于Integer,Date,String等重写了equals方法,所以,使用equals比较的是值,使用equals比较值为true。