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

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

前提:

1、Java和c#都提供自动装箱和自动拆箱操作,何为自动装箱,简单点说就是将值类型转换成为引用类型,自动拆箱就是将引用类型转换成为值类型。并且我们还经常被教导,要避免自动的装箱和拆箱操作,因为这个会影响性能。

2、比较常用的运算符是==,equals。

下面分几类来说明数据的比较,

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

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

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

开工

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

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

上代码

 public static void main(String[] args) throws Exception {
Integer integer = new Integer(0);
Integer mInteger = Integer.valueOf(0);
Integer sInteger = 0; System.out.println(integer == mInteger);//false
System.out.println(integer == sInteger);//false
System.out.println(mInteger == sInteger);//true System.out.println(memoryAddress(integer));
System.out.println(memoryAddress(mInteger));
System.out.println(memoryAddress(sInteger)); } private static int memoryAddress(Object object) {
// 内存地址会有所不同
return System.identityHashCode(object);
}

执行结果:

分析:

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

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

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

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

3、Integer sInteger = 0;   发生了什么呢?自动装箱,等价于Integer sInteger=Integer.valueOf(0)。通过这个,我们就可以得出比较等于true的原因了,都是从缓存中读取的对象,难怪内存地址会一致。

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

上代码:

 public static void main(String[] args) throws Exception {
Integer integer = new Integer(0);
Integer mInteger = Integer.valueOf(0);
Integer sInteger = 0; System.out.println(integer == mInteger);// false
System.out.println(integer == sInteger);// false
System.out.println(mInteger == sInteger);// true System.out.println(memoryAddress(integer));
System.out.println(memoryAddress(mInteger));
System.out.println(memoryAddress(sInteger)); System.out.println(integer.equals(mInteger));//true
System.out.println(integer.equals(sInteger));//true
System.out.println(mInteger.equals(sInteger));//true } private static int memoryAddress(Object object) {
// 内存地址会有所不同
return System.identityHashCode(object);
}

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

 public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

可以看到Integer的equals比较,其实比较的就是数值。

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

上代码

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

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

Integer与int的比较:

          Integer integer = new Integer(0);
Integer mInteger = Integer.valueOf(0);
Integer sInteger = 0;// 等价于Integer。valueof
int i = 0;
System.out.println(integer == i);//true
System.out.println(mInteger == i);//true
System.out.println(sInteger == i);//true
System.out.println(integer.equals(i));//true
System.out.println(mInteger.equals(i));//true
System.out.println(sInteger.equals(i));//true

分析:

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

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

因此引用类型与值类型之间的比较,使用equals与==都可以。

简单总结:

1、引用类型之间的比较,由于存在-127至128之间的缓存对象,因此使用== 进行比较存在风险。优先使用equals进行比较

2、引用类型与值类型进行比较,由于会自动拆箱,因此使用==和equals都可以正确得到结果

3、建议在实际编码过程中,对数值的比较使用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,这才是我们一直学习的动力。

Java基础之数据比较Integer、Short、int、short的更多相关文章

  1. java基础解析系列(二)---Integer

    java基础解析系列(二)---Integer 前言:本系列的主题是平时容易疏忽的知识点,只有基础扎实,在编码的时候才能更注重规范和性能,在出现bug的时候,才能处理更加从容. 目录 java基础解析 ...

  2. Java进阶(三十四)Integer与int的种种比较你知道多少?

    Java进阶(三十四)Integer与int的种种比较你知道多少? 前言 如果面试官问Integer与int的区别:估计大多数人只会说到两点:Ingeter是int的包装类,注意是一个类:int的初值 ...

  3. Java基础【基本数据类型包装类、int与String 之间的相互转换】

    为什么会有基本类型包装类? 将基本类型数据类型封装成对象,这样的好处可以在对象中定义更多方法操作该数据. 包装类常用的操作就是用于基本数据类型与字符串之间的转换 问题:int a=100; 为什么不能 ...

  4. Java数据类型中String、Integer、int相互间的转换

    1.Integer转换成int的方法 Integer i;  int k = i.intValue(); 即Integer.intValue(); 2.int转换成Integer int i; Int ...

  5. 【Java面试题】5 Integer的int 的种种比较?详细分析

    如果面试官问Integer与int的区别:估计大多数人只会说道两点,Ingeter是int的包装类,int的初值为0,Ingeter的初值为null.但是如果面试官再问一下Integer i = 1; ...

  6. (备忘)Java数据类型中String、Integer、int相互间的转换

    1.Integer转换成int的方法 Integer i; int k = i.intValue();即Integer.intValue(); 2.int转换成Integer int i; Integ ...

  7. Java基础:整型数组(int[]、Integer[])排序

    Windows 10家庭中文版,java version "1.8.0_152",Eclipse Oxygen.1a Release (4.7.1a), 参考链接:http://w ...

  8. java基础之数据类型转换

    在写java程序时,经常会遇到需要数据类型转换,下面我们来介绍一些一些基本数据类型之间的转换. 1.int,folat,double,boolean,long 转换成字符串,其实很简单只需使用一个函数 ...

  9. java基础类型数据与String类包装类之间的转换与理解

    数据类型转换一般分为三种: 在java中整型,实型,字符型视为简单数据类型,这些数据类型由低到高分别为:(byte,short,char--int-long-float-double) 简单数据类型之 ...

随机推荐

  1. 移动Web前端,游客点击商品的收藏按钮,登录完成,回来之后,如何自动收藏

    我们都知道,移动Web端(M站环境下),很多时候,前端是无法判断用户的登录状态的,因为出于安全性考虑,与账号相关的cookie字段一般都是 http-only的. 如果前端想判断用户的登录状态,需要主 ...

  2. 搭建的flask项目,若修改项目中的文件,项目没有reload,除非重启主机,解决方法如下

    1.博主本人前面有发过一篇博文如何搭建flask项目,可以去查看. 解决办法:加入一句 touch-reload=项目目录在uwsgi.ini 2.测试没问题

  3. OPPO A57 刷机(官方安装包)+完美Root+ 破解主题+屏蔽Root顶部红色框+NV修复

    朋友说她的手机被被人刷后,有许多预装的软件问我能不能处理下,让我装个纯净版. 开机可以看到预装了许多软件,通常想要删除预装软件就必须Root,于是下载刷机精灵,360刷机大师,线刷包之类的软件Root ...

  4. xtrabackup部署以及使用

    简介 备份mysql数据库一直是一个比较恶心的工作,主要就是备份的数据库比较大实在是慢.最近开始使用xtrabackup来备份数据库,速度上快了很多,尤其还原速度要快的多.下面我将从安装开始简要介绍一 ...

  5. Javascript 高级程序设计--总结【三】

    ********************  Chapter 8 BOM ******************** BOM由浏览器提供商扩展 window: 既是js访问浏览器窗口的接口,又是Globa ...

  6. Python数据类型转换函数

    数据类型转换函数 函 数 作 用 int(x) 将 x 转换成整数类型 float(x) 将 x 转换成浮点数类型 complex(real[,imag]) 创建一个复数 str(x) 将 x 转换为 ...

  7. Lua中的#

    Lua中的 对字符串来说,#取字符串的长度,但对于table需要注意. lua的table可以用数字或字符串等作为key, #号得到的是用整数作为索引的最开始连续部分的大小, 如果t[1] == ni ...

  8. no plugin found for prefix 'tomcat 7' in the current project and in the plugin groups的解决方法

    解决方法一: 找到这个settings.xml文件,进行编辑,在pluginGroups标签下加入下面的配置 <pluginGroups><pluginGroup>org.ap ...

  9. leetcode刷题--两数之和(简单)

    一.序言 第一次刷leetcode的题,之前从来没有刷题然后去面试的概念,直到临近秋招,或许是秋招结束的时候才有这个意识,原来面试是需要刷题的,面试问的问题都是千篇一律的,只要刷够了题就差不多了,当然 ...

  10. Spring的AOP基于AspectJ的注解方式开发2

    参考自黑马培训机构 上一篇博客提到了在配置文件中开启aop的注解开发,以及简单使用了@Before,@Aspect 这是为了告诉spring为前置通知和切面类 接下来介绍aop的注解的通知类型,和切入 ...