本文共 3241 字,大约阅读时间需要 10 分钟。
byte,short,char,int,long,float,double,boolean属于基本数据类型,它们之间的比较,比较的是它们的值。当比较的两个基本数据类型不同时,会进行自动类型转换,小类型会转换成大类型,此时比较的也是值,当无法进行自动类型转换,便会报语法错误。
从本质来讲,基本数据类型比较的也是内存地址,因为有jvm的常量池,所以我们赋值的是常量的内存地址。
引用数据类型是指对象、数组、字符串等之间的比较,比较的是它们的内存地址。
字符串比较举例String s1 = "abs"; String s2 = "abs"; // String s3 = new String("abs"); System.out.println(s1 == s2);//s1与s2 内存地址相同 System.out.println(s2 == s3);//s2与s3 内存地址不相同
在编译时s1和s2的字符串"abs"会被放入jvm的常量池中。所以s1和s2在赋值的时候都是一样指向常量池中"abs"的内存地址。而s3不同,s3新new String对象,其字符串内容被放在heap堆中,s3在stack栈中指向heap地址。因此s2和s3内存地址不同。
包装器类型是指基本数据类型对应的类(如:int与Integer)。在比较时,会进行自动拆箱、装箱的操作。
注:装箱就是包装成对象;拆箱就是拆为基本数据类型
自动拆箱和装箱举例//自动装箱Integer a = 127; //实际上是 Integer.valueOf(127)//自动拆箱int b = a; //实际上是 a.intValue()
Integer.valueOf()源码介绍
/** * Returns an {@code Integer} instance representing the specified * {@code int} value. If a new {@code Integer} instance is not * required, this method should generally be used in preference to * the constructor {@link #Integer(int)}, as this method is likely * to yield significantly better space and time performance by * caching frequently requested values. * * This method will always cache values in the range -128 to 127, * inclusive, and may cache other values outside of this range. * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
从源码中可以看出,该方法使用了IntegerCache进行缓存,缓存值的范围在-128~127之间。当未超过该区间时,使用的是相同的内存地址,超过该区间时,会重新new一个新Integer对象,所以内存地址不同啦
同理的Short、Long类也有类似的操作。我们只需要正确理解内存地址、拆装箱的操作即可。
intValue()方法是将Integer类型转换成int类型
具体源码如下:/** * Returns the value of this {@code Integer} as an * {@code int}. */ public int intValue() { return value; }
equals()方法是所有对象都拥有的默认方法。使用时我们必须明确的了解对应对象的equals()具体实现。常用的String、Integer已经实现好了
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
可以看出,Integer对象的equals() 方法,先判断类型是否相同,再判断值是否相等
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
可以看出,String对象的equals() 方法,先比较内存地址,其次比较类型是否相同,以及比较字符串值
具体源码如下:
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }
可以看出,Objects.equals()方法,先比较内存地址,如果内存地址不同会继续比较对象的值。与普通equals()方法不同的是,Objects.equals()方法可以防止空指针异常问题
转载地址:http://zhtii.baihongyu.com/