没人会喜欢空指针异常!有什么方法可以避免它们吗?或许吧。。
本文将讨论到以下几种技术
1.Optional类型(Java 8中新引入的)
2.Objects类(Java 7中原有的)
Java 8中的Optional类
它是什么?
1.Java 8中新引入的类型
2.它是作为某个指定类型的对象的包装器或者用于那些不存在对象(null)的场景
简单来说,它是处理空值的一个更好的替代品(警告:乍一看可能并没有那么明显)
基本用法
它是一种类型(一个类)——那么,怎么才能创建一个这个类型的实例?
使用下它的三个静态方法就可以了:
public static Optional<String> stringOptional(String input) { return Optional.of(input); }
简单明了——创建一个包含这个值的Optional包装器。记住——如果这个值是null的话,它会抛出NPE!
public static Optional<String> stringNullableOptional(String input) { if (!new Random().nextBoolean()) { input = null; } return Optional.ofNullable(input); }
我个人认为是要更好一点。这样就不会有NPE的风险了——如果输入为null的话,会返回一个空的Optional。
public static Optional<String> emptyOptional() { return Optional.empty(); }
如果你真的就是希望返回一个”空"值的话。“空”值并不意味着null。
好吧,那如何去消费/使用Optional呢?
public static void consumingOptional() { Optional<String> wrapped = Optional.of("aString"); if (wrapped.isPresent()) { System.out.println("Got string - " + wrapped.get()); } else { System.out.println("Gotcha !"); } }
简单的方法就是检查Optional包装器是否真的有值(使用isPresent方法)——你会怀疑这和使用if(myObj != null)相比有什么好处。别担心,这个我会解释清楚的。
public static void consumingNullableOptional() { String input = null; if (new Random().nextBoolean()) { input = "iCanBeNull"; } Optional<String> wrapped = Optional.ofNullable(input); System.out.println(wrapped.orElse("default")); }
你可以使用orElse方法,这样万一封装的确实是一个null值的话可以用它来返回一个默认值——它的好处显而易见。在提取出真实值的时候可以避免调用ifPresent方法这样明显多余的方式了。
public static void consumingEmptyOptional() { String input = null; if (new Random().nextBoolean()) { input = "iCanBeNull"; } Optional<String> wrapped = Optional.ofNullable(input); System.out.println(wrapped.orElseGet( () -> { return "defaultBySupplier"; } )); }
这个我就有点搞不清楚了。为什么有两个同样目的的不同方法?orElse和orElseGet明明可以重载的(同名但不同参数)。
不论如何,这两个方法明显的区别就在于它们的参数——你可以选择使用lambda表达式而不是Supplier的实例来完成这个(一个函数式接口)
为什么使用Optional要比常见的null检查强?
1.使用Optional最大的好处就是可以更明白地表述你的意图——返回null值的话会让消费者感到疑惑(当真的出现NPE的时候)这是不是故意返回的,因此还得查看javadoc来进一步定位。而使用Optional就相当明了了。
2.有了Optional你就可以彻底避免NPE了——如上所提,使用Optional.ofNullable,orElse以及orElseGet可以让我们远离NPE。
另一个救星!
看下这个代码片段
package com.abhirockzz.wordpress.npesaviors; import java.util.Map; import java.util.Objects; public class UsingObjects { String getVal(Map<String, String> aMap, String key) { return aMap.containsKey(key) ? aMap.get(key) : null; } public static void main(String[] args) { UsingObjects obj = new UsingObjects(); obj.getVal(null, "dummy"); } }
哪个可能会为空?
1.Map对象
2.进行搜索使用的key
3.方法调用的这个实例
如果抛出NPE的话,我们怎么能确定到底是哪个是null的?
package com.abhirockzz.wordpress.npesaviors; import java.util.Map; import java.util.Objects; public class UsingObjects { String getValSafe(Map<String, String> aMap, String key) { Map<String, String> safeMap = Objects.requireNonNull(aMap, "Map is null"); String safeKey = Objects.requireNonNull(key, "Key is null"); return safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null; } public static void main(String[] args) { UsingObjects obj = new UsingObjects(); obj.getValSafe(null, "dummy"); } }
requireNonNull方法
1.如果对象不为null的话就返回它本身
2.如果值为null的话,返回的NPE会带有指定的消息
为什么比if(myObj!=null)要好?
你所看到的栈跟踪信息会很清楚地看见Objects.requireNonNull的方法调用。这个再配合你自己的错误日志,可以让你更快地定位问题。。。至少在我看来是更快。
你还可以自己自义校验器,比如说实现一个简单的校验器来确保没有空值。
import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Predicate; public class RandomGist { public static <T> T requireNonEmpty(T object, Predicate<T> predicate, String msgToCaller){ Objects.requireNonNull(object); Objects.requireNonNull(predicate); if (predicate.test(object)){ throw new IllegalArgumentException(msgToCaller); } return object; } public static void main(String[] args) { //Usage 1: an empty string (intentional) String s = ""; System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "My String is Empty!")); //Usage 2: an empty List (intentional) List list = Collections.emptyList(); System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "List is Empty!").size()); //Usage 3: an empty User (intentional) User user = new User(""); System.out.println(requireNonEmpty(Objects.requireNonNull(user), (u) -> u.getName().isEmpty(), "User is Empty!")); } private static class User { private String name; public User(String name){ this.name = name; } public String getName(){ return name; } } }
不要让NPE在错误的地方成为痛苦。我们有许多工具能更好地处理NPE,甚至彻底地根除它们!
本文向大家介绍java 避免出现NullPointerException(空指针)的方法总结,包括了java 避免出现NullPointerException(空指针)的方法总结的使用技巧和注意事项,需要的朋友参考一下 java 避免出现NullPointerException(空指针)的方法总结 Java应用中抛出的空指针异常是解决空指针的最好方式,也是写出能顺利工作的健壮程序的关键。俗话说“预
本文向大家介绍利用Java8 Optional如何避免空指针异常详解,包括了利用Java8 Optional如何避免空指针异常详解的使用技巧和注意事项,需要的朋友参考一下 前言 空指针是我们最常见也最讨厌的异常,为了防止空指针异常,你不得在代码里写大量的非空判断。 Java 8引入了一个新的Optional类。用于避免空指针的出现,也无需在写大量的if(obj!=null)这样的判断了,前提是你得
问题内容: 有可能这可能是一个双重问题。我将String变量初始化为null。我可能会或可能不会使用一个值更新它。现在我想检查此变量是否不等于null以及我尝试执行的操作是否会得到null指针异常。空指针异常,因为它代价高昂。是否有任何有效的解决方法.TIA 问题答案: 如果您使用 你 不会 得到。 我怀疑你在做什么: 这是因为null 而引发,而不是因为null。 如果仍然无法解释,请发布您用于
我已经更新了我的项目中的一些依赖关系之后,我的Hibernate配置类显示Nullpointerx的。 我将SpringDataJPA存储库与hibernate一起使用,已经超过24小时了,仍然没有找到任何关于小问题的适当解决方案。 我已经尝试过的一些解决方案:- 使用@bean(name=“entityManagerFactory”)提供bean名称 我面临的问题 波姆。xml文件 配置类 db
它是从哪里来的?