java.lang.NullPointerException 不幸中的万幸?
NullPointerException应该是最常遇见的异常,但通常也比较容易解决
好的编程习惯可以减少这类异常的发生
返回值
函数的返回值尽量不要设计成返回null, 设计成null势必需要调用者进行检查,阻碍链式调用
如果没有特殊原因,可以返回空值代替null
- 字符串类型:Commons-lang的StringUtils可以返回空字符串StringUtils.EMPTY
- 数组类型:Commons-lang的ArrayUtils可以返回一系列空数组如ArrayUtils.EMPTY_INT_ARRAY
- 集合类型:Java自带的Collections可以返回空集合,并且都是不可变的,如Collections.emptyMap(),Collections.emptySet(),Collections.emptyList()
如果方法一定要返回null,应该详细注释
Optional
Java8引入了Optional类,标准库引入之前,Guava类库也提供类似功能
如果一定需要表示没有的情况,可以使用Optional
Optional是null的包装类,实现上仅仅是包含一个泛型变量
Optional顾名思义就是可选值,也就是表示可能有null存在。语义上更加明确,避免了以往忘记检查null的情况
1 | public final class Optional<T>{ |
包含四种基本操作:
- of/ofNullable 值包装成Optional
- isPresent 判断是否有值
- get 从Optional取出值
- orElse 无值时返回指定值
还有和lambda结合的操作
- ifPresent 有值时执行操作
- orElseGet 无值时执行操作生成指定值
- map/flatMap 转换生成新Optional或空Optional
- filter 条件返回自身或空Optional
Option在使用时,遇到null值就用空对象表示,相当于在内部消除了null
1 | public static <T> Optional<T> ofNullable(T value) { |
lambda操作的返回值也都是Optional,可以解决链式调用问题
1 | public<U> Optional<U> map(Function<? super T, ? extends U> mapper) { |
比如obj.getA().getB().getC(),中间A和B都可能是null,影响调用链,需要检查
1 | if(obj.getA() != null && obj.getA().getB() != null) { |
使用Optional可以
1 | Optional.ofNullable(obj) |
equals比较
因为对等性a.equals(b)和b.equals(a)效果是一样的,但是已知量在前可以避免NullPointer。
1 | "abc".equals(str); //str为null,返回false |
Java7 Objects.equals
内部处理null逻辑,使用时可以无视顺序
1 | public static boolean equals(Object a, Object b) { |
toString
尽量不用str.toString(),可以使用String.valueOf(str)
可以看出valueOf方法也是最终调用toString(),但好处是包含了null值检查
1 | public static String valueOf(Object obj) { |
Java7 Objects.toString
toString名字比较直观,为了继续使用,再包装一层
1 | public static String toString(Object o) { |
还可以在null值时使用替代值
1 | public static String toString(Object o, String nullDefault) { |
null防卫
检查到是null就抛出NullPointerException
Java7 Objects.requireNotNULL
1 | public static <T> T requireNonNull(T obj, String message) { |
null判断
如果厌倦了obj == null
这种判断,还可以采用Objects类在Java8中提供的方法
1 | public static boolean isNull(Object obj) { |
多值情况下可以用commons.lang3
中ObjectUtils.allNotNull
和ObjectUtils.anyNotNull
空判断
拿到一个可能空值的对象,首先要null判定然后才能空值判定
可以使用null容忍的工具类
- 针对String类型,可以采用
commons.lang
中的StringUtils.isEmpty
- 针对数组类型,可以采用
commons.lang
中的ArrayUtils.isEmpty
- 针对集合类型, 可以采用
commons.collections
中的Collections.isEmpty
null替换默认值
commons.lang3
中ObjectUtils.defaultIfNull
典型的情况是数字拆箱
1 | Integer objValue = null; |
版权声明
This site by Linest is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由Linest创作并维护的博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。