【问题标题】:Switch Statement: constant expression required error [duplicate]Switch 语句:常量表达式需要错误 [重复]
【发布时间】:2019-02-24 07:04:02
【问题描述】:

Eclipse 显示错误需要常量表达式,但所有归档都是final。那为什么会抛出这个错误。有人可以解释一下我的错误在哪里。

package com.oca.test.exam;

public class Test {

    public static final Integer x1 = 5;
    public static final Integer x2 = 10;
    public static final Integer x3 = 15;
    public static final Integer x4 = 20;

    public static void main(String[] args) {
        switch (x1) {
        case x1: 
            System.out.println();
            break;

        case x2: 
            System.out.println();
            break;

        case x3: 
            System.out.println();
            break;

        case x4: 
            System.out.println();
            break;
        }
    }
}

【问题讨论】:

  • "请不要标记重复的问题 问题是新的。" - Nope.
  • 顺便说一句:x1 什么时候不等于 x1
  • 用例 5:System.out.println();休息;案例 10:System.out.println();休息;案例 15:System.out.println();休息;案例 20:System.out.println();休息;默认值:System.out.println();休息;

标签: java switch-statement final


【解决方案1】:

一个 TL;DR 在最后。

查看documentation of the switch statement,我们可以找到以下内容:

开关适用于 byte、short、char 和 int 原始数据类型。它还适用于枚举类型(在 Enum Types 中讨论)、String 类和一些包装某些基本类型的特殊类:Character、Byte、Short 和 Integer(在 Numbers 和 Strings 中讨论)。

起初这似乎很好,你的问题不应该存在。然而,该定义没有提到这些包装器可以在哪里使用,在哪里不可以使用。查看specs of the switch-statements (JLS),我们发现开关的形式为:

1 个开关表​​达式

SwitchStatement: switch ( Expression ) SwitchBlock

进一步解释Expression

表达式的类型必须是 char、byte、short、int、Character、Byte、Short、Integer、String 或枚举类型(第 8.9 节),否则会发生编译时错误。

所以在这里,使用诸如Integer 之类的包装类是完全可以的。编译器会管理。

2 开关块

开关块可以分解为:

SwitchLabels BlockStatements

SwitchLabel 定义为:

SwitchLabel: case ConstantExpression : case EnumConstantName : default :

所以标签只接受常量表达式或枚举。如果我们现在查看definition of a constant expressions,我们会发现:

常量表达式是表示原始类型值或字符串的表达式...

当然,必须应用一些条件才能使原始类型成为常量(在此处列出),但在您的情况下,重要的部分是您必须使用原始类型或字符串。

奖金

包装类和原始类型之间的交换称为“自动装箱或拆箱”(取决于方向)。根据documentation,拆箱发生在:

将包装类型 (Integer) 的对象转换为其对应的原始 (int) 值称为拆箱。 Java 编译器在包装类的对象为以下情况时应用拆箱:

  • 作为参数传递给需要 对应的原始类型。
  • 分配给一个变量 对应的原始类型。

因此,Java 似乎根本不是为了使 switch 语句按照您的预期工作而进行所需的拆箱。

----------

TL;DR

对于 switch 表达式,您可以使用包装类。但是,对于标签,您只能使用原始类型:byte、short、char 和 int。

【讨论】:

    【解决方案2】:

    case 表达式必须是常量表达式,你可以使用 enum 更好的常量值和更可读的代码,这里是 enum 的例子:

    枚举类:

        public enum Numbers {
    
        HIGH(3), // calls constructor with value 3
        MEDIUM(2), // calls constructor with value 2
        LOW(1) // calls constructor with value 1
        ; // semicolon needed when fields / methods fol
        private final int levelCode;
    
        Numbers(int levelCode) {
            this.levelCode = levelCode;
        }
    
        public int getLevelCode() {
            return this.levelCode;
        }
    }
    

    给你的主要方法:

    public class Test {
    
        public static void main(String[] args) {
            switch (Numbers.HIGH) {
            case HIGH:
                System.out.println("hight");
                break;
    
            case MEDIUM:
                System.out.println("medium");
                break;
    
            case LOW:
                System.out.println("low");
                break;
    
            }
    
        }
    }
    

    【讨论】:

    • 您在switch 条件中使用Numbers.HIGH,但在这些情况下使用HIGHMEDIUMLOW。这可能会导致严重的错误。
    • 我知道,但那是让他明白什么对他更好,他想在 switch 语句中使用 x1,所以他已经想使用 final 作为常量值,但是 switch 比 final 值更好
    【解决方案3】:

    在 Java 中声明为 final 的变量不被视为编译时常量,因为它们的值仍然可以在运行时更改 - 从未定义状态变为已定义状态。

    必须在现场定义案例值,例如。 case 5: case 12: case "green":

    【讨论】:

    • 案例 12.5f: 你确定浮点型..
    • 你是对的,整数是这里唯一有效的数字。已更正。
    猜你喜欢
    • 2023-01-16
    • 1970-01-01
    • 2015-11-02
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多