Java 23 之前
让我们回顾一下这个 JEP 之前的世界。每当我们想要使用 switch 或 instanceof 时,我们都会受到很大限制。对于 switch,我们无法使用所有装箱类型。
无论何时你想写这段代码,
Double d = 20.0d; |
您将收到编译错误:
java: constant label of type double is not compatible with switch selector type java.lang.Double |
这是因为某些类型存在限制。在JLS中,您可以看到:
“Expression 称为选择器表达式。选择器表达式的类型必须是 char、byte、short、int 或引用类型,否则会发生编译时错误。”
从这句话中,我们可以了解到int类型可以在 switch 中使用。没错,你可以创建如下代码:
int v = 20; |
一切都会正常工作。正如您可能从我们的博客文章中知道或读到的那样,Java 21 中的 switch 进行了大量升级,您可以执行以下操作:
Integer v = 20; |
看起来不错吧?我们可以对原始 int 尝试类似的方法。
int v = 20; |
我们运行此代码,并收到编译错误:
java: unexpected type |
这是为什么呢?在 JEP-455 之前,Java 对 switch 模式的支持有限。
类似这样的切换模式对于记录模式来说是可能的。
record Value(int i){} |
正常工作。Instanceof 不适用于任何原始类型。
Java 23 之后 - 启用预览功能时
现在允许使用 Long、Float、Double 和 Boolean 进行切换。因此,我们的 Double 预览示例可以正常工作。
Instanceof 也改变了它们的行为。可以检查变量是否属于主要类型。
从现在开始,当我们运行如下代码时:
int i = 42; |
控制台上将显示“i is an instance of int”。太棒了!这段代码怎么样?
int i = 42; |
这很简单,对吧?我们什么也不会得到,因为int不是byte的实例。不幸的是,在这个例子中,我们将得到文本“i is an instance of byte?”
这是为什么?
一切都是因为转换。Java 的这个简单特性就是将一种原始数据类型的值赋给另一种类型。
你知道强制转换并不安全吗?让我们来看这个例子:
int i = 42; |
我们的 b 变量的值将是 42,对吗?现在怎么样?
int i = 128; |
你可能觉得这个问题有点可疑。你是对的。b 的值应该是-128。这是因为字节类型的范围是从 -128 到 127(含)。在这里,你可以了解有关整数类型和值的更多信息。
那么问题来了,如果值在转换后会发生变化,那么它是否是正确的类型?从 JEP 中我们得知答案是否定的。
这就是为什么 instanceof 现在不仅检查类型是否适合引用,而且还检查是否可以安全地转换原始值。
这会带来什么后果?
在 Java 23 之前,当您尝试如下代码时:
Integer i = 42; |
你收到一个错误:
error: incompatible types: Integer cannot be converted to Double |
但是对于原始类型,代码如下:
int i = 42; |
它工作得很好,因为每个 int 都可以毫无问题地转换为 double。当你想用更窄的类型尝试同样的情况时,你需要确保你的 switch 是详尽的。就像这样:
int i = 10_0000; |
如果您想知道将原始类型转换为其他类型是否安全,您可以查看JLS 中的转换上下文。
概括
Swtich模式在我们的日常工作中变得越来越有用。得益于 Project Amber,我们现在可以更轻松地使用原语,并且使用更少的冗长方法。