Java基础之数据比较Integer、Short、int、short

基础很重要,基础很重要,基础很重要。重要的事情说三遍,。程序员

今天聊一聊Java的数据比较,这个范围比较大,基础类型的比较、引用类型的比较。c#

前提:缓存

一、Java和c#都提供自动装箱和自动拆箱操做,何为自动装箱,简单点说就是将值类型转换成为引用类型,自动拆箱就是将引用类型转换成为值类型。而且咱们还常常被教导,要避免自动的装箱和拆箱操做,由于这个会影响性能。ide

二、比较经常使用的运算符是==,equals。性能

下面分几类来讲明数据的比较,学习

引用类型之间的比较:Integer与Integer之间的比较、Boolean与Boolean之间的比较、Integer与Boolean之间的比较编码

值类型之间的比较:int与int之间的比较、int与bool之间的比较spa

值类型与引用类型之间的比较:Integer与int之间的比较、Boolean与bool之间的比较设计

开工code

引用类型之间的比较--Integer与Integer之间的比较

简单说明一下,Integer是引用类型,表明的是整形数字

上代码

 1 public static void main(String[] args) throws Exception {
 2          Integer integer = new Integer(0);
 3          Integer mInteger = Integer.valueOf(0);
 4          Integer sInteger = 0;
 5 
 6         System.out.println(integer == mInteger);//false
 7          System.out.println(integer == sInteger);//false
 8          System.out.println(mInteger == sInteger);//true
 9 
10         System.out.println(memoryAddress(integer));
11          System.out.println(memoryAddress(mInteger));
12          System.out.println(memoryAddress(sInteger));
13 
14     }
15 
16     private static int memoryAddress(Object object) {
17          // 内存地址会有所不一样
18          return System.identityHashCode(object);
19      }

 

执行结果:

image

分析:

一、执行结果和咱们预想的不太同样,引用类型是在堆上存放的,每一个引用的地址应该都不相同。可是mInteger == sInteger  执行结果为true,而且mInteger ,sInteger的内存地址是相同的。

二、要分析这个缘由,咱们须要了解Java设计者为了性能而进行的一些努力,查看Java源代码,能够看到Integer的valueof方法里面包含了一个缓存:其中IntegerCache.low =-127,IntegerCache.high=128

1 @HotSpotIntrinsicCandidate
2    public static Integer valueOf(int i) {
3        if (i >= IntegerCache.low && i <= IntegerCache.high)
4            return IntegerCache.cache[i + (-IntegerCache.low)];
5        return new Integer(i);
6    }

 

对于使用Integer.valueof()方法,若是数值是-127至128,那么会使用缓存对象,不然会new一个对象。

三、Integer sInteger = 0;   发生了什么呢?自动装箱,等价于Integer sInteger=Integer.valueOf(0)。经过这个,咱们就能够得出比较等于true的缘由了,都是从缓存中读取的对象,难怪内存地址会一致。

引用类型比较--Integer与Integer引用类型比较   使用equals

上代码:

 1 public static void main(String[] args) throws Exception {
 2          Integer integer = new Integer(0);
 3          Integer mInteger = Integer.valueOf(0);
 4          Integer sInteger = 0;
 5 
 6         System.out.println(integer == mInteger);// false
 7          System.out.println(integer == sInteger);// false
 8          System.out.println(mInteger == sInteger);// true
 9 
10         System.out.println(memoryAddress(integer));
11          System.out.println(memoryAddress(mInteger));
12          System.out.println(memoryAddress(sInteger));
13 
14         System.out.println(integer.equals(mInteger));//true
15          System.out.println(integer.equals(sInteger));//true
16          System.out.println(mInteger.equals(sInteger));//true
17 
18     }
19 
20     private static int memoryAddress(Object object) {
21          // 内存地址会有所不一样
22          return System.identityHashCode(object);
23      }

 

分析:使用equals比较,只要数值相同,那么比较结果就是相同。查看Java源代码:

1 public boolean equals(Object obj) {
2        if (obj instanceof Integer) {
3            return value == ((Integer)obj).intValue();
4        }
5        return false;
6    }

 

能够看到Integer的equals比较,其实比较的就是数值。

 

值类型之间的比较:int与int

上代码

1           int  m=0;
2           int i=0;
3           int s=0;
4           System.out.println(m==i);//true
5           //值类型是没有equals方法
6           //System.out.println(m.equals(i));

 

分析:对于int 的比较,无需多言,原本就是数值比较。

Integer与int的比较:

 1          Integer integer = new Integer(0);
 2          Integer mInteger = Integer.valueOf(0);
 3          Integer sInteger = 0;// 等价于Integer。valueof
 4          int i = 0;
 5          System.out.println(integer == i);//true
 6          System.out.println(mInteger == i);//true
 7          System.out.println(sInteger == i);//true
 8          System.out.println(integer.equals(i));//true
 9          System.out.println(mInteger.equals(i));//true
10          System.out.println(sInteger.equals(i));//true

 

分析:

一、Integer类型与int类型经过==比较,Integer会自动拆箱,转换成int数值进行比较

二、equals方法更是读取对应的int数值进行比较。

所以引用类型与值类型之间的比较,使用equals与==均可以。

 

简单总结:

一、引用类型之间的比较,因为存在-127至128之间的缓存对象,所以使用== 进行比较存在风险。优先使用equals进行比较

二、引用类型与值类型进行比较,因为会自动拆箱,所以使用==和equals均可以正确获得结果

三、建议在实际编码过程当中,对数值的比较使用equals

 

深刻总结:

不单单Integer,其余的基本类型也都存在缓存,下面给出一个简单图表进行说明

基本类型 装箱类型 取值范围 是否缓存 缓存范围
byte Byte -128~127 -128~127
short Short -2^15 ~ (2^15 - 1) -128~127
int Integer -2^31 ~ (2^31 - 1) -128~127

long

Long -2^63 ~ (2^63 - 1) -128~127
float Float --  
double Double

--

 
boolean Boolean true、false true、false
char Character \u0000 ~ \uffff \u0000 ~ \uffff

 

Java博大精深,要想深刻,基础必需要好,才能避免bug。

咱们程序员的职责就是少写bug,这才是咱们一直学习的动力。

相关文章
相关标签/搜索