用 java.lang.Boolean 和 switch 做三元逻辑
Posted
技术标签:
【中文标题】用 java.lang.Boolean 和 switch 做三元逻辑【英文标题】:Doing Trinary logic with java.lang.Boolean and switch 【发布时间】:2012-08-07 11:57:08 【问题描述】: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;
不幸的是,Java 不允许这样做,并抱怨“无法打开布尔类型的值”。实现这个会导致混淆的控制流和不好看的代码:
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));
这样做需要实现一个枚举类(在现实生活中,它比这个例子更复杂,因为必须重写 .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;
在我看来,这是更好的解决方案,因为更具可读性,但是要转换的源方法大小的另一半很烦人,在现实生活中,您必须关心两个具有相同语义的不同空值。有没有更好的方法?
【问题讨论】:
有人可能会在此处添加“三元逻辑”标签 :) 其实叫“三元” ;-) 更好的方法:不要让NULL
等于null
,首先不要使用null
。
【参考方案1】:
使用空对象来传达这样的信息并不是最佳选择。请记住,您不能对 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;
【讨论】:
【参考方案2】:我同意这个开关确实支持null
或将其视为default
(如果未提及),这很烦人。
注意:Trinary 可以是 NULL
或 null
,这可能会造成混淆。
而不是使用真、假和空。我建议为模式使用有意义的名称。例如使用 VALIDATING、CONCATNATING、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 !!!
【讨论】:
以上是关于用 java.lang.Boolean 和 switch 做三元逻辑的主要内容,如果未能解决你的问题,请参考以下文章
javax.el.PropertyNotFoundException:属性 'foo' 在 java.lang.Boolean 类型上不可读
无法将 java.lang.Boolean 类型的对象转换为类型