Java 8:为什么最终变量不';开关组不工作?

Java 8:为什么最终变量不';开关组不工作?,java,function,java-8,switch-statement,Java,Function,Java 8,Switch Statement,为什么最终变量有效地用于函数而不用于开关块 下面的示例给出了一个编译错误 String comparing = " "; String effectivelyFinal = "Hello "; switch(comparing){ case effectivelyFinal : System.out.println("Are equal"); break ; default :

为什么最终变量有效地用于函数而不用于开关块

下面的示例给出了一个编译错误

    String comparing = " ";
    String effectivelyFinal = "Hello ";
    switch(comparing){
        case effectivelyFinal :
            System.out.println("Are equal");
            break ;
        default :
            System.out.println("Are not equal");
    }
    Predicate<String> areEqual = s -> s.equals(effectivelyFinal);
字符串比较=”;
字符串effectivelyFinal=“Hello”;
开关(比较){
案例有效最终:
System.out.println(“相等”);
打破
违约:
System.out.println(“不相等”);
}
谓词areEqual=s->s.equals(有效最终);

这段代码不会编译,因为在使用switch case时只能比较常量表达式。而对于lambdas(匿名函数),我们不受此限制


为了澄清更多的混淆,实际上final只是指一个变量或参数,其值在初始化后从未更改,但不一定使其成为一个常量表达式,因为您可以更改它;在这种情况下,它不再是有效的final,因此不允许将其作为开关大小写表达式。

代码不能编译,因为在使用开关大小写时,只能比较常量表达式。而对于lambdas(匿名函数),我们不受此限制


为了澄清更多的混淆,实际上final只是指一个变量或参数,其值在初始化后从未更改,但不一定使其成为一个常量表达式,因为您可以更改它;在这种情况下,它不再是有效的final,因此不允许作为开关大小写表达式使用。

开关标签必须是以下三种类型之一:

通过,常数表达式可以是

引用常量变量(§4.12.4)的简单名称(§6.5.6.1)

您的简单名称不引用常量变量,因此不允许使用


另一方面,对于lambdas,JLS没有此类限制。

开关标签必须是以下三种类型之一:

通过,常数表达式可以是

引用常量变量(§4.12.4)的简单名称(§6.5.6.1)

您的简单名称不引用常量变量,因此不允许使用


另一方面,对于lambda,JLS没有这样的限制。

这是因为
effectivelyFinal
实际上不是
final
,因为您可以将其重新分配给任何其他字符串

编译器确信
编译时常量
,而不是有效的常量

Java语言规范中有更多关于此的内容:

如果通过向变量添加
final
关键字来更新代码,那么它将成为
编译时常量
,代码将编译为现在
有效的final
变量,因为您无法再更改其值

String comparing = " ";
final String effectivelyFinal = "Hello ";
switch(comparing){
    case effectivelyFinal :
        System.out.println("Are equal");
        break ;
    default :
        System.out.println("Are not equal");
}
Predicate<String> areEqual = s -> s.equals(effectivelyFinal);
字符串比较=”;
final字符串effectivelyFinal=“Hello”;
开关(比较){
案例有效最终:
System.out.println(“相等”);
打破
违约:
System.out.println(“不相等”);
}
谓词areEqual=s->s.equals(有效最终);

对于lambda或常规函数,没有这样的限制。

这是因为
effectivelyFinal
不是真正的
final
,因为您可以将其重新分配给任何其他字符串

编译器确信
编译时常量
,而不是有效的常量

Java语言规范中有更多关于此的内容:

如果通过向变量添加
final
关键字来更新代码,那么它将成为
编译时常量
,代码将编译为现在
有效的final
变量,因为您无法再更改其值

String comparing = " ";
final String effectivelyFinal = "Hello ";
switch(comparing){
    case effectivelyFinal :
        System.out.println("Are equal");
        break ;
    default :
        System.out.println("Are not equal");
}
Predicate<String> areEqual = s -> s.equals(effectivelyFinal);
字符串比较=”;
final字符串effectivelyFinal=“Hello”;
开关(比较){
案例有效最终:
System.out.println(“相等”);
打破
违约:
System.out.println(“不相等”);
}
谓词areEqual=s->s.equals(有效最终);

对于lambda或正则函数,没有这样的限制。

因为开关是比较常量,而不是比较其他变量…@Walfrat在Java SE 8中,局部类可以访问局部变量和封闭块的参数,这些变量和参数是final或实际上是final。一个变量或参数的值在初始化后永远不会改变,它实际上是最终的。那么为什么switch不能有效地查看变量呢?它必须在编译时就知道了……我不明白为什么在这里使用
开关格
,而不是简单的
if else
,有效的最终变量的目的是保证变量的值不会改变。但是,它不控制其值的确定方式。它的值可以在运行时解析。
switch
语句只能处理编译时已知的常量值。@ThomasWeller我不这么认为,因为“为什么我不能打开字符串”与Java8无关,因为switch是比较常量,而不是与其他变量比较…@Walfrat在Java SE 8中,局部类可以访问封闭块的局部变量和参数,这些变量和参数是final或实际上是final。一个变量或参数的值在初始化后永远不会改变,它实际上是最终的。那么为什么switch不能有效地查看变量呢?它必须在编译时就知道了……我不明白为什么在这里使用
开关格
,而不是简单的
if else
,有效的最终变量的目的是保证变量的值不会改变。但是,它不控制其值的确定方式。它的值可以在运行时解析。
switch
语句只能处理编译时已知的常量值。@ThomasWeller我不这么认为,因为“为什么我不能打开字符串”与java8Int无关