用java.lang.Boolean和switch做三元逻辑

Mat*_*nge 4 java logic boolean switch-statement

java.lang.Boolean非常适合处理三元逻辑,因为它可以完全具有三种状态:Boolean.TRUE(就是这种情况),Boolean.FALSE(事实并非如此)和null(我们不知道)情况如何).使用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;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,Java不允许这样做,抱怨"无法打开布尔值类型的值".实现这会导致混淆的控制流和unnice代码:

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));
}
Run Code Online (Sandbox Code Playgroud)

这样做很好的方法需要实现一个枚举类(在现实生活中,比这个例子更复杂,因为必须重写.equals()以便Trinary.NULL.equals(null)变为真)并转换:

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;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,这是更好的,因为更可读的解决方案,但只是转换的代码的原始方法大小的另一半是令人讨厌的,并且在现实生活中你必须关心具有相同语义的两个不同的空值.有没有更好的方法呢?

Jon*_*nge 6

使用null对象来传达这样的信息并不是最佳的.请记住,你不能做一个空的对象,而这又意味着,如果你在未来不断会想调用任何.getClass,.equals,.compare等,你就必须重写代码的任何方法调用.

你最好的选择肯定是使用enum选项.

enum Ternary {TRUE,FALSE,UNKNOWN}
Run Code Online (Sandbox Code Playgroud)

您可以进一步扩展类以获得获取此类对象的方法,

public Ternary getByValue(Boolean o) {
    if(o == null)
        return UNKNOWN;
    if(o)
        return TRUE;
    return FALSE;
}
Run Code Online (Sandbox Code Playgroud)