为什么Java中的字符串以""开头?

20

可能重复:
为什么"abcd".startsWith("")返回true?

在调试某些代码时,我发现我的验证逻辑使用String类的.startsWith()方法来检查一个字符串是否以空白字符开头。

考虑以下情况:

public static void main(String args[])
{

    String s = "Hello";
    if (s.startsWith(""))
    {
        System.out.println("It does");
    }

}

它打印出It does

我的问题是,为什么字符串以空字符开头?我假设在内部,字符串本质上是字符数组,但在这种情况下,我认为第一个字符应该是H

可以有人解释一下吗?


8
“Blank”字符是指不打印任何可见符号的Unicode字符,例如空格、制表符和换行符等。 - PP.
11
@PP - 不要挑剔。1)许多SO用户的母语不是英语。2)空白是空格的可接受替代品。3)你真的知道他/他们的意思。 - Stephen C
6
@Stephen C 绝对不是的。这不是关于"英语"的问题。这是关于常见IT角色名称的问题。Blank并没有明确定义。空格、制表符、回车、换行都是有明确定义的空白字符名称。Blank - 是一个概括性的术语。 - PP.
2
为什么"abcd".startswith返回True的副本? - Peter Lawrey
显示剩余2条评论
8个回答

40

""表示一个没有字符的空字符串。除了空格或空字符(null character),不存在“空字符”,如果你指的是它们中的任意一种,那也不是空字符串。

你可以将一个字符串看作以无数个空字符串开头,就像你可以将一个数字看作以无数个前导零开始而不改变其含义。

1 = ...00001
"foo" = ... + "" + "" + "" + "foo"

字符串也以无限数量的空字符串结尾(与带有零的十进制数相同):

1 = 001.000000...
"foo" = "foo" + "" + "" + "" + ...

2
为了使类比完全对应,您应该使用1.0,这样在末尾添加零也没有影响。 :) - HostileFork says dont trust SE
2
@Justin,我相信Cameron更多是在指一种抽象概念(即在数学中1 = ...0000001 = 1.00000000...等等)。一个提示是"foo" = "foo"在Java中是非法的。他实际上会使用"foo" == "foo"。 - Yanick Rochon
4
前导零没有影响,但是我的老化学教授在末尾的零上大做文章...称它们为有效数字或其他类似的傻事 :) - BigMac66
3
说实话,关于有效数字的争论对数学本身没有影响。有效数字是基于测量精度而确定的,而这并不是大多数数学中使用的概念。在数学中的标准观点是1=1.0=1.00等等。 - Zoe
1
@Cameron:我还是喜欢它;-)。我想到了以下类比:空字符串有点像液体胶水。你在左右两边放置一些东西,将字符串粘贴到引号上。你需要在字符之间使用胶水,以防止字符串分裂。而且像胶水一样,空字符串是一个不确定的物质,你无法计算它,但你总是可以将其分成更多的空字符串。 - ollb
显示剩余9条评论

11

似乎您的代码存在误解。您的语句 s.startsWith("") 检查字符串是否以空字符串开头(而不是空白字符)。这可能是一个奇怪的实现选择,无论如何,所有字符串都会告诉你它们以空字符串开头。

此外,请注意,空格字符将是字符串 " ",与您的空字符串""不同。


7
"

你知道吗,“Hello” 以 "" 开始,也以 "H" 开始,以 "He" 开始,以 "Hel" 开始……看到了吗?

"

5

那个 "" 不是空格,而是空字符串。我猜 API 是在问这是不是那个字符串的子串。而长度为零的空字符串是所有字符串的子串。


4
空字符串("")基本上“满足”每个字符串。在您的示例中,Java 调用
s.startsWith(""); 

为了

s.startsWith("", 0);

这实质上遵循了“空元素(字符串)满足其约束(你的字符串语句)”的原则。

来自 String.java

/**
     * Tests if the substring of this string beginning at the
     * specified index starts with the specified prefix.
     *
     * @param   prefix    the prefix.
     * @param   toffset   where to begin looking in this string.
     * @return  <code>true</code> if the character sequence represented by the
     *          argument is a prefix of the substring of this object starting
     *          at index <code>toffset</code>; <code>false</code> otherwise.
     *          The result is <code>false</code> if <code>toffset</code> is
     *          negative or greater than the length of this
     *          <code>String</code> object; otherwise the result is the same
     *          as the result of the expression
     *          <pre>
     *          this.substring(toffset).startsWith(prefix)
     *          </pre>
     */
    public boolean startsWith(String prefix, int toffset) {
    char ta[] = value;
    int to = offset + toffset;
    char pa[] = prefix.value;
    int po = prefix.offset;
    int pc = prefix.count;
    // Note: toffset might be near -1>>>1.
    if ((toffset < 0) || (toffset > count - pc)) {
        return false;
    }
    while (--pc >= 0) {
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    return true;
    } 

这是我最喜欢的答案。+1。它基本上说字符串“起始于”空字符串,因为String.startsWith是这样编码的。上面的哲学答案都没有证明字符串以空字符串开头是Java中故意设计的选择还是仅仅是String.startsWith实现的偶然结果。在这一点得到确认之前,这个讨论只能是学术性的。 - Randall Cook

4
对于已经学过自动机理论的人来说,这是有道理的,因为空字符串ε是任何字符串的子串,也是连接恒等元素,即:

对于所有字符串x,ε + x = x,并且x + ε = x

所以,是的,每个字符串都“以”空字符串开头。还要注意(正如许多其他人所说),空字符串与空格或空字符不同。


2
一个空白是指 (" "),与空字符串不同。空格是一个字符,而空字符串则没有任何字符。

听到Java程序员称空格为“blanks”真是有趣。请问制表符是什么,也是“blank”吗? - PP.
@PP:我使用了你的术语,更准确的说法可能是指空格和制表符。 - Nathan Hughes

0

一个空字符串并不是一个空白字符。假设你的问题涉及到空字符串,我猜他们决定保持原样,但这似乎很奇怪。他们本可以检查长度,但他们没有这么做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接