牛蛙资源网 - 只为资源而生,分享永无止境
牛蛙资源网-只为资源而生,分享永无止境,牛蛙网

空指针异常主要原因以及解决方案是什么(空指针异常常用解决办法)

牛蛙小编 交流杂谈

数学中 *** 为空怎么表示,空指针异常主要原因以及解决方案

空指针异常产生的主要原因如下:

(1)当一个对象不存在时又调用其 *** 会产生异常obj.method() // obj对象不存在(2)当访问或修改一个对象不存在的字段时会产生异常obj.method() // method *** 不存在(3)字符串变量未初始化;(4)接口类型的对象没有用具体的类初始化,比如:List a;会报错List a = new ArrayList();则不会报错了当一个对象的值为空时,你没有判断为空的情况。你可以试着把下面的代码前加一行代码:if(rb!=null rb!="")改成:if(rb==null)if(rb!==nullrb!="") 或者if(().equals(rb))空指针的解决办法:重点关注报错发生的所在行,通过空指针异常产生的两条主要原因诊断具体的错误。同时为了避免空指针的发生,更好在做判断处理时将null或者空值放于设定的值之前。

另: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()}1234

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

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

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

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

生成的代码如下:

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

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

编程规范

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

使用那些已经对 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-coreStringUtils.isEmpty(str)CollectionUtils.isEmpty(col)// from guavaStrings.isNullOrEmpty(str)// from commons-collections4CollectionUtils.isEmpty(col)12345678910111213

如果函数的某个参数可以接收 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}1234567

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

// 当查询结果为空时,返回 new ArrayList()jdbcTemplate.queryForList("SELECT * FROM person")// 若找不到该条记录,则抛出 EmptyResultDataAccessExceptionjdbcTemplate.queryForObject("SELECT age FROM person WHERE id = 1", Integer.class)// 支持泛型 *** public List testReturnCollection() { return Collections.emptyList()}12345678910

静态代码分析

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

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

javax.annotation.Nonnull:由 *** R 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 加入到项目依赖中,以便使用对应的注解。

com.github.spotbugs spotbugs-annotations 3.1.712345

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

@NonNullprivate Object returnNonNull() { // 错误:returnNonNull() 可能返回空值,但其已声明为 @Nonnull return null}@CheckForNullprivate 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())}123456789101112131415161718192021222324252627282930

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

Checker Framework 与 @NonNull、@Nullable

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

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

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)}12345678910111213

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())123456789101112131415

Optional 类型

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

Optional 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)})123456789101112131415161718192021222324252627

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

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

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

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

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

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

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

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

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

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

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

opt.map(_.trim).filter(_.length > 0).map(_.toUpperCase).getOrElse("DEFAULT")val upper = for { text


    收藏永久发布页,不迷路
    关键词不能为空

免责声明:

本站提供的资源,都来自网络,版权争议与本站无关,所有内容及软件的文章仅限用于学习和研究目的。不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,我们不保证内容的长久可用性,通过使用本站内容随之而来的风险与本站无关,您必须在下载后的24个小时之内,从您的电脑/手机中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。侵删请致信E-mail: 1470282@qq.com

我来说两句
签到
交流杂谈 空指针异常主要原因以及解决方案是什么(空指针异常常用解决办法)
数学中 *** 为空怎么表示,空指针异常主要原因以及解决方案 空指针异常产生的主要原因如下:(1)当一个对象不存在时又调用其 *** 会产生异常obj.met...
扫描二维码阅读原文 扫描二维码阅读原文
牛蛙资源网 January, 01
生成社交图 ×