【问题标题】:Is StringUtils.isNumeric() method specification logically correct?StringUtils.isNumeric() 方法规范在逻辑上是否正确?
【发布时间】:2020-04-18 02:08:40
【问题描述】:

Apache 的 StringUtils.isNumeric() 方法规范说:
检查字符串是否仅包含 unicode 数字。小数点不是 unicode 数字并返回 falseNull 将返回 false。空的String ("") 将返回true

这在逻辑上正确吗? 为什么他们将空字符串视为数字?

【问题讨论】:

    标签: java string apache-commons-lang


    【解决方案1】:

    3.0 中的行为发生了变化。来自What's new in Commons Lang 3.0?

    StringUtils.isAlpha、isNumeric 和 isAlphanumeric 现在在传递空字符串时都返回 false。以前他们返回真。

    保留下面的旧答案,以供参考和 3.0 之前的用户。


    这在逻辑上正确吗?

    我们有

    1. 方法的行为
    2. 方法的文档(通常被视为规范或合同)
    3. 方法的名称

    在这种情况下 1 和 2 彼此一致;空字符串中的所有字符都是 unicode 数字。 (或者等效地,空字符串中的任何字符都不是 not unicode 数字。)这就是逻辑学家所说的 vacuously true 并且有点违反直觉。这就像说我公寓里所有的大象都是绿色的。这是真的,因为我的公寓里没有大象。

    然而,第 3 项(方法的名称)自然地被解释为如果给定字符串表示数字则返回 true 的方法。

    所以,要么是文档和实现错误,要么是命名错误。没有正确或错误的答案。

    提交了一个错误here。维护者认为这是预期的行为。

    为什么他们将空字符串视为数字?

    虽然方法的名称可能会让您相信该方法应该只对表示数字的字符串返回 true,但规范实际上说它应该在字符串仅包含 unicode 数字时返回 true。

    你说,

    我很困惑,因为规范说:“检查字符串是否只包含 unicode 数字。”我没有看到 "" 包含数字....

    请注意,空字符串不包含除 unicode 数字以外的任何内容。因此该方法返回 true。

    【讨论】:

    • 你也可以争辩说空字符串中的字符都不是unicode数字。
    • 是的!确切地!我也没有在空字符串中看到任何 unicode 数字!
    • 在我看来这可能是用于输入验证:您可以进行单独的“是数字”和“为空”验证检查,根据这个定义,这两者是完全正交的。
    • 嗯......从这个角度来看:“这就是逻辑学家所说的“虚无真实”。这就像说我公寓里的所有大象都是绿色的。这是真的,因为里面没有大象我的公寓。” - 规范是正确的。但这对我来说非常有争议......如果我说:“这是真的,约瑟夫是百万富翁”并且如果约瑟夫根本没有钱......有趣:)
    • 是...这是非常正确的陈述“一个字符串只包含 unicode 数字,当且仅当它不包含非 unicode 数字。空字符串显然不包含非 unicode 数字,因此它仅包含 unicode 数字。”... 但也可以说“字符串仅包含非数字字符,当且仅当它不包含数字字符时,因此“” - 包含非数字字符”:) 这样的混淆至于我:)
    【解决方案2】:

    问这个问题的不只是我 :) 人们在 Apache 的 Jira 中打开了这个缺陷: https://issues.apache.org/jira/browse/LANG-428

    他们没有修复就关闭了,只是为了保持向后兼容性(遵循方法规范)。

    但是每个人都同意方法的当前行为是错误的。

    【讨论】:

    • 引用您提供的链接:“空字符串没有字符,因此不能包含非法字符。”....因此它是可接受的行为。
    • 但它也不包含合法字符。一个人在 cmets 中问了一个合理的问题:“也许这个方法可以更好地命名为 isNotNonNumeric()?”我100%同意他。我的意思是......如果写“17”+“256” - 一切都清楚......但是“”+“256”......好吧......空字符串不应该被视为某个数字,无论是0还是1 或其他。
    • 我同意。该函数的名称有点误导和不幸。例如,它可以按照您的建议被称为 containsOnlyDigitsisNotNonNumeric。关于空字符串,有一些这样的惊喜。例如,您会说空字符串曾经包含任何内容吗?也就是说,"".contains(.....) 是否应该评估为真?嗯,确实如此! (我将把它作为练习留给你,让你弄清楚如何;)你只需要习惯这些,我们应该说空字符串的“反直觉属性”。
    • 他们至少可以弃用它并将其替换为isActuallyNumeric() 或其他东西。
    【解决方案3】:

    java.lang.Integer.parseInt("") 将失败。

    这不是逻辑问题。这也不是常识问题——没有任何数字是由无符号表示的。为什么空字符串应该代表 0 没有强有力的论据。

    如果方法名是containsOnlyNumeric(),根据我们的数学教科书,“”自然返回true。但是,方法名称是isNumeric(),“”的处理并不自然。此外,null 没有明显的理由返回 false。我会为 null 抛出异常。

    但它就是这样,它有据可查,你还能要求什么?

    【讨论】:

      【解决方案4】:

      首先检查字符串是否为空()的条件。

      if(StringUtils.isNotEmpty(str) && StringUtils.isNumeric(str)) {
      
      }
      

      那么你的问题就解决了。

      但还有一个问题是您传递负值,例如

      str = "-1";
      

      StringUtils.isNumeric(str) 这将是错误的。

      您需要注意这种情况。

      【讨论】:

      • 也许你想在你的第一个 sn-p 中使用isNotEmpty
      【解决方案5】:

      还有另一种解决方案。 NumberUtils.isNumber 这会检查它是否是 Long、Double、Integer 中的数字。

      希望有帮助

      【讨论】:

        【解决方案6】:

        从 Commons Lang 3.5 开始,NumberUtils.isCreatable 是执行此操作的方法。有关更详细的说明,请参阅this answer

        【讨论】:

          猜你喜欢
          • 2013-03-25
          • 1970-01-01
          • 2013-12-25
          • 2019-07-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-20
          相关资源
          最近更新 更多