在Java交换机中声明和初始化变量

nam*_*olk 92 java scope initialization declaration switch-statement

我有一个关于Java交换机的疯狂问题.

int key = 2;

switch (key) {
    case 1:
        int value = 1;
        break;
    case 2:
        value = 2;
        System.out.println(value);
        break;
    default:
        break;
}
Run Code Online (Sandbox Code Playgroud)

场景1 - 当它key为2时,它成功地将值打印为2.
场景2 - 当我要在其中发表评论value = 2case 2:,说出该局部变量值可能尚未初始化.

问题:

场景1:如果执行流程没有进入case 1:(当时key = 2),那么它如何知道值变量的类型为int

场景2:如果编译器知道值变量的类型int,则必须访问.中的int value = 1;表达式case 1:.(声明和初始化).那么为什么sqawrk当我要评论value = 2case 2:,说本地变量值可能没有被初始化.

Jon*_*eet 110

基本上,切换语句在范围方面是奇怪的.从JLS第6.3节开始:

块(第14.4节)中局部变量声明的范围是声明出现的块的其余部分,从其自己的初始化器开始,并包括局部变量声明语句中右侧的任何其他声明符.

在你的情况下,与case 2它在同一个case 1并且在它之后出现,即使case 1永远不会执行...所以局部变量在范围内并且可用于写入,尽管你逻辑上从不"执行"声明.(尽管初始化是,但声明并不是真正的"可执行".)

如果你注释掉了value = 2;赋值,编译器仍然知道你所指的是哪个变量,但是你不会经历任何为它赋值的执行路径,这就是你在尝试时遇到错误的原因.读取任何其他未明确分配的局部变量.

我强烈建议你不要使用在其他情况下声明的局部变量 - 它会导致代码高度混乱,正如你所见.当我在switch语句中引入局部变量时(我很少尝试这样做 - 案例应该非常简短,理想情况)我通常更喜欢引入一个新的范围:

case 1: {
    int value = 1;
    ...
    break;
}
case 2: {
    int value = 2;
    ...
    break;
}
Run Code Online (Sandbox Code Playgroud)

我相信这更清楚.

  • +1"声明不是真的"可执行"虽然初始化是.".谢谢你的建议太Skeet. (10认同)

Pau*_*aul 21

变量已声明(作为int),但未初始化(分配初始值).想想这条线:

int value = 1;
Run Code Online (Sandbox Code Playgroud)

如:

int value;
value = 1;
Run Code Online (Sandbox Code Playgroud)

int value部分在编译时告诉编译器您有一个名为value的变量,它是一个int.该value = 1部分初始化它,但这发生在运行时,如果没有输入交换机的分支,则根本不会发生.


Gar*_*age 18

来自 http://www.coderanch.com/t/447381/java-programmer-SCJP/certification/variable-initialization-within-case-block

声明在编译时处理,不依赖于代码的执行流程.由于value在switch块的本地范围内声明,因此从声明的角度来看,它可以在该块中的任何位置使用.

  • 确实如此.所以,+1,一分钱,也来自我的身边. (7认同)

Nam*_*man 7

通过在 JDK-12 早期访问版本中集成JEP 325:Switch 表达式(预览版)从乔恩的回答中可以看出一些变化 ——

  1. 局部变量作用域- switch case 中的局部变量现在可以是 case 本身的局部变量,而不是整个 switch 块的局部变量。Day考虑枚举类以进行进一步解释的示例(类似于乔恩在语法上尝试的内容)

    public enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }
    
    // some another method implementation
    Day day = Day.valueOf(scanner.next());
    switch (day) {
        case MONDAY,TUESDAY -> {
            var temp = "mon-tue";
            System.out.println(temp);
        }
        case WEDNESDAY,THURSDAY -> {
            var temp = Date.from(Instant.now()); // same variable name 'temp'
            System.out.println(temp);
        }
        default ->{
            var temp = 0.04; // different types as well (not mandatory ofcourse)
            System.out.println(temp);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. Switch 表达式- 如果目的是给变量赋值然后使用它,则可以使用 switch 表达式。例如

    private static void useSwitchExpression() {
        int key = 2;
        int value = switch (key) {
            case 1 ->  1;
            case 2 -> 2;
            default -> {break 0;}
        };
        System.out.println("value = " + value); // prints 'value = 2'
    }
    
    Run Code Online (Sandbox Code Playgroud)