首先看下==与equals比较的示例:
那么问题来了~
- 为什么(a == b)为true,(e == f)为false;
- (a == b )为true,因为int是基本数据类型,而Integer是int的包装类型,当一个基本类型与一个包装类型进行比较时,Java会自动将包装类型拆箱为基本类型,然后进行值的比较;
- (e == f)为false,因为在Java中,包装类型的比较使用
==
时比较的是引用地址而不是值,这是因为包装类型(如Integer
、Double
、Boolean
等)是对象类型。对象类型在Java中是通过引用进行管理的,而==
运算符对于对象类型比较的是它们的引用地址(即上述e,f两个对象在内存中的位置的值),而不是它们的值。
- 那么又有问题来了,为什么(c == d)为true,难道127,128的值还有什么区别吗?
- 是的,有区别;
Integer
作为类,理论上进行==
比较时必须要有相同的地址值才返回true
,但为了减少内存占用,jdk
中Integer的实现用到了一个静态内部类IntegerCache
:- 该静态内部类维护了一个Interger类型的数组
cache
,默认的取值范围为low = -128; high = 127;
- 当我们创建一个Integer对象或赋值时,都用调用valueOf()方法【自动装箱,编译时会调用 valueOf()方法】,而valueOf方法,会对在-128~127以内值,直接返回该对象;这是为什么(c == d)为true,因为他们值为127在处于【-128~127】范围内,他们使用是一个对象,因此相等;
- valueOf()示例:
- 为什么(c.equals(d))为true?
- 我们先看下最原始的equals方法(Object类下,所有包装类型都会继承该类和重写部分方法),实际用的还是==,也就是比较两个对象是否引用的同一个地址:
- 我们看下Integer中equals中的实现,可以看到实际比较的value值:
- 这是为什么c.equals(d)为true,因为Integer类,重写了equals方法,实际变成了值比较,而不是对象的地址;(原先Object类中比较的还是对象,也就是对象的地址值是否相等)
- 总结:
- == 比较两个引用是否指向同一个对象,也就是内存地址值。对于基本数据类型,比较它们的值;
- equals用户比较两个对象的内容是否相等,因为所有的包装类通常是重写了Object类中的equals方法;
- 我们先看下最原始的equals方法(Object类下,所有包装类型都会继承该类和重写部分方法),实际用的还是==,也就是比较两个对象是否引用的同一个地址: