发现做项目的过程中,在数值类型的比较上容易犯错,特别是Integer和Integer的比较,Integer和int的比较。虽然这些都是些基础语法,但稍不留意就容易犯错,在实际开发过程中如果出现这类失误,很容易失之毫厘谬以千里。在这里,总结下这些基础知识点。

java虽然宣称一切都是对象,但原始数据类型是例外。int是整形数字,是java的9个原始数据类型(Primitive Types)(boolean、byte、short、char、int、float、double、long、void)之一。Integer是int对应的包装类,它有一个int类型的字段存储数据,并且提供了基本操作,比如数学运算、int和字符串之间转换等。在java 5中引入了自动装箱和自动拆箱功能(boxing/unboxing),java可以根据上下文,自动进行转换,极大地简化了相关编程。javac自动把装箱转换为Integer.valueOf(),把拆箱替换为Integer.intValue()

自动装箱实际上算是一种语法糖。什么是语法糖?可以简单理解为java平台为我们自动进行了一些转换,保证不同的写法在运行时等价,他们发生在编译阶段,也就是生产的字节码是一致的。(此句摘自极客时间专栏)

原始数据类型的变量,需要使用并发相关手段才能保证线程安全。如果有线程安全的计算需要,建议考虑使用类似AtomicInteger、AtomicLong这样的线程安全类。

原始数据类型和java泛型并不能配合使用。因为java的泛型某种程度上可以算作伪泛型,它完全是一种编译期的技巧,java编译期会自动将类型转换为对应的特定类型。这就决定了使用泛型,必须保证相应类型可以转换为Object。

废话不多说,直接来demo,这样效果更直接。

public class Test {public static void main(String[] args) {Integer a1 = 6;Integer a2 = 6;int a11 = 6;System.out.println(a1 == a2); //trueSystem.out.println(a1 == a11); //trueSystem.out.println("----------------");Integer a3 = 128;Integer a4 = 128;int a33 = 128;System.out.println(a3 == a4); //false//Integer会自动拆箱为int,所以为trueSystem.out.println(a3 == a33); //trueSystem.out.println(a3.equals(a4)); //trueSystem.out.println("----------------");Integer a5 = new Integer(6);Integer a6 = new Integer(6);System.out.println(a5 == a6); //falseSystem.out.println(a5.equals(a6)); //true}

需要明确的一点是,包装型(Integer)和基本型(int)比较会自动拆箱(jdk1.5以上)。

在这里很多人比较容易迷惑的是如下情况:

     Integer a1 = 6;Integer a2 = 6;System.out.println(a1 == a2); //trueInteger a3 = 128;Integer a4 = 128;System.out.println(a3 == a4); //false

如果研究过jdk源码,你就会发现Integer a3 = 128;在java编译时会被翻译成 Integer a3 = Integer.valueOf(128); 我们再来看看valueOf()的源码就更清晰了。

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

由以上源码就会发现,对于-128到127之间的数,会进行缓存,Integer a1 = 6时,会将6进行缓存,下次再写Integer a2 = 6;时,就会直接从缓存中取,也就不用new一个对象了,所以a1和a2比较时就为true。但a3和a4是超过范围,会new一个对象,==是进行地址和值比较,是比较两个对象在JVM中的地址,这时a3和a4虽然值相同但地址是不一样的,所以比较就为false了。

通过上面的分析可知:

  • 两个都不是new出来的Integer,且数值在-128~127之间,用==比较时,基本值相等时为true,否则为false;
  • 两个都是new出来的Integer,为false
  • int和Integer比较,数值相同,用==比较时为true。(因为Integer会自动拆箱为int去比较)

所有包装类对象之间值的比较,建议使用equals方法比较

==判断对象是否同一个。

Integer var = ?在缓存区间的赋值,会复用已有对象,因此这个区间内的Integer使用==进行判断可通过,但是区间之外的所有数据,则会在上新产生,不会通过。

因此如果用== 来比较数值,很可能在小的测试数据中通过,而到了生产环境才出问题。

为了节省内容,对与下列包装对象的两个实例,当他们的基本值相同时,用==判断会为true:

 Boolean  Byte  Character, \u0000 - \u007f(7f是十进制的127)  Integer, -128 — 127

我们也可以看看其它包装型的缓存情况:

Boolean:(全部缓存)
Byte:(全部缓存)Character(缓存范围'\u0000'到'\u007F')
Short(-128 — 127缓存)
Long(-128 — 127缓存)Float(没有缓存)
Doulbe(没有缓存)

如果要比较两个Integer对象的值(均为new的对象),可以通过.intValue()进行转换后来比较,如下:

     Integer a3 = 128;Integer a4 = 128;System.out.println(a3.intValue() == a4.intValue());

也可以使用equal()来进行比较,如下:

     Integer a3 = 128;Integer a4 = 128;System.out.println(a3.equals(a4)); //true

Integer和Integer比较以及Integer和Int的比较分析相关推荐

  1. int 和 Integer有什么区别,Integer 有哪些函数方法

    [基本数据类型对象包装类JDk1.5以后的新特性]--[自动拆箱,装箱] 简化书写. Integer i = new Integer(5); 基本数据类型对象包装类,对象创建的简化写法Integer ...

  2. java int和integer的区别_int和Integer的区别

    int和Integer的区别 1.Integer是int的包装类,int则是java的一种基本数据类型 2.Integer变量必须实例化后才能使用,而int变量不需要 3.Integer实际是对象的引 ...

  3. int 和 Integer 有什么区别,Integer的值缓存范围

    目录 int与Integer的基本使用对比 int与Integer的深入对比 int与Integer的基本使用对比 Integer是int的包装类:int是基本数据类型: Integer变量必须实例化 ...

  4. integer比较_Java整数缓存Integer.valueOf(127)==Integer.valueOf(127)为True

    在一次采访中,我的一个朋友被问到,如果我们有两个整数对象,Integer a = 127; Integer b = 127;为什么要a == b的值为true ?在本文中,我将尝试回答这个问题,并解释 ...

  5. java integer long 转换_java - 将Integer转换为Long

    java - 将Integer转换为Long 我需要使用反射来获取字段的值. 碰巧我并不总是确定该字段的数据类型是什么. 为此,为了避免一些代码重复,我创建了以下方法: @SuppressWarnin ...

  6. Integer i1 = 10;和Integer = new Integer(10);的区别

    首先我们要明白Integer是引用数据类型,是包装类(封装类) 1.5版本之后,存在自动拆装包.他是int类型对应的封装类. Integer是直接继承于Number类间接继承于Object类 ,实现了 ...

  7. Integer对比的问题以及Integer的取值范围

    今天写完代码测试的时候遇到一个小bug,写下来做个记录 我发现当fTimeYear=2018,lTimeYear也等于2018时,结果竟然是false,然后我去查了integer的源码 static ...

  8. INTEGER PRIMARY KEY AUTOINCREMENT 和 INTEGER PRIMARY KEY 区别

    转自网络,地址不可考,谢谢原作者,如有冒犯,立即删除! Sqlite 中INTEGER PRIMARY KEY AUTOINCREMENT和rowid/INTEGER PRIMARY KEY的使用  ...

  9. 为何类型转型Integer[] = Object[]可以,而Integer[] = int[]却不行

    写代码的时候经常碰到这种情况,想在Integer[]和int[]之间互转,却直接提示编译期错误,很蛋疼.而Integer[]和Object[]之间却可以强转.以前一直觉得int和Integer的关系比 ...

最新文章

  1. 春招不迷茫,模板刷题101实验室上线啦
  2. Altium designer快捷键汇总
  3. 使用饼图_【Excel饼图使用系列】之使用饼图的注意事项及几个小技巧
  4. 收藏列表放入MySQL还是redis_mysql导入redis
  5. *和**在Python中意味着什么?它与指针和地址有关吗?
  6. Le-net网络总结
  7. erlang 编译 安装
  8. linux的awk命令如何用?
  9. 云计算学习笔记006---运行hadoop的例子程序:统计字符--wordcount例子程序
  10. 基于spss的偏相关分析(partial correlation analysis)
  11. 如何获取海量长尾关键词流量
  12. 意外找回CSDN老账号,记录记录新账号备忘
  13. 倾斜摄影测量三维实景建模
  14. Docker和Jenkins构建项目总结
  15. 教你如何进入有密码的 XP 系统
  16. Elastic:使用 ElastAlert 发送 Slack 通知
  17. 关于http的refer参数
  18. 最流行的编程语言2018_2018年十大最受欢迎的编程语言
  19. 与JDBC相识的第一天超级NICE
  20. Linux里得conda虚拟环境使用pip安装都包不可用-解决方法(实用,conda4.6+)

热门文章

  1. 小米6 android 9氮os,360 N7和小米6X哪个好 360手机N7与小米6X区别对比
  2. 白居易李白唐代诗三百
  3. redis切换数据库命令
  4. python面试宝典2018最新版
  5. 高级语言程序设计与c语言,高级语言程序设计-C语言.pdf
  6. mysql5张表连接查询_5、mysql的连接查询
  7. android Tab实现(仿新浪微博)
  8. ccxprocess启动项可以禁用么_Mac禁用Adobe无用自启动项如何操作 Mac禁用Adobe无用自启动项教程...
  9. mysql时间索引和格式探讨
  10. 58同城 2021校招 测试岗