[英]Benefit of using final variables in Java 17 switch-case
有人能告诉我 Java 17 接受最终表达式作为 switch-case-constructs 中的 case 表达式的好处,但不接受最终表达式作为参数传递吗?
void test(int distinction, final int foo) {
final var bar = 2;
switch (distinction) {
case foo -> doSomething(); // does not compile -> case expressions must be constant expressions
case bar -> doSomething(); // does compile
case 3 -> doOtherThings(); // does compile
}
}
为什么编译器不接受案例 1,尽管 foo 和 bar 一样是最终变量?
在我看来,案例 3 的可读性比案例 2 好得多。所以我看不到新语言结构的好处。
案例标签必须是编译时常量。 最终参数不是编译时常量; 它可能不会随着方法的给定调用而变化,但它可以随着方法的调用而变化。 (最终实例字段或没有初始化程序的 static 最终字段也是如此。)
你的陈述“所以我没有看到新语言结构的好处”包含了一个错误的假设,即涉及到一个新的语言结构。
自 Java 1.0 以来,编译时常量的定义没有改变。
常量变量是使用常量表达式( 第 15.29 节)初始化的原始类型或
String
类型的final
变量。
因此,与流行的顽固神话相反,编译时常量不必是static
也不必是字段。 使用常量表达式初始化的final
局部变量是编译时常量。 相反,从不具有初始值设定项的参数永远不会是编译时常量。
此外,当为 integer 类型时, switch
标签必须是编译时常量的规则从未改变。 这更难识别,因为添加了对其他 case 标签的支持,Java 5 引入了切换enum
类型的可能性,Java 7 添加了对切换String
值的支持,并且新的模式匹配将允许切换类型。 在enum
或类型标签的情况下,大小写标签不是编译时常量,而是不变的符号名称,因此在切换enum
或类型时根本不能使用变量名称。
因此,以下程序适用于每个 Java 版本:
class SwitchTest {
public static void main(String[] args) {
final int one = 1, two = 2;
switch(args.length) {
case one: System.out.println("one"); break;
case two: System.out.println("two"); break;
case one + two: System.out.println("three"); break;
}
}
}
这里不需要实际的用例。 拥有简单而一致的规则比拥有试图排除看似无用的组合的复杂规则要好。
作为附录,从Java 5开始,引入注解,以下是合法代码
class Test {
@interface Example { String value(); }
public static void main(String[] args) {
final String str = "test";
@Example(str) class Local {}
}
}
这证明了规则的一致性。 注释要求值是编译时常量,因此如果变量是编译时常量,则可以在注释中使用局部变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.