【问题标题】:"Missing return statement" after switch(enum) - Why?switch(enum) 之后的“缺少返回语句” - 为什么?
【发布时间】:2018-05-02 20:10:23
【问题描述】:

编译器声称MyClass.parse() 末尾缺少返回语句。代码如下:

package de.hs_rm.safelyovertaken.ble;

import android.support.annotation.NonNull;

import java.util.Arrays;

class MyClass {

    @NonNull
    static MyClass parse(byte[] encoded) throws MyParseException {

        MyEnum myEnum = MyEnum.parse(Arrays.copyOfRange(encoded, 0, 2));

        switch (myEnum) {
            case A:
                return new MyClassA();

            case B:
                return new MyClassB();

            case C:
                return new MyClassC();
        }

        // compile error: "Missing return statement"

//        return null; // should never be reached
//        throw new AssertionError("Should never be reached");
    }
}

enum MyEnum {
    A, B, C;

    @NonNull
    static MyEnum parse(byte[] encoded) throws MyParseException {

        MyEnum result = null;

        // parse logic here

        if (result == null) {
            throw new MyParseException();
        }

        return result;
    }
}

class MyParseException extends Exception {
}

class MyClassA extends MyClass {
}

class MyClassB extends MyClass {
}

class MyClassC extends MyClass {
}

编译器对吗? (安卓工作室)

如果是这样,在什么情况下可以达到方法的结尾?我认为 myEnum 不能是 null 并且所有枚举都包含在 switch 语句中,在任何情况下,return 语句都会离开该方法。 myEnum 不能是 null,因为如果结果是 null@NonNull 方法 MyEnum.parse() 会抛出异常。

如果不是,您会用return null // should never be reached 标记方法的(希望是)无法到达的结尾还是抛出AssertionError

【问题讨论】:

  • 'myEnum 不能是 null,因为如果结果是 MyEnum.parse()@NonNull 方法会抛出异常 null' - 编译器不知道这一点

标签: java enums compiler-errors


【解决方案1】:

编译器对吗?

是的,因为它不会在编译时验证枚举覆盖率。假设枚举存在于另一个二进制文件中,并使用新常量进行了更新。该方法会返回什么?

myEnum 不能是 null,因为如果结果是 null@NonNull 方法 MyEnum.parse() 会抛出异常。

编译器不够聪明,无法解决这个问题(尽管您的 IDE 可能如此)。但这是一个有争议的问题,因为打开 null 会导致 NPE。

如果不是,您会用return null // should never be reached 标记方法的(希望)无法到达的结尾还是抛出AssertionError

投掷AssertionError 非常传统。或者,考虑使用embedding conditional logic in the enum constants 而不是使用开关。

【讨论】:

  • 我认为在 switch 语句中检查枚举覆盖率是枚举优于常量的一个优势。但是是的..由于枚举值存储在使用它们的 .class 文件中,您描述的场景应该使检查在技术上是不可能的。
  • TBH 我从来没有遵循“假设枚举存在于另一个 jar 中并使用新常量更新它”的逻辑。我知道这是关于破坏性与非破坏性的变化,但是......如果我的代码足够强大,可以处理在撰写本文时甚至不存在的枚举案例,那么我想我会永远需要是default 子句。在枚举常量中嵌入条件逻辑比 switch 子句要好得多
猜你喜欢
  • 2014-02-17
  • 2013-11-30
  • 2017-01-26
  • 2017-09-21
  • 2021-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-21
相关资源
最近更新 更多