4

java.lang.Boolean は、Boolean.TRUE (該当する場合)、Boolean.FALSE (該当しない)、null (不明) の 3 つの状態を持つことができるため、三項論理を処理するのに最適です。どんな場合ですか)。switch ステートメントを使用してこれを処理するのは良い設計です。このコンストラクターで:

public class URN {
private String value = null;    

public URN (String value, Boolean mode){
    switch (mode){
        case TRUE:
            if(!isValidURN(value))
                throw new MalformedURLException("The string could not be parsed.");
            this.value = value;
        break;
        case FALSE:
            this.value = value.concat(checkByteFor(value));
        break;
        case null:
            if(isValidURN(value))
                this.value = value;
            else
                this.value = value.concat(checkByteFor(value));
        break;
    }
    return;
}

残念ながら、Java はそれを許可せず、「Boolean 型の値をオンにすることはできません」と不平を言っています。これを実装すると、難読化された制御フローと見栄えの悪いコードが生成されます。

public URN (String value, Boolean mode){
    Boolean valid = null;
    if (!Boolean.FALSE.equals(mode)){
        valid = isValidURN(value);

        if (Boolean.TRUE.equals(mode) && !valid)
                throw new MalformedURLException("The string could not be parsed.");

        if(Boolean.TRUE.equals(valid)) {
            this.value = value;
            return;
    }   }

    this.value = value.concat(checkByteFor(value));
}

良い方法でそれを行うには、enum クラスを実装する必要があります (実際には、Trinary.NULL.equals(null) が true になるように .equals() を書き直す必要があるため、この例よりも複雑です) と変換:

private enum Trinary {TRUE, FALSE, NULL};
public URN (String value, Boolean toConvert, String x){

    Trinary mode;
    if(toConvert == null)
        mode = Trinary.NULL;
    else
        mode = toConvert.equals(Boolean.TRUE) ? Trinary.TRUE : Trinary.FALSE;

    switch (mode){
        case TRUE:
            if(!isValidURN(value)) throw new MalformedURLException("The string could not be parsed.");
            this.value = value;
        break;
        case FALSE:
            this.value = value.concat(checkByteFor(value));
        break;
        case NULL:
            if(isValidURN(value))
                this.value = value;
            else
                this.value = value.concat(checkByteFor(value));
        break;
    }
    return;
}

私の目には、これはより読みやすい解決策であるため、より優れていますが、変換するだけのコードの元のメソッドサイズの残りの半分は面倒であり、実際には、同じセマンティックを持つ 2 つの異なる null に注意する必要があります。それを行うより良い方法はありますか?

4

2 に答える 2

6

このような情報を伝達するために null オブジェクトを使用することは最適ではありません。null オブジェクトに対してメソッド呼び出しを行うことはできないことに注意してください。これは、将来、.getClass、.equals、.compare などを呼び出したい場合は、コードを書き直す必要があることを意味します。

あなたの最善の選択肢は、間違いなく enum オプションを使用することです。

enum Ternary {TRUE,FALSE,UNKNOWN}

さらにクラスを拡張して、そのようなオブジェクトを取得するメソッドを持つことができます。

public Ternary getByValue(Boolean o) {
    if(o == null)
        return UNKNOWN;
    if(o)
        return TRUE;
    return FALSE;
}
于 2012-08-11T08:35:42.940 に答える
2

私は、スイッチが言及されていないかのようにサポートnullまたは処理するという面倒なことに同意します。default

注: Trinary は混乱を招く可能NULLnullがあります。

true、false、および null を使用する代わりに。モードには意味のある名前を使用することをお勧めします。たとえば、VALIDATING、CONCATENATING、MIXED、またはより適切なものを使用します。

最も簡単な解決策は

public URN (String value, Boolean mode){
    if (mode == null) {
        this.value = isValidURN(value) ? values : value.concat(checkByteFor(value));
    } else if (mode) {
        if(!isValidURN(value))
            throw new MalformedURLException("The string could not be parsed.");
        this.value = value;
    } else {
        this.value = value.concat(checkByteFor(value));
    }
    return;
}

ところで、と比較するTRUEと混乱する可能性があります。

Boolean b = new Boolean(true);
if (b == Boolean.TRUE) // is false !!!
于 2012-08-10T07:38:40.293 に答える