ava 语言在处理 null
引用方面一直让开发者头疼。尽管许多开发者在编码时假设某些变量永远不会是 null
,但在现有的 Java 语法中却无法明确表达这一意图,导致潜在的空指针异常(NullPointerException)无处不在。
为了解决这一痛点,Java 正在引入一项新的预览特性——Null-Restricted 和 Nullable 类型。[1]这项特性旨在让开发者能够在类型定义中明确指出该类型是否允许 null
值,从而在编译时和运行时提供更强的类型安全和检测机制。
例如下:
-
Foo!
是非空限制类型 - 这种类型的可接受值不包括null
。 -
Foo?
是可空类型 - 这种类型的可接受值明确包括null
。 -
Foo
未指定是否接受null
- 这种类型没有明确说明是否可以接受null
。
特性亮点
-
明确表达类型的空值限制:开发者可以使用
Foo!
表示不允许null
的类型,使用Foo?
表示允许null
的类型。而默认的Foo
类型仍不指定空值限制。 -
兼容现有代码:新特性可以逐步引入,保证与传统 Java 代码的兼容性。无需一次性重构所有代码,也不需要修改现有的标准库。
-
自动检测并警告潜在的空指针异常:类型转换时,Java 编译器会自动检查可能的
null
处理不当情况,并给出警告。例如,将Foo?
转换为Foo!
时,编译器会在运行时插入检测,防止null
引发异常。 -
字段和数组的严格初始化:对于声明为
null
限制的字段和数组,Java 要求在它们被读取前必须初始化,否则将抛出异常。例如,String![] labels
在初始化时必须为每个元素提供初始值。 -
灵活的 nullness 转换:类型之间可以进行似于自动装箱和拆箱机制。这使得在不同空值类型间的转换更加自然,但潜在的风险仍会在运行时被检测到。
展望未来
虽然这项特性目前只是预览版,但它为 Java 开发者提供了强大的工具来更好地控制空值处理。在未来,我们有望看到更多 API 采用这些新语法,甚至有可能出现让整个类或模块默认使用 null
限制的功能。
这对于开发者来说无疑是一个重大利好,将 Java 推向更健壮、更安全的编程语言迈出了一大步。
对比 TypeScript
在 TypeScript 中,!
和 ?
这两个符号有不同的含义,分别用于处理可选属性、非空断言。
1. !
非空断言
!
在 TypeScript 中被称为非空断言操作符。它告诉编译器,某个变量或属性在使用时一定不是 null
或 undefined
,即使编译器无法静态推断这一点。
示例:
let name: string | null = "Alice";
console.log(name!.toUpperCase()); // 非空断言,假定 name 不会为 null
在这个例子中,name!
表示我们确信 name
不是 null
。如果实际值是 null
,那么在运行时仍然可能会抛出错误,但编译器不会报错。
常见使用场景:
-
当你确定一个值在某些情况下不会为
null
或undefined
,但编译器无法推断时使用。 -
在处理 DOM 元素或第三方库数据时,常见于 TypeScript 项目中。
2. ?
可选属性/可选参数
?
在 TypeScript 中用于声明可选属性或可选参数。它表示该属性或参数可以不存在,或者它的值可以是 undefined
。
示例 1:可选属性
interface Person {
name: string;
age?: number; // 可选属性
}
const alice: Person = { name: "Alice" }; // 可以不提供 age 属性
使用 ?
标记的属性或参数是可选的,意味着可以不赋值或不传递。