前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Java和 Kotlin中的常见NPE

Java和 Kotlin中的常见NPE

原创
作者头像
Nimyears
发布2024-10-28 11:35:54
发布2024-10-28 11:35:54
10700
代码可运行
举报
运行总次数:0
代码可运行

写一篇关于NPL的技术文章为了帮助我总结,避免了大量浪费时间处理这种的常见问题。最近我做了很多项目经常会碰到的“噩梦”之一就是NullPointerException(NPE),因为Java允许变量为null,而在调用对象方法或属性时未做null检查,就会抛出NPE。这种情况在Kotlin里几乎不再是问题,因为Kotlin从语言层面引入了空安全支持,彻底减少了NPE的出现概率。下面我们看看两种语言是如何应对NPE的,通过示例展示常见的编程场景。

一、Kotlin 的可空类型和编译时检查

几乎所有对象都可以为null,意味着我在调用任何方法时,都需要小心检查对象是否为空。例如,以下代码会抛出NPE,因为 a可能为null:

代码语言:java
复制
int getStringLength(String a) {
    return a.length(); // 如果a是null,就会抛出NPE
}

方案一:null检查

可以在调用方法前手动检查null值避免NPE:

代码语言:java
复制
int getStringLength(String a) {
    return a != null ? a.length() : 0;
}

方案二:Optional

Java 8引入了Optional类,提供一种更优雅的null处理方式。下面的代码使用了Optional类:

代码语言:java
复制
Optional<String> optionalString = Optional.ofNullable(a);
int length = optionalString.map(String::length).orElse(0);

二、Kotlin的空安全设计,编译时检查避免NPE

所有类型默认都是不可空的,除非特意用?标记它是可空的。这样,Kotlin可以在编译时帮助我们捕捉潜在的NPE,而不是等到代码运行时才发现。比如:

代码语言:kotlin
复制
fun getStringLength(a: String): Int = a.length // 编译时检查,a不能为null

如果希望变量可以为空,那么可以将类型声明为String?(带?表示可空),表示它可以保存null值:

代码语言:javascript
代码运行次数:0
复制
fun getStringLength(a: String?): Int = a?.length ?: 0

在上面的代码中,a?.length是一种安全调用写法(?.),它的作用是如果a为空就返回null,而不是抛出异常。?:称为Elvis操作符,它为null的情况指定一个默认值。这样代码是很安全又简洁,非常适合日常开发中使用。

三、Elvis 操作符:提供默认值

Elvis操作符(?:)可以在变量为null时提供默认值。举例子,在找一个订单,但找不到时希望返回默认订单对象,就可以这么写:

代码语言:javascript
代码运行次数:0
复制
val order = findOrder() ?: Order(Customer("默认客户"))

这段代码的意思是:如果findOrder()返回的订单是null,就用一个默认的订单代替。相比Java中的if-else空检查,这样的写法很简单、易读。

四、Kotlin调用Java代码:平台类型的风险

Kotlin 和Java 可以互相调用,但Java代码没有空安全检查,会让Kotlin这些类型为“平台类型”。平台类型没有空安全约束,可当作可空类型也可当作非空类型,这意味着Kotlin不会强制检查null,但使用Java代码时一定要小心,确保不会触发NPE。例如:

代码语言:kotlin
复制
val customer = javaMethodThatReturnsNullableCustomer()
println(customer?.name ?: "未找到客户")

这种情况下,Kotlin调用Java方法时不会做null检查,需要在使用平台类型变量前加上安全调用(?.),避免意外的NPE。

五、类型转换更安全

在Java中,类型转换通常借助instanceof判断变量类型,确保转换安全。Kotlin则提供了as?操作符,用于安全类型转换。如果转换失败,它会返回null而不是抛异常。这种设计避免了强制类型转换带来的风险:

代码语言:kotlin
复制
fun getStringLength(y: Any): Int {
    val x: String? = y as? String
    return x?.length ?: -1
}

这段代码意思是:尝试将y转换为String,如果转换失败就返回null。配合?.使用,为了很轻松编写安全代码。

六、Kotlin 的优势总结

综上总结,Kotlin通过编译时的空检查、可空类型支持和安全调用等功能,几乎不会发生了NPE的发生。Java虽然引入了Optional类解决空值问题,但整体语法很繁琐。而Kotlin将空安全直接融入类型系统,不需要额外操作即可避免NPE。

在日常开发中,Kotlin让代码更流畅、更安全,从Java转向Kotlin的开发者可以充分体验到空安全特性的便捷,减少了处理空值所带来的麻烦。这些空安全特性不仅让开发更高效,也让代码更健壮

谢谢大家阅读)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Kotlin 的可空类型和编译时检查
    • 方案一:null检查
    • 方案二:Optional
  • 二、Kotlin的空安全设计,编译时检查避免NPE
  • 三、Elvis 操作符:提供默认值
  • 四、Kotlin调用Java代码:平台类型的风险
  • 五、类型转换更安全
  • 六、Kotlin 的优势总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档