0

次のパターンの Java コードがあります。

enum Foo
{
    ORANGE, APPLE, BANANA
}

Foo bar()
{
    switch(calcValue())
    {
        case "orange": return ORANGE;
        case "apple": return APPLE;
        case "banana": return BANANA;
    }
}

メソッドの設計により、switch ステートメントがチェックする 3 つの文字列以外は何もcalcValue返されないことが保証されます。3 つの文字列のいずれも返すことができない場合は、例外がスローされます。これは、不足しているキーワードが不要である可能性があり、デフォルトのスイッチ動作がトリガーされないことを意味します。したがって、省略されます。ただし、Java は当然のことながら (そして当然のことながら、一般的には)、(常に) 値を返さなければならないと文句を言います。デフォルトで例外をスローすることを考えていましたが、前述のように既に例外がスローされています。私は主に、この小さな問題を解決するためのシンプルで効率的な (最小限のランタイム チェックとコードを含む) 設計を求めています。2 つの例外をスローしたくありません。defaultdefaultbarcalcValuecalcValue私の支配下にないので、私はそれをどうすることもできません。

ここで自分自身を十分に説明したことを願っています。そうでない場合は、明確にするために最善を尽くします。本質的に、これは、スイッチのデフォルトが適用されないことがわかっている値を持つメソッドを設計することに関するものです。if-then-else-if-then-else-...-then-elseこれは、ステートメント パターンにも適用される場合があります。

4

7 に答える 7

2

あなたが書いた

calcValue メソッドの設計により、switch ステートメントがチェックする 3 つの文字列以外は返されません。

ただし、この契約は の署名によって表されませんcalcValue。文字列を返すだけで、Java の型チェッカーは、一部の文字列のみが可能であることを知る方法がありません。これは、関数の API の欠陥だと思いcalcValueます。

肝心なのは、Java が正しいということです。内部の動作に関する想定は型システムによって強制されないため、ケース不足しているため、コンパイラが気付かないうちにいつでも変更される可能性があります。defaultcalcValue

于 2012-09-28T09:29:59.497 に答える
1

デフォルトのケースではエラーがcalcValue()スローされますが、これは論理的な結論であり、Java コンパイラはそれを理解できないため、戻り値のないコード パスについて不平を言っています。デフォルトの場合でも、このメソッドから例外をスローする必要があります。

于 2012-09-28T09:23:06.830 に答える
1

正当な理由を求めています。calcValue() を制御しないため、将来の変更を処理するコードが必要です。

ただし、上記のように続行する場合は、最後のケースをデフォルトに変更して、ORANGE または APPLE がない場合に常に "BANANA" を返すようにします。

于 2012-09-28T09:24:04.147 に答える
1

あなたが言った

calcValue は私の管理下にありません

throw次に、それが常に例外になることに依存するべきではありません。

コンストラクトに追加defaultするswitch必要があり、制御がそこに到達した場合は例外をスローする必要があります。

もう 1 つのポイントは、bar()メソッドはそれ自体で完全でなければならないということです。

と密結合させようとしていcalcValue()ます。の署名コントラクトは、Bar()常に a を返すと言っていますが、それを行う代わりに、コントラクトの実装にFoo依存しています。calcValue()それは間違っています。

于 2012-09-28T09:24:49.940 に答える
1

私の意見では、長い if/then/else および switch ステートメントは悪い兆候です。できる限りオブジェクト指向スタイルで書くことを好みます。

Map を使用して、キーを渡し、値を返すように。

あなたの簡単な例は、列挙型である可能性があり、また列挙型であるべきです。

于 2012-09-28T09:22:10.683 に答える
1

質問に直接答えるわけではありませんが、使用するものが簡単になるかもしれませんEnum.valueOf()。がこれら 3 つの値のいずれかを返すことが保証されている場合calcValue()は、次のようにすることができます。

enum Foo { ORANGE, APPLE, BANANA }

Foo bar() { return Foo.valueOf(calcValue().toUpperCase()); }

そして、決定を にデリゲートします。ちなみに、そのような要素がない場合Enum.valueOfは をスローします。IllegalArgumentException

于 2012-09-28T09:28:36.907 に答える
1

一般的なパターンは、列挙型に自分自身を適切に変換する方法を知ってもらうことです

public enum Foo {
    BANANA("banana"),
    ORANGE("orange"),
    APPLE("apple");

private String calculationCode;

private Foo(String calculationCode) {
    this.calculationCode=calculationCode;
}

public static Foo byCalculationCode(String code) {
    for (Foo foo : values()) {
        if (foo.calculationCode.equals(code)) {
            return foo;
        }
    }
    throw new NoSuchElementException("Unknown code:" + code);
}
于 2012-09-28T10:23:57.763 に答える