AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

新的 JEP 草案发布,将在 Java 中引入可选空值标记

Ben Evans

  • 2024-09-14
    北京
  • 本文字数:2027 字

    阅读完需:约 7 分钟

新的JEP草案发布,将在Java中引入可选空值标记

之前我们报道了 JSpecify 1.0.0 版本的发布。这个版本主要引入了类型使用注解,用于指示静态类型的空值状态。


与之相关的是,JEP 8303099 草案 最近已对外公布。这个 JEP 探讨了 Null-Restricted 和 Nullable 类型,旨在将可选的空值标记引入到 Java 中。


该提案的核心是在类型使用上引入明确的标记——不仅仅是注解,指明在特定使用场景中允许的值是否包括。需要注意的是,这个提案目前还处于初步开发阶段(例如,它尚未获得正式的 JEP 编号),因此其语法在未来有可能会发生变化。尽管如此,目前的提案借鉴了 Kotlin 的标记方式,因此,对于类型,有三种使用方式:


  • Foo! 表示 Null-Restricted——这种类型可接受的值不包括;

  • Foo? 表示 Nullable——这种类型可接受的值包括 ;

  • Foo 没有明确指定是否接受。


使用未加修饰的 Foo 作为默认选项,这样做是为了保持现有代码在编译时的语义不变。


目前,该提案要求对于每一个类型的使用都进行注解,即尚不支持将整个类或模块标记为 Null-Restricted(比如像 JSpecify 那样),尽管这个功能可能会在未来引入。


这个新特性引入了一种空值转换机制(类似扩展和拆箱转换)。例如,以下这些赋值是被允许的:


  • 将 Foo! 赋值给 Foo?;

  • 将 Foo! 赋值给 Foo;

  • 将 Foo? 赋值给 Foo;

  • 将 Foo 赋值给 Foo?。


这种属于约束放宽——例如,任何 Null-Restricted 的值都可以被放在 Nullable 的值中。


也有窄化空值的转换,例如:


  • 将 Foo? 赋值给 Foo!;

  • 将 Foo 赋值给 Foo!。


这些可能会导致运行时错误,例如尝试将 null 从一个 Foo? 赋值给 Foo!。通常的策略是将这些情况视为编译时警告(而不是错误),并引入运行时检查,如果检测到违反空值界限,就抛出 NullPointerException。


请注意,这些例子仅展示了一些基础情况,实际当中可能存在更为复杂的情形。例如,在处理泛型时,编译器可能会面临类型参数的空值属性与其声明的界限不匹配的情况。


引入空标记不仅增强了编译时的安全性,还支持逐步采用的策略——首先定义类型允许的空值,然后通过解决编译时警告来逐步优化代码。


InfoQ 采访了 Kevin Bourrillion(谷歌核心库团队创始人,现在是 Oracle Java 语言团队成员),深入了解该项目的更多细节。

InfoQ:你能介绍一下你在 Java 空值处理方面的专业背景和相关经验吗?

Bourrillion: 我与其他一些人共同创立了 JSpecify 小组,并一直是主要的“设计师”(这个角色可以被理解为在推动复杂设计决策过程中达成共识的人)。尽管现在我加入了 Oracle,仍然以相似的方式继续参与项目。

InfoQ:这个 JEP 与 JSpecify 的工作有哪些重叠的地方?

Bourrillion: 最终我们将拥有一个支持空值标记的 Java 版本。JSpecify 在精确定义注解语义的含义方面完成了艰巨的任务。这意味着无论项目选择怎样的升级时间表,都将处于一个非常有利的位置,能够从 JSpecify 的注解平滑迁移到语言级别的空值标记——实际上,这种迁移应该是高度自动化的。

InfoQ:JEP 8303099 草案和 Java 5 中添加泛型的方式似乎有一些相似之处。这么说对吗?都是一种编译时机制,大部分信息会在字节码级别被擦除,是这样吗?

Bourrillion: 是的。我们认为类型擦除和所谓的“堆污染”是不得已的妥协,但正是这种设计让特性更容易被广泛采用。这也正是为什么现在几乎看不到原始类型的原因(至少我希望如此!)。空值污染将是一个长期存在的问题,但这没关系!现在全部都是关于空值污染。


正如泛型类型信息一样,空值注解在运行时通过反射发挥作用,但不参与运行时类型检查。我很好奇是否会有人基于我们的注解开发一个注入空检查的字节码工具;我认为这可能会非常有用,但也可能存在不值得投入精力的情况;我们只能等待并观察市场和技术社区的反应。

InfoQ:空值限制也是 Project Valhalla 的一个重要话题,不是吗?你能分享一些这个 JEP 草案与 Valhalla 项目正在进行的工作之间的相互影响和互动吗?

Bourrillion: 这实际上是同一个问题;Valhalla 项目是在这个 JEP 草案的基础上进一步构建的。知道哪些值不能为空将有助于虚拟机优化这些间接调用。

InfoQ:从中期到长期来看,JSpecify 应该能够为 Java 语言级别的空值支持提供一个平滑的过渡路径。它已经能够与 Kotlin 的空值支持相协调。对于开发者采用 JSpecify,你有哪些建议?

Bourrillion: JSpecify 目前处于 1.0.0 版本,尽管注解的定义已经相当精确,但规范仍有可能会经历一些细微的调整。所以,如果你现在开始对你的代码库进行注解,你的代码不太可能突然无法编译,但在一些小的规范修订后,你可能需要在某些地方移除或增加一些 @Nullable 注解。


如果你发现将空值分析集成到现有的工具链中过于耗时,因为你需要清理所有的警告,那么采用@SuppressWarnings注解是完全可以接受的!虽然这可能看起来不够优雅,但你可以随着时间的推移逐步对它们进行清理。即使这可能需要很长时间,但关键在于新代码从现在开始就有了空值检查,而这才是最需要关注的部分。


InfoQ:感谢接受采访!


查看英文原文:

https://www.infoq.com/news/2024/08/null-restricted-java/

2024-09-14 00:0910799

评论

发布
暂无评论
发现更多内容

git fetch&pull讲解 | Git

Appleex

git

谈谈曾经做的一个测试报告平台(1)

MegaQi

Python 测试平台 10月月更

“程”风破浪的开发者 | 基建及团队建设的方法论

甜点cc

团队管理 学习方法 基建 “程”风破浪的开发者

liunx:进程概念

雪芙花

c c++ 10月月更

C++进阶之哈希(unordered_map/set的使用及其模拟)

雪芙花

c c++ 10月月更

趁年少,多读书

暮春零贰

读书笔记 10月月更

C++精通之路:红黑树的应用(模拟实现map/set)

雪芙花

c c++ 10月月更

如何提高Docker容器的安全性

乌龟哥哥

10月月更

【web 开发基础】PHP 快速入门(7)-PHP 运算符之比较运算符详解

迷彩

10月月更 PHP基础 比较运算符

docker数据卷使用

忙着长大#

,docker

[HCTF 2018]WarmUp题解(较为详细的)

w010w

Web CTF 每日一题 10月月更

消息推送渠道那么多,该怎么设计消息中心?

产品海豚湾

产品经理 产品设计 消息系统 产品架构 10月月更

golang中的字符串

六月的

golang 字符串

2022年中国数字疗法市场洞察

易观分析

医疗

微服务的常见架构方式

乌龟哥哥

10月月更

云计算商业周期超过其他产业,技术的天花板是商业机遇

B Impact

【愚公系列】2022年10月 Go教学课程 036-类型断言

愚公搬代码

10月月更

数据湖(八):Iceberg数据存储格式

Lansonli

数据湖 10月月更

中东地区被低估,沙特偏好企业服务和云,新加坡稳定,东南亚复杂|出海

B Impact

再聊加班的感受

李印

成长感悟

极客时间运维进阶训练营第一周作业

老曹

JS事件,你真的懂吗(捕获,冒泡)?

乌龟哥哥

10月月更

ubuntu使用apt-get安装docker

忙着长大#

Ubuntu20.04

Python运算符有哪些你清楚吗

芥末拌个饭吧

后端 python 3.5+ 10月月更

python有哪些格式化输出的方法

芥末拌个饭吧

后端 python 3.5+ 10月月更

HashMap 源码分析(五)

知识浅谈

HashMap底层原理 10月月更

阿里云无影向RPA开闸,金智维、影刀、弘玑已落地|生态商机

B Impact

一起学习 Go 语言设计模式之设计模式概述

宇宙之一粟

设计模式 Go 语言 10月月更

Web3.0杂谈-#008(55/100)

hackstoic

Web3.0

“程”风破浪的开发者 | 关于web3.0远离银手镯比什么都重要!

王中阳Go

区块链 NFT Web3.0 10月月更 “程”风破浪的开发者

新的JEP草案发布,将在Java中引入可选空值标记_大前端_InfoQ精选文章