前言:按理说这种错误,工作多年之后就不应该再犯的,不过实际工作中我遇到过两次,工作n年的同事还是犯了,所以,在此记上一笔以作警醒。还是先尝栗子,再下结论。
1:使用BigDecimal类,实际中也是经常用的,不过相对来说使用此类时犯的错误会少一点
package com.jd.test.integer;import java.math.BigDecimal;public class TestBigDecimalMain { public static void main(String args[]){ BigDecimal _BigDecimal1 = new BigDecimal(99); BigDecimal _BigDecimal2 = new BigDecimal(99); System.out.println("_BigDecimal1 hashCode is :"+_BigDecimal1.hashCode()+"\n_BigDecimal2 hashCode is :"+_BigDecimal2.hashCode()); System.out.println("_BigDecimal1 identityHashCode is :"+System.identityHashCode(_BigDecimal1)+"\n_BigDecimal2 identityHashCode is :"+System.identityHashCode(_BigDecimal2)); //包装类型的==比较,赋值时采用的是创建对应的对象的方式 System.out.println("_BigDecimal1==_BigDecimal2 is : "+(_BigDecimal1==_BigDecimal2));//false,注意:这里是false,也就是说不能使用这种比较方式 //包装类型的equals比较 System.out.println("_BigDecimal1.equals(_BigDecimal2) is : "+(_BigDecimal1.equals(_BigDecimal2)));//true }}
2:使用Double类,特别是_Double1==_Double2相比较时,更容易出错
package com.jd.test.integer;public class TestDoubleMain { public static void main(String args[]){ double double1 = 99; double double2 = 99; Double _Double1 = 99D; Double _Double2 = 99D; Double _Double3 = new Double(99); Double _Double4 = new Double(99); System.out.println("double1 identityHashCode is :"+System.identityHashCode(double1)+"\ndouble2 identityHashCode is :"+System.identityHashCode(double2)); System.out.println("_Double1 hashCode is :"+_Double1.hashCode()+"\n_Double2 hashCode is :"+_Double2.hashCode()); System.out.println("_Double1 identityHashCode is :"+System.identityHashCode(_Double1)+"\n_Double2 identityHashCode is :"+System.identityHashCode(_Double2)); System.out.println("_Double3 hashCode is :"+_Double3.hashCode()+"\n_Double4 hashCode is :"+_Double4.hashCode()); System.out.println("_Double3 identityHashCode is :"+System.identityHashCode(_Double3)+"\n_Double4 identityHashCode is :"+System.identityHashCode(_Double4)); //基本类型的==比较 System.out.println("double1==double2 is : "+(double1==double2));//true //基本类型和包装类型的==比较 System.out.println("double1==_Double1 is : "+(double1==_Double1));//true// System.out.println("_Double1==double1 is : "+(_Double1==double1));//true System.out.println("double1==_Double3 is : "+(double1==_Double3));//true// System.out.println("_Double3==double1 is : "+(_Double3==double1));//true //包装类型的==比较,赋值时采用的是直接赋值的方式 System.out.println("_Double1==_Double2 is : "+(_Double1==_Double2));//false,注意:这里是false,也就是说不能使用这种比较方式 //包装类型的==比较,赋值时采用的是创建对应的对象的方式 System.out.println("_Double1==_Double3 is : "+(_Double1==_Double3));//false,注意:这里是false,也就是说不能使用这种比较方式 System.out.println("_Double3==_Double4 is : "+(_Double3==_Double4));//false,注意:这里是false,也就是说不能使用这种比较方式 //基本类型和包装类型的equals比较 System.out.println("_Double1.equals(double1) is : "+(_Double1.equals(double1)));//true //包装类型的equals比较 System.out.println("_Double1.equals(_Double2) is : "+(_Double1.equals(_Double2)));//true System.out.println("_Double3.equals(_Double1) is : "+(_Double3.equals(_Double1)));//true System.out.println("_Double3.equals(_Double4) is : "+(_Double3.equals(_Double4)));//true System.out.println(System.identityHashCode(_Double1)+" "+System.identityHashCode(_Double2));//true }}
3:使用Float类,特别是_Float1==_Float2相比较时,更容易出错
package com.jd.test.integer;public class TestFloatMain { public static void main(String args[]){ float float1 = 99; float float2 = 99; Float _Float1 = 99F; Float _Float2 = 99F; Float _Float3 = new Float(99); Float _Float4 = new Float(99); System.out.println("float1 identityHashCode is :"+System.identityHashCode(float1)+"\nfloat2 identityHashCode is :"+System.identityHashCode(float2)); System.out.println("_Float1 hashCode is :"+_Float1.hashCode()+"\n_Float2 hashCode is :"+_Float2.hashCode()); System.out.println("_Float1 identityHashCode is :"+System.identityHashCode(_Float1)+"\n_Float2 identityHashCode is :"+System.identityHashCode(_Float2)); System.out.println("_Float3 hashCode is :"+_Float3.hashCode()+"\n_Float4 hashCode is :"+_Float4.hashCode()); System.out.println("_Float3 identityHashCode is :"+System.identityHashCode(_Float3)+"\n_Float4 identityHashCode is :"+System.identityHashCode(_Float4)); //基本类型的==比较 System.out.println("float1==float2 is : "+(float1==float2));//true //基本类型和包装类型的==比较 System.out.println("float1==_Float1 is : "+(float1==_Float1));//true// System.out.println("_Float1==float1 is : "+(_Float1==float1));//true System.out.println("float1==_Float3 is : "+(float1==_Float3));//true// System.out.println("_Float3==float1 is : "+(_Float3==float1));//true //包装类型的==比较,赋值时采用的是直接赋值的方式 System.out.println("_Float1==_Float2 is : "+(_Float1==_Float2));//false,注意:这里是false,也就说不能使用这种比较方式 //包装类型的==比较,赋值时采用的是创建对应的对象的方式 System.out.println("_Float1==_Float3 is : "+(_Float1==_Float3));//false,注意:这里是false,也就说不能使用这种比较方式 System.out.println("_Float3==_Float4 is : "+(_Float3==_Float4));//false,注意:这里是false,也就说不能使用这种比较方式 //基本类型和包装类型的equals比较 System.out.println("_Float1.equals(float1) is : "+(_Float1.equals(float1)));//true //包装类型的equals比较 System.out.println("_Float1.equals(_Float2) is : "+(_Float1.equals(_Float2)));//true System.out.println("_Float3.equals(_Float1) is : "+(_Float3.equals(_Float1)));//true System.out.println("_Float3.equals(_Float4) is : "+(_Float3.equals(_Float4)));//true }}
4:使用Integer类,特别是integer1==integer3相比较时,更容易出错
package com.jd.test.integer;public class TestIntegerMain { public static void main(String args[]){ int int1 = 99; int int2 = 99; Integer _Integer1 = 99; Integer _Integer2 = 99; Integer _Integer3 = new Integer(99); Integer _Integer4 = new Integer(99); System.out.println("int1 identityHashCode is :"+System.identityHashCode(int1)+"\nint2 identityHashCode is :"+System.identityHashCode(int2)); System.out.println("_Integer1 hashCode is :"+_Integer1.hashCode()+"\n_Integer2 hashCode is :"+_Integer2.hashCode()); System.out.println("_Integer1 identityHashCode is :"+System.identityHashCode(_Integer1)+"\n_Integer2 identityHashCode is :"+System.identityHashCode(_Integer2)); System.out.println("_Integer3 hashCode is :"+_Integer3.hashCode()+"\n_Integer4 hashCode is :"+_Integer4.hashCode()); System.out.println("_Integer3 identityHashCode is :"+System.identityHashCode(_Integer3)+"\n_Integer4 identityHashCode is :"+System.identityHashCode(_Integer4)); //基本类型的==比较 System.out.println("int1==int2 is : "+(int1==int2));//true //基本类型和包装类型的==比较 System.out.println("int1==_Integer1 is : "+(int1==_Integer1));//true// System.out.println("_Integer1==int1 is : "+(_Integer1==int1));//true System.out.println("int1==_Integer3 is : "+(int1==_Integer3));//true// System.out.println("_Integer3==int1 is : "+(_Integer3==int1));//true //包装类型的==比较,赋值时采用的是直接赋值的方式 System.out.println("_Integer1==_Integer2 is : "+(_Integer1==_Integer2));//true //包装类型的==比较,赋值时采用的是创建对应的对象的方式 System.out.println("_Integer1==_Integer3 is : "+(_Integer1==_Integer3));//false,注意:这里是false,也就说不能使用这种比较方式 System.out.println("_Integer3==_Integer4 is : "+(_Integer3==_Integer4));//false,注意:这里是false,也就说不能使用这种比较方式 //基本类型和包装类型的equals比较 System.out.println("_Integer1.equals(int1) is : "+(_Integer1.equals(int1)));//true //包装类型的equals比较 System.out.println("_Integer1.equals(_Integer2) is : "+(_Integer1.equals(_Integer2)));//true System.out.println("_Integer3.equals(_Integer1) is : "+(_Integer3.equals(_Integer1)));//true System.out.println("_Integer3.equals(int1) is : "+(_Integer3.equals(int1)));//true System.out.println("_Integer3.equals(_Integer4) is : "+(_Integer3.equals(_Integer4)));//true }}
5:使用Long类,特别是_Long1==_Long3相比较时,更容易出错
package com.jd.test.integer;public class TestLongMain { public static void main(String args[]){ long long1 = 99; long long2 = 99;; Long _Long1 = 99L; Long _Long2 = 99L; Long _Long3 = new Long(99); Long _Long4 = new Long(99); System.out.println("long1 identityHashCode is :"+System.identityHashCode(long1)+"\nlong2 identityHashCode is :"+System.identityHashCode(long2)); System.out.println("_Long1 hashCode is :"+_Long1.hashCode()+"\n_Long2 hashCode is :"+_Long2.hashCode()); System.out.println("_Long1 identityHashCode is :"+System.identityHashCode(_Long1)+"\n_Long2 identityHashCode is :"+System.identityHashCode(_Long2)); System.out.println("_Long3 hashCode is :"+_Long3.hashCode()+"\n_Long4 hashCode is :"+_Long4.hashCode()); System.out.println("_Long3 identityHashCode is :"+System.identityHashCode(_Long3)+"\n_Long4 identityHashCode is :"+System.identityHashCode(_Long4)); //基本类型的==比较 System.out.println("long1==long2 is : "+(long1==long2));//true //基本类型和包装类型的==比较 System.out.println("long1==_Long1 is : "+(long1==_Long1));//true// System.out.println("_Long1==long1 is : "+(_Long1==long1));//true System.out.println("long1==_Long3 is : "+(long1==_Long3));//true// System.out.println("_Long3==long1 is : "+(_Long3==long1));//true //包装类型的==比较,赋值时采用的是直接赋值的方式 System.out.println("_Long1==_Long2 is : "+(_Long1==_Long2));//true //包装类型的==比较,赋值时采用的是创建对应的对象的方式 System.out.println("_Long1==_Long3 is : "+(_Long1==_Long3));//false,注意:这里是false,也就是说不能使用这种比较方式 System.out.println("_Long3==_Long4 is : "+(_Long3==_Long4));//false,注意:这里是false,也就是说不能使用这种比较方式 //基本类型和包装类型的equals比较 System.out.println("_Long1.equals(long1) is : "+(_Long1.equals(long1)));//true //包装类型的equals比较 System.out.println("_Long1.equals(_Long2) is : "+(_Long1.equals(_Long2)));//true System.out.println("_Long3.equals(_Long1) is : "+(_Long3.equals(_Long1)));//true System.out.println("_Long3.equals(_Long4) is : "+(_Long3.equals(_Long4)));//true }}
6:结论
6-1:当变量声明时使用的全部都是基本数据类型,使用==比较是没问题的,当然,也只能使用==看看他们是否相等,此时比较的是变量的值是否相等
6-2:当变量声明时全部或者部分使用了封装类型,使用==比较可能得不到我们预期的效果,建议一定使用equals方法,基本类型的包装类型类,都重写了equals方法,比较的是对象的内容是否相等,对于数据类型而言,就是他们的值是否相等
如果想问为什么这样呢?请参看吧!
如果你将代码执行起来,观察了一下的话,还是有些问题没解释清楚的,比如:为什么 int int1=99;int int2=99;int1和int2的identityHashCode是一样的哪?为什么float float1=99;float float2=99;float1和float2的identityHashCode是不一样的哪?那就需要了解identityHashCode的生成规则了,需要了解一下java的内存地址分配规则了。为什么double1==_Double1 is : true,但是他们的identityHashCode却不相等哪?这需要了解一下基本数据类型和封装类型,自动拆箱和自动装箱的相关知识点了。