专栏首页闷骚的程序员Java 中的比较运算符

Java 中的比较运算符

小菜鸟才学习 Java 没多久,这天要写一个存储长整形的列表,于是这样写:

List<long> listData = new ArrayList<long>();

这时 Android Studio 不高兴了,在 long 下面打上红色波浪线,然后提示小菜鸟:

Type argument cannot be of primitive type

赶紧进 List 的定义看了一下,发现类型参数必须是引用类型,不能用原始数值类型。

于是就改为:

List<Long> listData = new ArrayList<Long>();

这时 Android Studio 不说什么了,于是小菜鸟很开心地继续往下写,往 listData 里添加了一些 long 类型的值,并且给它们排了序,如果发现它们中有相邻并且不相等的元素后执行一些操作:

int size = listData.size();
for (int i = 1; i < size; i++) {
    if (listData.get(i - 1) != listData.get(i)) {
        // do something
    }
}

这时 Android Studio 貌似又不高兴了,在 != 上加上黄底色,指上去一看显示:

Number objects are compared using '!=', not 'equals()'

小菜鸟不高兴了,我比较两个 long 类型都非得用方法,不能用操作符了吗?(他脑子里的定势一直以为 List 的类型参数还是 long 呢),Java 就是比 C++ 矫情。想想 IDE 这里只是警告,并不是错误,所以也不加理会继续完成他的代码去了。

但是到后来怎么运行结果都不太对,明明给 List 里添加的元素里有相等的,有些情况下应该不进入 if 才对,可是却每次比较完都进了 if。百思不得其解之后想起了 Android Studio 的警告,然后把 != 改成 !list.get(i -1).equals(listData.get(i)),立马就好了。

小菜鸟惭愧极了,基础不牢靠啊,赶紧翻出自己的 Java 入门书对应的章节看了一下,看完才恍然大悟,原来 Java 里的比较运算符里还有这么多小细节呢……不是把 C++ 里的经验直接照搬过来就行了的。

Java 比较运算符里的一些细节

  • >>=<<= 只支持两边操作数都是数值类型。
  • ==!= 两边的操作数可以都是数值类型,也可以都是引用类型,但必须是同一个类的实例。
  • obj1obj2 引用同一个对象时,则 obj1 == obj2,否则 obj1 != obj2
  • 每种数值类型都有对应的包装类,比如 long 的包装类 Long。包装类的实例可以与数值型的值比较,是直接取出包装类实例所包装的数值来比较的。
  • 涉及自动装箱后情况复杂了一些,比如 Integer ina = 18; Integer inb = 18; Integer inc = 188; Integer ind = 188; 这时 ina == inb 成立,而 inc == ind 不成立。 原因是在 java.lang.Integer 类里,对 -128~127 之间的整数自动装箱成 Integer 实例,并且缓存了起来,所以对此范围内的整数自动装箱时,实际上都指向了缓存里的对象,所以会出现上面的情况。 与此类似的是 String 类型也会对诸如 String stra = "Hello"; 这样的直接赋值创建的实例进行缓存。

最佳实践

  • 引用类型实例之间,除非想要知道是否是引用同一个对象,否则它们之间的比较,总是使用 equals() 方法。

参考

《疯狂 Java 讲义》——李刚著 第 3.7.5 节 比较运算符。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 阅读源码的意义与方法

    思索了这两个问题良久,也去知乎找了一些相关话题的问答,但并没有标准答案。所以,我这里也只是记录一些我对此的看法,也许会随着 RTFSC 阅历的丰富而发生变化,我...

    mzlogin
  • TortoiseSVN 从 GitHub 更新时发生异常

    使用 TortoiseSVN 从 GitHub 仓库 Update 时,弹出错误提示对话框:

    mzlogin
  • 为 Markdown 生成 TOC 的 Vim 插件

    因为饱受 GFM 和 Redcarpet 两种 Markdown 引擎生成 TOC 链接的差异的折磨,而我又不得不同时使用它们——博客基于 Jekyll 使用 ...

    mzlogin
  • 【玩转腾讯云】使用Docker一键部署Cloudreve网盘

    项目地址:https://github.com/littleplus/Cloudreve-Docker 容器地址:https://hub.docker.com...

    YINUXY
  • JVM堆

    堆针对一个JVM进程来说是唯一的,也就是一个进程只有一个JVM,但是进程包含多个线程,他们是共享同一堆空间的。

    麋鹿大哥
  • CVPR 2020 | 中科大提出AANet:高效立体匹配的适应聚合网络

    CVPR2020接受的工作,AANet: Adaptive Aggregation Network for Efficient Stereo Matching。

    Amusi
  • H3C开启SNMP协议

    snmp-agent  snmp-agent local-engineid 800063A2035866BAF05801  snmp-agent commu...

    py3study
  • OC学习1——基本数据类型

    1、OC是在C语言的基础上进行扩展的一种面向对象的编程语言。很多基础知识都和C语言中的非常类似。首先介绍一下OC中的基本数据类型,整体框架如下图: ?  2、自...

    mukekeheart
  • redis集群简单介绍

    redis是单线程,但是一般的作为缓存使用的话,redis足够了,因为它的读写速度太快了。

    随心助手
  • redis集群原理

    redis是单线程,但是一般的作为缓存使用的话,redis足够了,因为它的读写速度太快了。       官方的一个简单测试:     测试完成了50个并发执行1...

    MonroeCode

扫码关注云+社区

领取腾讯云代金券