将字符串解析为布尔值,默认值为 true

mkc*_*zyk -1 java apache-commons guava

我有一个字符串,我想将其解析为布尔值。如果它不包含truefalse字符串,它应该返回默认值(true在我的例子中)。

"true" -> true
"false" -> false
"something" -> true
Run Code Online (Sandbox Code Playgroud)

我正在寻找 Java 方法或一些 util(Apache Commons 或 Guava)。


我无法使用Java方法Boolean.parseBoolean,因为它没有带默认值的参数(默认值始终是false):

System.out.println(Boolean.parseBoolean("true")); // true
System.out.println(Boolean.parseBoolean("false")); // false
System.out.println(Boolean.parseBoolean("something")); // false instead of true
Run Code Online (Sandbox Code Playgroud)

与 Apache Commons 相同BooleanUtils.toBoolean

System.out.println(BooleanUtils.toBoolean("true")); // true
System.out.println(BooleanUtils.toBoolean("false")); // false
System.out.println(BooleanUtils.toBoolean("something")); // false instead of true
Run Code Online (Sandbox Code Playgroud)

我可以写我自己的方法:

private static Boolean toBoolean(String value, boolean defaultValue) {
    return Optional.ofNullable(BooleanUtils.toBooleanObject(value))
            .orElse(defaultValue);
}
Run Code Online (Sandbox Code Playgroud)

并使用它:

System.out.println(toBoolean("true", true)); // true
System.out.println(toBoolean("false", true)); // false
System.out.println(toBoolean("something", true)); // true (that's what I want!)
Run Code Online (Sandbox Code Playgroud)

但是,我希望某些 util 中存在用默认值解析为布尔值的方法,或者我可以用更简单的方式来实现(在 lambda 链中使用一个衬垫)。

rzw*_*oot 5

该方法不存在也不应该存在于任何标准库中,因此,您应该自己编写它。Apache 中有类似的东西,但它默认为 false,并且像 apache 公共库中的很多东西一样,这是一个你不应该使用的糟糕方法。核心库中也有类似的东西 ( Boolean.parseBoolean),但它也默认为 false,而且也是一个不应该使用的坏方法。在这里编写自己的方法是正确的策略。

你的实现有点奇怪:

  • 它不遗余力地跳舞,null尽管equals它自己已经做得很好了
  • 它是一个简单的实用方法,它使用整个库只是为了调用其中包含的一个简单的实用方法。这不是 javascript -你肯定不希望因为如此微不足道的事情而导致左键盘崩溃
  • 它使用大写 B 布尔值,尽管它实际上无法返回,null这很奇怪。

为什么不保持简单呢?

public boolean isFalse(String in) {
    return "false".equals(in);
}

public boolean isTrue(String in) {
    return "true".equals(in);
}
Run Code Online (Sandbox Code Playgroud)

这些方法:

  • 做你想做的事
  • 它们的名称准确地反映了它的作用,甚至可以让调用者很好地猜测如果您使用非"true"/"false"输入调用它们会发生什么。
  • 非常简单

如果您必须采用 defaultValue 概念,我会坚持使代码尽可能具有可读性,即使以一定长度为代价:

public boolean toBoolean(String value, boolean defaultValue) {
    if ("true".equals(value)) return true;
    if ("false".equals(value)) return false;
    return defaultValue;
}
Run Code Online (Sandbox Code Playgroud)

好的,但是为什么这个方法不应该存在于实用程序库中呢?

一般原则是:“如果发生意外的事情,就在黑暗中大胆尝试一下这意味着什么,然后继续”是 PHP 和 javascript 等语言中比较常见的操作模式。

幸运的是,java 生态系统通常根本不遵守这个原则 - 为此,我给予 java 生态系统和语言很多荣誉,因为这个原则对我来说似乎完全倒退了。

假设有某种方法。给定这个方法的签名并且没有其他信息,无论如何,您给我这个方法的一堆输入,并要求我猜测这个方法应该做什么。如果您询问的几乎所有程序员都得到正确的每个示例输入答案,那么该方法就是名副其实的。

在某些情况下这是不可能的(它的作用非常复杂,您无法用简洁的方法名称来描述它,因此需要阅读文档)。重点并不是所有的方法都应该是这样的,而只是如果一个方法可以是这样的话,它就应该是这样。

这就留下了极端情况。每个人都可以猜到toBoolean("true")返回 true,但如果我问它是什么,那就很棘手了toBoolean("oui")。当然,许多法国程序员会猜测true,一些非法国程序员也会猜测。我提出以下规则:您在规则中得到一个“out”,即程序员应该能够仅根据名称和签名来猜测方法的作用:如果程序员很难猜测的任何输入会导致异常,那就没关系了。

例外的要点是充当一个巨大的红色箭头 - 将调试变成 5 秒的事情(而不是 7 天的徒劳无功的追逐)。想一想:如果它们都很容易被测试捕获,我宁愿解决 100 个错误,并且每个问题需要一分钟,而一个难以测试的错误会影响生产和我的客户,并且需要我一周的时间来解决!)。因此,反过来说:您是 API 设计者,调用者是您的客户。如果您(该toBoolean方法的作者)不确定调用者打算让您做什么(例如,调用者向您提供了字符串"oui"),请不要猜测。扔东西。或者确保方法签名(名称+参数类型)不遗余力地清楚将要发生的情况。

不幸的是,apache 的库往往会犯这个错误。但请注意,java自己的Boolean.parseBoolean也这样做(它进行不区分大小写的检查,其中不区分大小写"true"为真,所有其他字符串为假),所以也许这是时代的标志 - 两者都写得远远超过2几十年前,社区的通用标准从那时起就不断发展。