Java 爪哇语:在一个开关盒中,不能在一个盒后断开-为什么?

Java 爪哇语:在一个开关盒中,不能在一个盒后断开-为什么?,java,switch-statement,Java,Switch Statement,我编了一个游戏。 我使用SwitchCase实现了一个状态机。 问题是,如果是ZIEHEN_SP,break语句就不起作用。 当我调试它时,编译器只需跳过break语句,然后转到下一个例子ZIEHEN_BA 我对编译器忽略break语句的部分进行了注释 为什么? import java.util.*; 导入java.util.Scanner; 导入java.io.*; 黑杰克2级{ 静态整数芯片=100; 静态int einsatz=0; 枚举状态{INIT,EINSATZ,ZIEHEN_SP,

我编了一个游戏。 我使用SwitchCase实现了一个状态机。 问题是,如果是ZIEHEN_SP,break语句就不起作用。 当我调试它时,编译器只需跳过break语句,然后转到下一个例子ZIEHEN_BA

我对编译器忽略break语句的部分进行了注释

为什么?

import java.util.*;
导入java.util.Scanner;
导入java.io.*;
黑杰克2级{
静态整数芯片=100;
静态int einsatz=0;
枚举状态{INIT,EINSATZ,ZIEHEN_SP,ZIEHEN_BA}
静态状态=State.INIT;
静态ArrayList bankKarten=新ArrayList();
静态ArrayList SpilerKarten=新ArrayList();
静态扫描仪=新扫描仪(System.in);
静态字符串s=“”;
静态int eingabe=0;
静态void init(){
System.out.println(“\nEin neues Spiel beginnt:”);
bankKarten.clear();
斯皮尔卡顿;
bankKarten.add(giveCard());
添加(giveCard());
}
静态空隙切屑塞森(){
einsatz=0;
如果(芯片==0){
System.out.print(“\nSie haben”+chips+“chips!”);
系统出口(1);
}
做{
系统输出打印(“\nSie haben”+芯片+芯片”);
System.out.print(“\n您是否已设置?”;
试一试{
einsatz=Integer.parseInt(scanner.next());
}捕获(例外e){
}
}while(einsatz芯片);
芯片-=einsatz;
}
静态int sumSpielerKarten(){
整数和=0;
对于(int i=0;i 21 | |(s>b&s 21 | | b>s | | b==21&&s!=21){
ret=“银行”;
}else如果(b==s){
ret=“两者”;
}
返回ret;
}
静态int updateMoney(int s,int b){
字符串获胜者=评估获胜者(s,b);
int newChips=0;
如果(获胜者=“玩家”){
新芯片=einsatz*2+芯片;
}否则如果(获胜者=“双方”){
新芯片=einsatz+芯片;
}否则如果(获胜者=“银行”){
新芯片=芯片;
}
System.out.println(“获胜者:+Winner”);
归还新芯片;
}
静态无效显示卡(){
系统输出打印(“\n银行:\t”);

对于(int i=0;i,因为您将
state
更改为与
state.ZIEHEN_BA
条件匹配的值:

 state = State.ZIEHEN_BA;
因此,这里:

while(true){
   ... 
       state = State.ZIEHEN_BA;
       break; 

    case ZIEHEN_BA:
       banksTurn();
       state = State.INIT;
       break;
   ...
}
在循环的下一次迭代中执行
案例ZIEHEN_BA

Eclipse显示的可能是在运行时或由编译器执行的JVM优化


编辑

我已经完成了测试,我不认为这是编译器优化。

请看这个最小的示例,在这种情况下,我没有设置状态:

public class TestSwitch {

    public enum MyEnum {
        A, B
    };

    public static void main(String[] args) {

        MyEnum state = MyEnum.A;

        while (true) {
            switch (state) {

            case A:             
                break;

            case B:
                break;
            }
        }
    }
}
下面是main()方法的反汇编代码:

 public static void main(java.lang.String[]);
   Code:
      0: getstatic     #18                 // Field a/TestSwitch$MyEnum.A:La/TestSwitch$MyEnum;
      3: astore_1
      4: invokestatic  #24                 // Method $SWITCH_TABLE$a$TestSwitch$MyEnum:()[I
      7: aload_1
      8: invokevirtual #27                 // Method a/TestSwitch$MyEnum.ordinal:()I
     11: iaload
     12: tableswitch   { // 1 to 2
                    1: 36
                    2: 39
              default: 39
         }
     36: goto          4
     39: goto          4
 public static void main(java.lang.String[]);
   Code:
      0: getstatic     #18                 // Field a/TestSwitch$MyEnum.A:La/TestSwitch$MyEnum;
      3: astore_1
      4: invokestatic  #24                 // Method $SWITCH_TABLE$a$TestSwitch$MyEnum:()[I
      7: aload_1
      8: invokevirtual #27                 // Method a/TestSwitch$MyEnum.ordinal:()I
     11: iaload
     12: tableswitch   { // 1 to 2
                    1: 36
                    2: 43
              default: 43
         }
     36: getstatic     #31                 // Field a/TestSwitch$MyEnum.B:La/TestSwitch$MyEnum;
     39: astore_1
     40: goto          4
     43: goto          4
看看我在案例A中设置的状态在案例B中输入的版本:

public class TestSwitch {

    public enum MyEnum {
        A, B
    };

    public static void main(String[] args) {

        MyEnum state = MyEnum.A;

        while (true) {
            switch (state) {

            case A:
                state = MyEnum.B;
                break;

            case B:
                break;
            }
        }
    }
}
下面是main()方法的反汇编代码:

 public static void main(java.lang.String[]);
   Code:
      0: getstatic     #18                 // Field a/TestSwitch$MyEnum.A:La/TestSwitch$MyEnum;
      3: astore_1
      4: invokestatic  #24                 // Method $SWITCH_TABLE$a$TestSwitch$MyEnum:()[I
      7: aload_1
      8: invokevirtual #27                 // Method a/TestSwitch$MyEnum.ordinal:()I
     11: iaload
     12: tableswitch   { // 1 to 2
                    1: 36
                    2: 39
              default: 39
         }
     36: goto          4
     39: goto          4
 public static void main(java.lang.String[]);
   Code:
      0: getstatic     #18                 // Field a/TestSwitch$MyEnum.A:La/TestSwitch$MyEnum;
      3: astore_1
      4: invokestatic  #24                 // Method $SWITCH_TABLE$a$TestSwitch$MyEnum:()[I
      7: aload_1
      8: invokevirtual #27                 // Method a/TestSwitch$MyEnum.ordinal:()I
     11: iaload
     12: tableswitch   { // 1 to 2
                    1: 36
                    2: 43
              default: 43
         }
     36: getstatic     #31                 // Field a/TestSwitch$MyEnum.B:La/TestSwitch$MyEnum;
     39: astore_1
     40: goto          4
     43: goto          4
此编译代码中没有优化。

案件A执行后:

     36: getstatic     #31                 // Field a/TestSwitch$MyEnum.B:La/TestSwitch$MyEnum;
     39: astore_1
下一条指令是转到循环:

40: goto          4

因此,优化可能是由JVM或Eclipse调试器在运行时执行的。

编译器优化了您的代码:-)

当您将开关变量设置为
State.ZIEHEN_BA
时,在这两行之间没有要执行的内容(
while(true)
和重新输入开关),这正是下一行要执行的内容

我不确定它是否应该以这种方式运行(在开关内部打开变量将导致检查以下情况),但在您的情况下,我完全同意编译器

正如您在本例中所看到的,这种行为并不总是如此:

public static void main(String[] args) {
    int i = 3;
    switch(i) {
    case 1:
        System.out.println("1:");
        break;
    case 2:
        System.out.println("2:");
        break;
    case 3:
        System.out.println("3:");
        i = 5;
        break;
    case 4:
        System.out.println("4:");
        break;
    case 5:
        System.out.println("5:");
        i = 5;
        break;
    case 6:
        System.out.println("6:");
        break;
    case 7:
        System.out.println("7:");
        break;
        default:
            break;
    }
    System.out.println("I = " + i);
}
导致

 3:
 I = 5

这是一个优化。当您将状态设置为ZIEHEN_BA时,编译器知道它将作为下一步到达那里。如果没有优化,只会有一些传统的步骤,但无论如何它都会到达那里:


设置状态;执行中断;转到while(true),现在执行切换并…它到达ZIEHEN_BA。因此,这相当于直接到达那里。

实际上,编译器并没有忽略中断

当您在现有案例语句中设置
state=state.ZIEHEN_BA

因此,在调用break之后,它将在
while(ture)
循环的下一次迭代中直接进入
ZIEHEN_BA
。)


通过忽略
break
,它似乎会直接进入
ZIEHEN_BA
,但它会在接下来的迭代中进入那里。

您编写的主程序是一个不可中断的循环。一旦我们正确地看到代码,您就会在遇到某个情况时将状态分配给另一个情况。而且,您永远不会结束中断了循环。while循环不知道在哪里停止。不确定你想做什么

仅供参考,中断没有被跳过,但它只起到了中断开关循环的作用。我猜您的期望是中断while循环…


如果希望代码在特定点停止,请在while循环中放置一个中断。再次在开关中放置
break;
不会起作用,因为它会中断开关循环。相反,请尝试在while之前设置一个
布尔变量
,并在希望循环中断的位置将变量值更改为
false

o使用C?将状态设置为
状态。ZIEHEN_BA
并在
开关
周围有一个
循环,那么除了进入该状态之外,你还期望什么呢?在
开关
求值中更改
状态
的值是个坏主意。在
开关
中,你应该将下一个状态分配给一个新变量在
开关
语句中断后,再次循环,并且自状态更改后,调试