Java 中 null > 0 为什么要报错,怎么用语法糖或者 JDK 封装的方法避免

363 天前
 yibo2018
if (a > 0) { }

if (Objects.compare(a, 0L, Long::compareTo) > 0) {        }

Exception in thread "main" java.lang.NullPointerException

上面这样写如果 a 是 null 就都会报错

一般写法是这样可以避免

if (a != null && a > 0) { }
···

但我实在不想每次遇到都写一遍判空逻辑
null 和 0 本来就不相等,为啥还要报错
我想找一个 JDK 封装的方法去解决,但没找到
3602 次点击
所在节点    程序员
41 条回复
crazyweeds
363 天前
@momocraft 深有同感,感觉 js 一直在走极端,明明只要一个强类型,然后搞出了 ts ,开始有人吐槽了。作为一个 java 写 js ,我觉得最难写的就是判断,各种出乎意料的结果。
crazyweeds
363 天前
@yazinnnn 感动哭了,JS 判断行为真的让人无语。
Still4
363 天前
用 long 不要用 Long ,你既然用了 Long ,那么说明有需求要区分 null 和 0
iyiluo
363 天前
null 和 0 能比较才是大问题吧,null 表示没赋值,未初始化,怎么能拿来比较
yibo2018
363 天前
@Still4 怪我没说清,用 Long 是因为在 HashMap 里面
DinnyXu
363 天前
我在想一个问题,已知变量 a 是数字类型,那么这个变量在判断的时候是否可以有默认值来代替呢,这样就可以进入你的 if 判断了啊。比如你数据库查询出来的 a 是 null 那么判断是否 > 0 肯定是会报错的,你数据库不能设置默认值吗。
githmb
363 天前
我的建议是换 Kotlin ,保证参数签名是 Long 的函数不会被 null 调用
qping
363 天前
你可以参数定义为 int a
hangszhang
363 天前
没参加考试是 null ,考了 0 分是 0 ,这就是包装类最大的意义,区分 0 和 null
dcsuibian
363 天前
null 是空,什么都没有怎么比
ThreeK
363 天前
既然都报了 NullPointerException 那就是变量有 null 的情况,去处理 null 的场景,自己定义 null 和 0 比较的结果。
要是代码能百分百确定不是 null ,那你担心什么抛异常。
oldshensheep
363 天前
语法糖用 manifold ,甜死我啦。

你这个用 manifold 好像不能实现,但是可以用扩展方法实现一个类似解决方案
```java
public class DemoApplication {
public static void main(String[] args) {
Long num = null;
num.greater(1).print();
}
}
```
虽然 num 是 null 但是不会有 NPE ,实际上就是调用你写的静态的扩展方法

运行结果是 true
greater 是扩展方法,返回一个 Boolen
print 是扩展方法,调用 sout

你这个就直接
a.greater(0)
oldshensheep
363 天前
@oldshensheep 上面输出结果说错了,结果是 false
Still4
363 天前
@yibo2018 map 的话我觉得需要在写入的时候检查 null 的情形,读取的时候就不需要担心 npe 了
Aynamic
363 天前
不要用包装类就不会,用包装类就 equals
Ericcccccccc
363 天前
因为 java 里面 0, 1 这种数字很独特, 是个"基本类型",

a 作为一个对象, 想和基本类型做大小比较, 需要先转成基本类型, 而 null 是转不过去的
CLMan
363 天前
别想太多,纯粹是 JS 设计太烂而已。

null 与 0 之间转换本来就不符合逻辑,各种语言都给你来这种 feature ,而且还不保持一致,你如果是个多语言用户你咋办,死记硬背这些莫名其妙的无聊规则吗?
nothingistrue
363 天前
@yibo2018 #20 a 是 Long 的时候,a > 0 在编译时会被转换为 a.longValue > 0 (实际情况可能只是编译后等效而不是先转换再编译,但可以先这么认为)。原本 null > 0 ,或者对量变量 obj > 0 ,都是编译错误,8 个封装类型是加了语法糖,才能这么写。

知道以上情况,会更容易定位到 NullPointerException “> 0” 没有关系,抛出它的地方是 a.longValue 的时候 a 是 null 。这只是一个很普通但很难处理的 NPE 问题。对于你这种从别的地方接过来的变量(不是你能控制的变量)来说,你只能判断它给你的是不是 null ,但不能控制它不给你 null ,所以是铁定要做 null 判断的。

如果你只是需要代码更好写 /看,而不是避开 null 判断,那还是有办法的。可以写成这样,if ( requestNonNullOrDefult(a, -1) > 0) 。requestNonNullOrDefult 就需要你自己提供,或者找第三方工具包了,JDK 是没有的。JDK 8 以后用了另一种套路来解决 NPE 问题,它要求方法返回一定不会是 null 的对象,要么是确实不会是 null 的对象,要么是可能为 empty 的 Optiona<T> 对象。
jim9606
362 天前
因为算术运算符与 null 运算,不管是返回 null 还是 false 都不合常理,例如 == 和 != 会同时返回 null/false
你需要的是默认值,将需要比较的 nullable 变量转为 not nullable ,例如 C#的 null 合并运算符 ?? 和 ??=
```
(someVar ??= -1) > 0
```
不过关系运算符支持 null 倒是合理的。
blankmiss
362 天前
你没有用过 Optional 吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/941309

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX