谈谈“equals”和“==”
总是遇到 equals 和 == 这类题,之前只知道对于基本数据类型, == 比较的是值,对于引用类型,== 比较的是内存地址。关于 equals 方法,首先是在Object 中被定义的,它的定义中就是使用==方式来匹配的。equals 默认是用来比较内存地址的,但是像 String、Long、Integer 等包装类型,默认重写 equals 方法,所以 equals 比较的就是值了。
下面对于此问题进行更详细的解释:
1.关于==
首先要知道==用于匹配内存单元上的内容,其实就是一个数字,计算机内部也只有数字,而在java语言中,当==匹配时,就是比对两个单元内存的内容是否一样。
如果是原始类型,byte,boolean,short,char,int,long,float,double,就是直接比较他们的值。
如果是引用,比较的就是引用的值,引用的值可以被认为是对象的逻辑地址,如果两个引用发生==操作,就是比较两个相应的对象的地址值是否一样,换句话说,如果两个引用保存的是同一个对象,则返回true,否则返回false。
2.关于equals()
equals方法,首先是在Object中被定义的,它的定义中就是使用==方式来匹配的,也就是说,如果不去重写equals方法,并且对应的类其父类列表中都没有重写过equals方法,那么默认的equals操作就是对比对象的地址。
equals方法之所以存在,是希望子类去重写这个方法,实现对比值的功能,类似的,String就自己实现了该方法。
-
int和int之间,用==比较,肯定为true。基本数据类型没有equals方法
-
int和Integer比较,Integer会自动拆箱,== 和 equals都肯定为true
-
int和new Integer比较,Integer会自动拆箱,调用intValue方法, 所以 == 和 equals都肯定为true
-
Integer和Integer比较的时候,由于直接赋值的话会进行自动的装箱。所以当值在
[-128,127]
中的时候,由于值缓存在IntegerCache中,那么当赋值在这个区间的时候,不会创建新的Integer对象,而是直接从缓存中获取已经创建好的Integer对象。而当大于这个区间的时候,会直接new Integer。 -
当Integer和Integer进行==比较的时候,在[-128,127]区间的时候,为true。不在这个区间,则为false
-
当Integer和Integer进行equals比较的时候,由于Integer的equals方法进行了重写,比较的是内容,所以为true
-
Integer和new Integer : new Integer会创建对象,存储在堆中。而Integer在[-128,127]中,从缓存中取,否则会new Integer.
所以 Integer和new Integer 进行==比较的话,肯定为false ; Integer和new Integer 进行equals比较的话,肯定为true -
new Integer和new Integer进行==比较的时候,肯定为false ; 进行equals比较的时候,肯定为true
原因是new的时候,会在堆中创建对象,分配的地址不同,==比较的是内存地址,所以肯定不同 -
装箱过程是通过调用包装器的valueOf方法实现的
-
拆箱过程是通过调用包装器的xxxValue方法实现的(xxx表示对应的基本数据类型)
总结:Byte、Short、Integer、Long这几个类的valueOf方法实现类似的。所以在[-128,127]区间内,==比较的时候,值总是相等的(指向的是同一对象),在这个区间外是不等的。
而Float和Double则不相等, Boolean的值总是相等的
测试题:
Integer a = 1000, b = 1000;
System.out.println(a == b);//1 false
Integer c = 100, d = 100;
System.out.println(c == d);//2 true
Integer s=new Integer(9);
Integer t=new Integer(9);
Long u=new Long(9);
- (s==u) ×
- (s==t) ×
- (s.equals(t)) √
- (s.equals(9)) √
- (s.equals(new Integer(9)) √