Java 开关默认分支从未到达,但需要用于任意返回值/异常

Java 开关默认分支从未到达,但需要用于任意返回值/异常,java,methods,enums,return,switch-statement,Java,Methods,Enums,Return,Switch Statement,现在我正在读一本Java书籍,里面有很多简洁的练习。其中一个想让我用枚举实现Mod-3的模运算 我已经到了一个地步,我不知道如何以一种我可以秘密地向其他人展示的方式实现一个方法 该方法获取一个自然数(包括0)并将其转换为模-3值,将其作为枚举元素返回。我的问题是switch语句。当我进行模-3运算并检查前提条件时,我有3种可能的情况需要检查,0,1或2。每个都返回其对应的enum元素,但编译器根本不知道这一点,并希望我用return语句定义一个default分支 如果在default中定义ret

现在我正在读一本Java书籍,里面有很多简洁的练习。其中一个想让我用枚举实现Mod-3的模运算

我已经到了一个地步,我不知道如何以一种我可以秘密地向其他人展示的方式实现一个方法

该方法获取一个自然数(包括0)并将其转换为模-3值,将其作为枚举元素返回。我的问题是switch语句。当我进行模-3运算并检查前提条件时,我有3种可能的情况需要检查,0,1或2。每个都返回其对应的enum元素,但编译器根本不知道这一点,并希望我用return语句定义一个
default
分支

如果在
default
中定义
returnnull
,知道它永远不会被执行,并且(对我来说)返回
null
毫无意义,我会认为它是一个糟糕的代码。因此,抛出一个异常会更好(我认为),但是现在我必须选择一个异常类型,并且我需要定义异常处理,知道逻辑使得抛出不可能(因为之前的
断言

如果您回答,请解释为什么您的实现优于其他实现。我非常感谢你抽出时间

public enum Mod3 {
    Zero(0), One(1), Two(2);

    private final int value;

    Mod3(final int value) {
        this.value = value;
    }

    /**
     * Converts a given natural number to a modulo value.
     * @param naturalNumber To be converted to modulo-value. Not negative.
     * @return The modulo-value of given naturalNumber. 0 <= value < 3.
     */
    Mod3 get(final int naturalNumber) throws IllegalArgumentException {
        final int moduloNumber;
        if (naturalNumber >= 0)
            moduloNumber = naturalNumber % 3;
        else
            throw new IllegalArgumentException("argument has not to be negative, but was " + naturalNumber);


        assert moduloNumber >= 0 && moduloNumber < 3: "moduloNumber should have been >= 0 and < 3, but was " + moduloNumber;
        switch (moduloNumber) {
            case 0: return Zero;
            case 1: return One;
            case 2: return Two;

            // I don't know what to do here.
            default: throw new WhatTypeOfExceptionToUseHere("Logic error! Should have never been thrown!");
        }
    }
}
公共枚举Mod3{
零(0)、一(1)、二(2);
私有最终整数值;
Mod3(最终整数值){
这个值=值;
}
/**
*将给定的自然数转换为模值。
*@param naturalNumber要转换为模值。不是负值。
*@返回给定自然数的模值。0=0)
ModuleNumber=自然数%3;
其他的
抛出新的IllegalArgumentException(“参数必须不是否定的,而是“+naturalNumber”);
断言modulenumber>=0&&modulenumber<3:“modulenumber本应>=0且<3,但为“+modulenumber;
交换机(模块数){
案例0:返回零;
案例1:返回一个;
案例2:返回两个;
//我不知道在这里该怎么办。
默认设置:抛出新的WhatTypeOfExceptionToUsere(“逻辑错误!应该从未抛出过!”);
}
}
}
但编译器对此一无所知,希望我用return语句定义一个默认分支

编译器会抱怨,因为您的方法必须返回某些内容,遗憾的是,编译器没有那么聪明,无法理解您只是检查了3个选项

可能的解决方案(所有这些解决方案都包括从
开关
中删除
默认
案例):

  • throw new whattypeofexceptiontosehere
    语句移动到
    开关
    之后

  • 将您的
    0
    1
    2
    作为
    默认值(我并不建议这样做)

  • 添加一个
    返回null
    开关
    语句之后

对于您的
WhattypeofExceptionTohere
,您可以定义新的异常或使用。依我看,后者比前者好


需要注意的是,和
算术异常
都是从扩展而来的,这意味着它们是并且不需要在方法定义中指定。

最好不要先断言,而是让默认值抛出错误。这是因为JVM可能会关闭断言。

如果我抛出异常,您会为此定义一个新的异常类,还是选择什么类型?返回的
null
代码是否不错?很高兴知道,它们是从
RuntimeException
扩展而来的,我几乎没有经验。尽管如此,您的建议之一是返回
null
,我是否应该避免这种情况,因为它可能对阅读我的代码的人没有意义,因为null在这里没有任何意义,因为它只是编译器保持安静的肉?@th3m3s这取决于您的编程风格。正如我指出的,它们只是可能的解决方案,这将取决于应用程序设计者定义使用哪种方法。在我看来,我更愿意抛出
运行时异常
并在应用程序的另一个层中处理异常。如果我删除
断言
并在默认分支中抛出异常,您会为此定义自己的异常类,还是选择预定义的异常类(如果,哪个)?此外,您会在某个地方处理
异常
,还是将其传递给JVM?最后,切换前的
assert
是否不是一个好主意,因为它确实是一个捕捉逻辑故障的断言,因为如果逻辑正确,则该值不可能与断言检查的值不同,因此,它只是用于开发目的,不会在构建中被激活。实际上,您永远不应该使用断言来捕获逻辑故障,因为断言可能会被关闭。因此,你的逻辑将失败。但如果,ofc,它只用于开发目的,它可以放在那里。我会抛出一个非法的辩论例外,但这是有争议的。。