精华内容
下载资源
问答
  • 参数Integer等包装类型时,因为自动拆箱出现了空指针异常 字符串比较出现空指针异常 诸如ConcurrentHashMap这样的容器不支持Key和Value为null,强行put null的Key或Value会出现空指针异常 A对象包含了B,在通过A...

    空值处理:如何避免空指针异常?

    常见的5种空指针异常场景

    • 参数值是Integer等包装类型时,因为自动拆箱出现了空指针异常
    • 字符串比较出现空指针异常
    • 诸如ConcurrentHashMap这样的容器不支持Key和Value为null,强行put null的Key或Value会出现空指针异常
    • A对象包含了B,在通过A对象的字段获得B之后,没有对字段判空就级联调用B的方法
    • 方法或远程服务返回的List不是空而是null,没有判空就直接调用List的方法出现空指针异常

    解决方法

    使用Optional.ofNullable方法捕获null,然后使用orElse方法给null的字段赋值,如下:

    import java.util.Optional;
    
    // 如果var为null,则初始化为""
    Optional.ofNullable(var).orElse("");
    
    展开全文
  • java中如何避免空指针异常

    千次阅读 2014-04-16 11:52:43
    java中的空指针最常见的错误之一,要尽量避免空指针异常,首先在使用对象前,先对其进行初始化。 另外,要完全避免空指针,最好做到以下几点: 1:对于所有 public 方法传入的对象参数进行 null 值检查 2:对于...
    
    

    java中的空指针是最常见的错误之一,要尽量避免空指针异常,首先在使用对象前,先对其进行初始化。

    另外,要完全避免空指针,最好做到以下几点:
    1:对于所有 public 方法传入的对象参数进行 null 值检查
    2:对于所有从数据库获取的对象进行 null 值检查
    3:对于所有从网络、IO 中获取的数据(对象)进行 null 值检查

    同时,也要注意编码的形式,如:

    有时检察输入的String类型变量str是否为合法输入时,使用判断:
    if( str!= null && !str.isEmpty() )
    而不能写成 if( !str.isEmpty() && str!= null )这样的话程序因为优先执行左边的判断语句,从而导致NullPointerException 的发生.

    展开全文
  • java防止空指针异常

    2020-09-22 16:23:18
    java 中任何对象都有可能为空,当我们调用空对象的方法时就会抛出 NullPointerException 空指针异常,这一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常,使得我们的代码更为健壮。本文将列举...

    java 中任何对象都有可能为空,当我们调用空对象的方法时就会抛出 NullPointerException 空指针异常,这是一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常,使得我们的代码更为健壮。本文将列举这些解决方案,包括传统的空值检测、编程规范、以及使用现代 Java 语言引入的各类工具来作为辅助。

    运行时检测
    最显而易见的方法就是使用 if (obj == null) 来对所有需要用到的对象来进行检测,包括函数参数、返回值、以及类实例的成员变量。当你检测到 null 值时,可以选择抛出更具针对性的异常类型,如 IllegalArgumentException,并添加消息内容。我们可以使用一些库函数来简化代码,如 Java 7 开始提供的 Objects#requireNonNull 方法:

    public void testObjects(Object arg) {
      Object checked = Objects.requireNonNull(arg, "arg must not be null");
      checked.toString();
    }
    

    Guava 的 Preconditions 类中也提供了一系列用于检测参数合法性的工具函数,其中就包含空值检测:

    public void testGuava(Object arg) {
      Object checked = Preconditions.checkNotNull(arg, "%s must not be null", "arg");
      checked.toString();
    }
    

    我们还可以使用 Lombok 来生成空值检测代码,并抛出带有提示信息的空指针异常:

    public void testLombok(@NonNull Object arg) {
      arg.toString();
    }
    

    生成的代码如下:

    public void testLombokGenerated(Object arg) {
      if (arg == null) {
        throw new NullPointerException("arg is marked @NonNull but is null");
      }
      arg.toString();
    }
    

    这个注解还可以用在类实例的成员变量上,所有的赋值操作会自动进行空值检测。

    编程规范
    通过遵守某些编程规范,也可以从一定程度上减少空指针异常的发生。

    使用那些已经对 null 值做过判断的方法,如 String#equals、String#valueOf、以及三方库中用来判断字符串和集合是否为空的函数:

    if (str != null && str.equals("text")) {}
    if ("text".equals(str)) {}
    
    if (obj != null) { obj.toString(); }
    String.valueOf(obj); // "null"
    
    // from spring-core
    StringUtils.isEmpty(str);
    CollectionUtils.isEmpty(col);
    // from guava
    Strings.isNullOrEmpty(str);
    // from commons-collections4
    CollectionUtils.isEmpty(col);
    

    如果函数的某个参数可以接收 null 值,考虑改写成两个函数,使用不同的函数签名,这样就可以强制要求每个参数都不为空了:

    public void methodA(Object arg1) {
      methodB(arg1, new Object[0]);
    }
    
    public void methodB(Object arg1, Object[] arg2) {
      for (Object obj : arg2) {} // no null check
    }
    

    如果函数的返回值是集合类型,当结果为空时,不要返回 null 值,而是返回一个空的集合;如果返回值类型是对象,则可以选择抛出异常。Spring JdbcTemplate 正是使用了这种处理方式:
    // 当查询结果为空时,返回 new ArrayList<>()

    jdbcTemplate.queryForList("SELECT * FROM person");
    

    // 若找不到该条记录,则抛出

    EmptyResultDataAccessException
    jdbcTemplate.queryForObject("SELECT age FROM person WHERE id = 1", Integer.class);
    

    // 支持泛型集合

    public <T> List<T> testReturnCollection() {
      return Collections.emptyList();
    }
    

    静态代码分析
    Java 语言有许多静态代码分析工具,如 Eclipse IDE、SpotBugs、Checker Framework 等,它们可以帮助程序员检测出编译期的错误。结合 @Nullable 和 @Nonnull 等注解,我们就可以在程序运行之前发现可能抛出空指针异常的代码。

    但是,空值检测注解还没有得到标准化。虽然 2006 年 9 月社区提出了 JSR 305 规范,但它长期处于搁置状态。很多第三方库提供了类似的注解,且得到了不同工具的支持,其中使用较多的有:

    javax.annotation.Nonnull:由 JSR 305 提出,其参考实现为 com.google.code.findbugs.jsr305;
    org.eclipse.jdt.annotation.NonNull:Eclipse IDE 原生支持的空值检测注解;
    edu.umd.cs.findbugs.annotations.NonNull:SpotBugs 使用的注解,基于 findbugs.jsr305;
    org.springframework.lang.NonNull:Spring Framework 5.0 开始提供;
    org.checkerframework.checker.nullness.qual.NonNull:Checker Framework 使用;
    android.support.annotation.NonNull:集成在安卓开发工具中;
    我建议使用一种跨 IDE 的解决方案,如 SpotBugs 或 Checker Framework,它们都能和 Maven 结合得很好。

    SpotBugs 与 @NonNull、@CheckForNull
    SpotBugs 是 FindBugs 的后继者。通过在方法的参数和返回值上添加 @NonNull 和 @CheckForNull 注解,SpotBugs 可以帮助我们进行编译期的空值检测。需要注意的是,SpotBugs 不支持 @Nullable 注解,必须用 @CheckForNull 代替。如官方文档中所说,仅当需要覆盖 @ParametersAreNonnullByDefault 时才会用到 @Nullable。

    官方文档 中说明了如何将 SpotBugs 应用到 Maven 和 Eclipse 中去。我们还需要将 spotbugs-annotations 加入到项目依赖中,以便使用对应的注解。

    <dependency>
        <groupId>com.github.spotbugs</groupId>
        <artifactId>spotbugs-annotations</artifactId>
        <version>3.1.7</version>
    </dependency>
    

    以下是对不同使用场景的说明:

    @NonNull
    private Object returnNonNull() {
      // 错误:returnNonNull() 可能返回空值,但其已声明为 @Nonnull
      return null;
    }
    
    @CheckForNull
    private Object returnNullable() {
      return null;
    }
    
    public void testReturnNullable() {
      Object obj = returnNullable();
      // 错误:方法的返回值可能为空
      System.out.println(obj.toString());
    }
    
    private void argumentNonNull(@NonNull Object arg) {
      System.out.println(arg.toString());
    }
    
    public void testArgumentNonNull() {
      // 错误:不能将 null 传递给非空参数
      argumentNonNull(null);
    }
    
    public void testNullableArgument(@CheckForNull Object arg) {
      // 错误:参数可能为空
      System.out.println(arg.toString());
    }
    

    对于 Eclipse 用户,还可以使用 IDE 内置的空值检测工具,只需将默认的注解 org.eclipse.jdt.annotation.Nullable 替换为 SpotBugs 的注解即可:

    Eclipse null analysis

    Checker Framework 与 @NonNull、@Nullable
    Checker Framework 能够作为 javac 编译器的插件运行,对代码中的数据类型进行检测,预防各类问题。我们可以参照 官方文档,将 Checker Framework 与 maven-compiler-plugin 结合,之后每次执行 mvn compile 时就会进行检查。Checker Framework 的空值检测程序支持几乎所有的注解,包括 JSR 305、Eclipse、甚至 lombok.NonNull。

    import org.checkerframework.checker.nullness.qual.Nullable;
    
    @Nullable
    private Object returnNullable() {
      return null;
    }
    
    public void testReturnNullable() {
      Object obj = returnNullable();
      // 错误:obj 可能为空
      System.out.println(obj.toString());
    }
    

    Checker Framework 默认会将 @NonNull 应用到所有的函数参数和返回值上,因此,即使不添加这个注解,以下程序也是无法编译通过的:

    private Object returnNonNull() {
      // 错误:方法声明为 @NonNull,但返回的是 null。
      return null;
    }
    
    private void argumentNonNull(Object arg) {
      System.out.println(arg.toString());
    }
    
    public void testArgumentNonNull() {
      // 错误:参数声明为 @NonNull,但传入的是 null。
      argumentNonNull(null);
    }
    

    Checker Framework 对使用 Spring Framework 5.0 以上的用户非常有用,因为 Spring 提供了内置的空值检测注解,且能够被 Checker Framework 支持。一方面我们无需再引入额外的 Jar 包,更重要的是 Spring Framework 代码本身就使用了这些注解,这样我们在调用它的 API 时就能有效地处理空值了。举例来说,StringUtils 类里可以传入空值的函数、以及会返回空值的函数都添加了 @Nullable 注解,而未添加的方法则继承了整个框架的 @NonNull 注解,因此,下列代码中的空指针异常就可以被 Checker Framework 检测到了:

    // 这是 spring-core 中定义的类和方法
    public abstract class StringUtils {
      // str 参数继承了全局的 @NonNull 注解
      public static String capitalize(String str) {}
    
      @Nullable
      public static String getFilename(@Nullable String path) {}
    }
    
    // 错误:参数声明为 @NonNull,但传入的是 null。
    StringUtils.capitalize(null);
    
    String filename = StringUtils.getFilename("/path/to/file");
    // 错误:filename 可能为空。
    System.out.println(filename.length());
    

    Optional 类型
    Java 8 引入了 Optional 类型,我们可以用它来对函数的返回值进行包装。这种方式的优点是可以明确定义该方法是有可能返回空值的,因此调用方必须做好相应处理,这样也就不会引发空指针异常。但是,也不可避免地需要编写更多代码,而且会产生很多垃圾对象,增加 GC 的压力,因此在使用时需要酌情考虑。

    Optional<String> opt;
    
    // 创建
    opt = Optional.empty();
    opt = Optional.of("text");
    opt = Optional.ofNullable(null);
    
    // 判断并读取
    if (opt.isPresent()) {
      opt.get();
    }
    
    // 默认值
    opt.orElse("default");
    opt.orElseGet(() -> "default");
    opt.orElseThrow(() -> new NullPointerException());
    
    // 相关操作
    opt.ifPresent(value -> {
      System.out.println(value);
    });
    opt.filter(value -> value.length() > 5);
    opt.map(value -> value.trim());
    opt.flatMap(value -> {
      String trimmed = value.trim();
      return trimmed.isEmpty() ? Optional.empty() : Optional.of(trimmed);
    });
    

    方法的链式调用很容易引发空指针异常,但如果返回值都用 Optional 包装起来,就可以用 flatMap 方法来实现安全的链式调用了:

    String zipCode = getUser()
        .flatMap(User::getAddress)
        .flatMap(Address::getZipCode)
        .orElse("");
    

    Java 8 Stream API 同样使用了 Optional 作为返回类型:

    stringList.stream().findFirst().orElse("default");
    stringList.stream()
        .max(Comparator.naturalOrder())
        .ifPresent(System.out::println);
    

    此外,Java 8 还针对基础类型提供了单独的 Optional 类,如 OptionalInt、OptionalDouble 等,在性能要求比较高的场景下很适用。

    其它 JVM 语言中的空指针异常
    Scala 语言中的 Option 类可以对标 Java 8 的 Optional。它有两个子类型,Some 表示有值,None 表示空。

    val opt: Option[String] = Some("text")
    opt.getOrElse("default")
    

    除了使用 Option#isEmpty 判断,还可以使用 Scala 的模式匹配:

    opt match {
      case Some(text) => println(text)
      case None => println("default")
    }
    

    Scala 的集合处理函数库非常强大,Option 则可直接作为集合进行操作,如 filer、map、以及列表解析(for-comprehension):

    opt.map(_.trim).filter(_.length > 0).map(_.toUpperCase).getOrElse("DEFAULT")
    val upper = for {
      text <- opt
      trimmed <- Some(text.trim())
      upper <- Some(trimmed) if trimmed.length > 0
    } yield upper
    upper.getOrElse("DEFAULT")
    

    Kotlin 使用了另一种方式,用户在定义变量时就需要明确区分 可空和不可空类型。当可空类型被使用时,就必须进行空值检测。

    var a: String = "text"
    a = null // 错误:无法将 null 赋值给非空 String 类型。
    
    val b: String? = "text"
    // 错误:操作可空类型时必须使用安全操作符(?.)或强制忽略(!!.)。
    println(b.length)
    
    val l: Int? = b?.length // 安全操作
    b!!.length // 强制忽略,可能引发空值异常
    

    Kotlin 的特性之一是与 Java 的可互操作性,但 Kotlin 编译器无法知晓 Java 类型是否为空,这就需要在 Java 代码中使用注解了,而 Kotlin 支持的 注解 也非常广泛。Spring Framework 5.0 起原生支持 Kotlin,其空值检测也是通过注解进行的,使得 Kotlin 可以安全地调用 Spring Framework 的所有 API。

    展开全文
  • Java 中任何对象都有可能为空,当我们调用空对象的方法时就会抛出NullPointerException空指针异常,这一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常,使得我们的代码更为健壮。本文将列举...

    Java 中任何对象都有可能为空,当我们调用空对象的方法时就会抛出 NullPointerException 空指针异常,这是一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常,使得我们的代码更为健壮。本文将列举这些解决方案,包括传统的空值检测、编程规范、以及使用现代 Java 语言引入的各类工具来作为辅助。

    运行时检测

    最显而易见的方法就是使用 if (obj == null) 来对所有需要用到的对象来进行检测,包括函数参数、返回值、以及类实例的成员变量。当你检测到 null 值时,可以选择抛出更具针对性的异常类型,如 IllegalArgumentException,并添加消息内容。我们可以使用一些库函数来简化代码,如 Java 7 开始提供的 Objects#requireNonNull 方法:

    public void testObjects(Object arg) {
      Object checked = Objects.requireNonNull(arg, "arg must not be null");
      checked.toString();
    }
    

     

    Guava 的 Preconditions 类中也提供了一系列用于检测参数合法性的工具函数,其中就包含空值检测:

    public void testGuava(Object arg) {
      Object checked = Preconditions.checkNotNull(arg, "%s must not be null", "arg");
      checked.toString();
    }
    

     

    我们还可以使用 Lombok 来生成空值检测代码,并抛出带有提示信息的空指针异常:

    public void testLombok(@NonNull Object arg) {
      arg.toString();
    }
    

     

    生成的代码如下:

    public void testLombokGenerated(Object arg) {
      if (arg == null) {
        throw new NullPointerException("arg is marked @NonNull but is null");
      }
      arg.toString();
    }
    

     

    这个注解还可以用在类实例的成员变量上,所有的赋值操作会自动进行空值检测。

    编程规范

    通过遵守某些编程规范,也可以从一定程度上减少空指针异常的发生。

    • 使用那些已经对 null 值做过判断的方法,如 String#equalsString#valueOf、以及三方库中用来判断字符串和集合是否为空的函数:
    if (str != null && str.equals("text")) {}
    if ("text".equals(str)) {}
    
    if (obj != null) { obj.toString(); }
    String.valueOf(obj); // "null"
    
    // from spring-core
    StringUtils.isEmpty(str);
    CollectionUtils.isEmpty(col);
    // from guava
    Strings.isNullOrEmpty(str);
    // from commons-collections4
    CollectionUtils.isEmpty(col);
    
    
    • 如果函数的某个参数可以接收 null 值,考虑改写成两个函数,使用不同的函数签名,这样就可以强制要求每个参数都不为空了:
    public void methodA(Object arg1) {
      methodB(arg1, new Object[0]);
    }
    
    public void methodB(Object arg1, Object[] arg2) {
      for (Object obj : arg2) {} // no null check
    }
    
    
    • 如果函数的返回值是集合类型,当结果为空时,不要返回 null 值,而是返回一个空的集合;如果返回值类型是对象,则可以选择抛出异常。Spring JdbcTemplate 正是使用了这种处理方式:
    // 当查询结果为空时,返回 new ArrayList<>()
    jdbcTemplate.queryForList("SELECT * FROM person");
    
    // 若找不到该条记录,则抛出 EmptyResultDataAccessException
    jdbcTemplate.queryForObject("SELECT age FROM person WHERE id = 1", Integer.class);
    
    // 支持泛型集合
    public <T> List<T> testReturnCollection() {
      return Collections.emptyList();
    }
    

     

    静态代码分析

    Java 语言有许多静态代码分析工具,如 Eclipse IDE、SpotBugs、Checker Framework 等,它们可以帮助程序员检测出编译期的错误。结合 @Nullable 和 @Nonnull 等注解,我们就可以在程序运行之前发现可能抛出空指针异常的代码。

    但是,空值检测注解还没有得到标准化。虽然 2006 年 9 月社区提出了 JSR 305 规范,但它长期处于搁置状态。很多第三方库提供了类似的注解,且得到了不同工具的支持,其中使用较多的有:

    • javax.annotation.Nonnull:由 JSR 305 提出,其参考实现为 com.google.code.findbugs.jsr305
    • org.eclipse.jdt.annotation.NonNull:Eclipse IDE 原生支持的空值检测注解;
    • edu.umd.cs.findbugs.annotations.NonNull:SpotBugs 使用的注解,基于 findbugs.jsr305
    • org.springframework.lang.NonNull:Spring Framework 5.0 开始提供;
    • org.checkerframework.checker.nullness.qual.NonNull:Checker Framework 使用;
    • android.support.annotation.NonNull:集成在安卓开发工具中;

    我建议使用一种跨 IDE 的解决方案,如 SpotBugs 或 Checker Framework,它们都能和 Maven 结合得很好。

    SpotBugs 与 @NonNull@CheckForNull

    SpotBugs 是 FindBugs 的后继者。通过在方法的参数和返回值上添加 @NonNull 和 @CheckForNull 注解,SpotBugs 可以帮助我们进行编译期的空值检测。需要注意的是,SpotBugs 不支持 @Nullable 注解,必须用 @CheckForNull 代替。如官方文档中所说,仅当需要覆盖 @ParametersAreNonnullByDefault 时才会用到 @Nullable

    官方文档 中说明了如何将 SpotBugs 应用到 Maven 和 Eclipse 中去。我们还需要将 spotbugs-annotations 加入到项目依赖中,以便使用对应的注解。

    <dependency>
        <groupId>com.github.spotbugs</groupId>
        <artifactId>spotbugs-annotations</artifactId>
        <version>3.1.7</version>
    </dependency>
    

    以下是对不同使用场景的说明:

    @NonNull
    private Object returnNonNull() {
      // 错误:returnNonNull() 可能返回空值,但其已声明为 @Nonnull
      return null;
    }
    
    @CheckForNull
    private Object returnNullable() {
      return null;
    }
    
    public void testReturnNullable() {
      Object obj = returnNullable();
      // 错误:方法的返回值可能为空
      System.out.println(obj.toString());
    }
    
    private void argumentNonNull(@NonNull Object arg) {
      System.out.println(arg.toString());
    }
    
    public void testArgumentNonNull() {
      // 错误:不能将 null 传递给非空参数
      argumentNonNull(null);
    }
    
    public void testNullableArgument(@CheckForNull Object arg) {
      // 错误:参数可能为空
      System.out.println(arg.toString());
    }
    
    

    对于 Eclipse 用户,还可以使用 IDE 内置的空值检测工具,只需将默认的注解 org.eclipse.jdt.annotation.Nullable 替换为 SpotBugs 的注解即可:

    Eclipse null analysis

    Checker Framework 与 @NonNull@Nullable

    Checker Framework 能够作为 javac 编译器的插件运行,对代码中的数据类型进行检测,预防各类问题。我们可以参照 官方文档,将 Checker Framework 与 maven-compiler-plugin 结合,之后每次执行 mvn compile 时就会进行检查。Checker Framework 的空值检测程序支持几乎所有的注解,包括 JSR 305、Eclipse、甚至 lombok.NonNull

    import org.checkerframework.checker.nullness.qual.Nullable;
    
    @Nullable
    private Object returnNullable() {
      return null;
    }
    
    public void testReturnNullable() {
      Object obj = returnNullable();
      // 错误:obj 可能为空
      System.out.println(obj.toString());
    }
    
    

    Checker Framework 默认会将 @NonNull 应用到所有的函数参数和返回值上,因此,即使不添加这个注解,以下程序也是无法编译通过的:

    private Object returnNonNull() {
      // 错误:方法声明为 @NonNull,但返回的是 null。
      return null;
    }
    
    private void argumentNonNull(Object arg) {
      System.out.println(arg.toString());
    }
    
    public void testArgumentNonNull() {
      // 错误:参数声明为 @NonNull,但传入的是 null。
      argumentNonNull(null);
    }
    

     

    Checker Framework 对使用 Spring Framework 5.0 以上的用户非常有用,因为 Spring 提供了内置的空值检测注解,且能够被 Checker Framework 支持。一方面我们无需再引入额外的 Jar 包,更重要的是 Spring Framework 代码本身就使用了这些注解,这样我们在调用它的 API 时就能有效地处理空值了。举例来说,StringUtils 类里可以传入空值的函数、以及会返回空值的函数都添加了 @Nullable 注解,而未添加的方法则继承了整个框架的 @NonNull 注解,因此,下列代码中的空指针异常就可以被 Checker Framework 检测到了:

    // 这是 spring-core 中定义的类和方法
    public abstract class StringUtils {
      // str 参数继承了全局的 @NonNull 注解
      public static String capitalize(String str) {}
    
      @Nullable
      public static String getFilename(@Nullable String path) {}
    }
    
    // 错误:参数声明为 @NonNull,但传入的是 null。
    StringUtils.capitalize(null);
    
    String filename = StringUtils.getFilename("/path/to/file");
    // 错误:filename 可能为空。
    System.out.println(filename.length());
    
    

    Optional 类型

    Java 8 引入了 Optional<T> 类型,我们可以用它来对函数的返回值进行包装。这种方式的优点是可以明确定义该方法是有可能返回空值的,因此调用方必须做好相应处理,这样也就不会引发空指针异常。但是,也不可避免地需要编写更多代码,而且会产生很多垃圾对象,增加 GC 的压力,因此在使用时需要酌情考虑。

    Optional<String> opt;
    
    // 创建
    opt = Optional.empty();
    opt = Optional.of("text");
    opt = Optional.ofNullable(null);
    
    // 判断并读取
    if (opt.isPresent()) {
      opt.get();
    }
    
    // 默认值
    opt.orElse("default");
    opt.orElseGet(() -> "default");
    opt.orElseThrow(() -> new NullPointerException());
    
    // 相关操作
    opt.ifPresent(value -> {
      System.out.println(value);
    });
    opt.filter(value -> value.length() > 5);
    opt.map(value -> value.trim());
    opt.flatMap(value -> {
      String trimmed = value.trim();
      return trimmed.isEmpty() ? Optional.empty() : Optional.of(trimmed);
    });
    
    

    方法的链式调用很容易引发空指针异常,但如果返回值都用 Optional 包装起来,就可以用 flatMap 方法来实现安全的链式调用了:

    String zipCode = getUser()
        .flatMap(User::getAddress)
        .flatMap(Address::getZipCode)
        .orElse("");
    
    

    Java 8 Stream API 同样使用了 Optional 作为返回类型:

    stringList.stream().findFirst().orElse("default");
    stringList.stream()
        .max(Comparator.naturalOrder())
        .ifPresent(System.out::println);
    
    

    此外,Java 8 还针对基础类型提供了单独的 Optional 类,如 OptionalIntOptionalDouble 等,在性能要求比较高的场景下很适用。

    其它 JVM 语言中的空指针异常

    Scala 语言中的 Option 类可以对标 Java 8 的 Optional。它有两个子类型,Some 表示有值,None 表示空。

    val opt: Option[String] = Some("text")
    opt.getOrElse("default")
    

    除了使用 Option#isEmpty 判断,还可以使用 Scala 的模式匹配:

    opt match {
      case Some(text) => println(text)
      case None => println("default")
    }
    

    Scala 的集合处理函数库非常强大,Option 则可直接作为集合进行操作,如 filermap、以及列表解析(for-comprehension):

    opt.map(_.trim).filter(_.length > 0).map(_.toUpperCase).getOrElse("DEFAULT")
    val upper = for {
      text <- opt
      trimmed <- Some(text.trim())
      upper <- Some(trimmed) if trimmed.length > 0
    } yield upper
    upper.getOrElse("DEFAULT")
    

    Kotlin 使用了另一种方式,用户在定义变量时就需要明确区分 可空和不可空类型。当可空类型被使用时,就必须进行空值检测。

    var a: String = "text"
    a = null // 错误:无法将 null 赋值给非空 String 类型。
    
    val b: String? = "text"
    // 错误:操作可空类型时必须使用安全操作符(?.)或强制忽略(!!.)。
    println(b.length)
    
    val l: Int? = b?.length // 安全操作
    b!!.length // 强制忽略,可能引发空值异常
    

    Kotlin 的特性之一是与 Java 的可互操作性,但 Kotlin 编译器无法知晓 Java 类型是否为空,这就需要在 Java 代码中使用注解了,而 Kotlin 支持的 注解 也非常广泛。Spring Framework 5.0 起原生支持 Kotlin,其空值检测也是通过注解进行的,使得 Kotlin 可以安全地调用 Spring Framework 的所有 API。

    结论

    在以上这些方案中,我比较推荐使用注解来预防空指针异常,因为这种方式十分有效,对代码的侵入性也较小。所有的公共 API 都应该使用 @Nullable 和 @NonNull 进行注解,这样就能强制调用方对空指针异常进行预防,让我们的程序更为健壮。

    参考资料

    展开全文
  • Java的null 表示它没有引用指向或没有指针,这时操作该变量必会引发空指针异常,即NullPointerException。当线上环境发生该异常时,就会收到大量投诉!如何才能避免呢? 毕竟NPE虽烦人但易定位,麻烦的要弄清楚...
  • 空指针一种不受编程语言检查的运行时异常,只能由程序员主动通过逻辑判断来避免,但即使最出色的程序员,也不可能将所有潜在的空指针异常全部考虑到。 我们来看一段非常简单的Java代码: public void doStudy...
  • 异常(Exception): 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络链接失败、非法参数等 异常指程序运行期间,它影响了正常的...NullPointerException:空指针异常 ArithmeticException:算数异
  • 文章目录8.1 定义返回的统一 JSON 结构8.2 处理系统异常8.2.1 处理参数缺失异常8.2.2 处理空指针异常8.2.3 一劳永逸?8.3 拦截自定义异常8.3.1 定义异常信息8.3.2 拦截自定义异常 在项目开发过程中,不管对底层...
  • error```类:描述典型的逻辑错误,这类错误可以通过编程修复```runtime_error```类:这类异常是无法避免的问题bad_alloc异常类:也从exception类公有派生而来,处理new分配内存失败的错误示例和空指针方案兼容的方法...
  • 可以参考一些参数为指针的API,比如strncpy,当对其强制传入一个空指针时,程序并不会悄无声息,而是会抛出异常。 因为这样的参数已经违反了接口的规约,函数内部不知道该如何处理,只能抛出异常让程序崩溃。 ...
  • java8-optional

    2020-10-24 11:46:43
    避免空指针异常(NullPointerException) 经常遇到的异常就是空指针异常,具体表现 对象实例.调用方法,提示对象实例一个null,抛出异常。 使用 Optional 修饰对象,避免出现空指针异常 优化判空校
  • 解答:java中的空指针最常见的错误之一,要尽量避免空指针异常,首先在使用对象前,先对其进行初始化。 另外,要完全避免空指针,最好做到以下几点: 1:对于所有 public 方法传入的对象参数进行 null 值检查 ...
  • Java8新特性

    2020-01-06 19:32:43
    空指针异常是我们日常项目中经常出现的问题,一般在操作前必须进行判空处理,Java8中引入了 Optional 类可以帮助我们避免显式判空处理。 Optional.of(T value),该方法通过一个非 null 的 value 来构造一个 ...
  • 一、不能使用NUll调用方法,否则会空指针异常二、参数的传递 如果参数是基本数据类型,称为值传递,传递过去的是值的拷贝,无论怎么拷贝,原值都不会改变。如果参数是引用类型,对象作为参数传递时,是把对象在内存...
  • Java8新特性 Optional类

    2021-04-03 00:45:18
    这篇文章我们来学习Java8如何通过Optional类来避免空指针异常的。 先来看一下不使用Optional类时,我们为了防止NullPointerException会怎么处理。 public String getParentName(Person son) { if (son != null) {...
  • 如果你在使用MCU进行开发,在项目中后期随着...在空指针读写、内存泄漏、堆栈溢出、参数错误等情况都可能使MCU运行死机,有些问题非常难以复现的,为了复现发生异常的场景,往往需要打很多log进行辅助分析,但一...
  • int 初始化 0; 这如果代码这样,就会...但是在使用Integer的时候一定要注意判空,否则如果Integer类型的参数在未赋值的情况下,与数字进行比较就会出现空指针异常 在设计过程中一定要细心,才能避免这...
  • test1会直接报空指针异常,你想想看,null.equals看不起来不就怪怪的吗?空指针怎么可能有方法呢吧, **拓展:**我们一般在企业开发中都会将已知的字面量放在equals,未知的参数放在equals后面,这样可以避免空...
  • 10. Java8-Optional 简介

    万次阅读 2019-08-27 16:12:15
    Optional 的目的是避免空指针异常, 但是笔者并没有如何才能用好它 1. 常用API API 签名 方法描述 public static Optional of(T value) 创建实例, 参数不能为null public static Optional...
  • 什么时候用!=null?

    2021-04-24 12:24:24
    =null,为了避免程序返回空指针异常,但是这样的代码会显得丑陋繁冗! 1.使用null的意义: 往往我们判断某个返回是不是为空的时候,应该思考两种情况: (1):第一种 null一个有效有意义的返回值 (2):第二种 ...
  • NullPointerException可谓随时随处可见,为了避免空指针异常,我们常常需要进行一些防御式的检查,例如前端传来的可变参数、有的参数可传可不穿、所以需要判断是否为空、然后再加入查询条件; Optional类能让我们...
  • 可空性(避免空指针异常) /* *这个函数的参数代表传入一个String类型变量的实例,这代表它不可以为空 */ fun a(str:String){ println(str) } //这样调用a()会在编译期就显示错误,因为a()的参数不...
  • JAVA8新特性之Optional<T> 类

    千次阅读 2020-07-26 22:49:39
    并且可以避免空指针异常 2常用API(带*号表示常用) Optional.of(T t):创建一个 Optional 实例 @Test public void test01(){ // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerE
  • 一、Optional类:为了在程序中避免出现空指针异常而创建的。 常用的方法: ofNullable(T t) orElse(T t) //orElse(T t1):如果单前的Optional内部封装的t是非空的,则返回内部的t. //如果内部的t是空的,则返回...
  • Object类和Objects类的常用方法

    千次阅读 2018-08-20 20:34:00
    Objects常用方法:equals, 此方法的作用同Object类的equals()方法的作用一样,只是此方法可以避免空指针异常”。此方法内部也基于参数对象的equals()方法的。 Object和Objects的equals方...
  • Java8 Optional类

    2017-07-16 21:18:29
    Optional 类(java.util.Optional) 一个容器...可以避免空指针异常。常用方法如下:Optional.of(T t) : 创建一个非null的值创建一个Optional 实例,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullP
  • 并且可以避免空指针异常。  也就是说调用一个方法得到了一个返回值却不能直接将返回值作为参数去调用别的方法,我们首先要判断这个返回值是否为空,只有在非空的情况下才能将其作为其它方法...
  • 6.常量字符串一般放前面比较避免空指针异常 7.remove删除的漏洞 8.后续继续写标记备注 9.将引用数据类型提到外面可以提高访问权限 1.江湖规矩将封装好的对象放domain 2.自己写的类也可以数组类型存储的...

空空如也

空空如也

1 2 3 4 5
收藏数 90
精华内容 36
关键字:

避免参数是空指针异常