非空字符串中的空字符串

2022-09-04 20:49:19

我对代码感到困惑

public class StringReplaceWithEmptyString 
{
    public static void main(String[] args) 
    {
        String s1 = "asdfgh";
        System.out.println(s1);
        s1 = s1.replace("", "1");
        System.out.println(s1); 
    }
}

输出为:

asdfgh
1a1s1d1f1g1h1

所以我的第一个意见是字符串中的每个字符在两侧都有一个空字符串。但是,如果是这种情况,则在(在字符串中)之后,输出的第二行中应该有两个(一个用于“a”的末尾,第二个用于“s”的开头)。""'a''1'

现在我检查了这些链接中的字符串是否表示为char[]在Java中,String是字符数组吗?Java中的字符串表示我得到的答案是YES。

所以我试图为变量分配一个空字符,但它给了我一个编译器错误,''char

字符常量无效

当我尝试时,相同的过程给出了编译器错误char[]

char[] c = {'','a','','s'};  // CTE

所以我对三件事感到困惑。

  1. 空字符串如何由 char[] 表示?
  2. 为什么我得到上述代码的输出?
  3. String s1 在首次初始化时如何用 char[] 表示?

对不起,如果我的问题的任何部分都错了。


答案 1

只是为Tim Biegeleisen的答案添加更多的解释。

从Java 8开始,java.lang.String类中的方法代码是replace

public String replace(CharSequence target, CharSequence replacement) {
        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}

在这里,您可以清楚地看到字符串被正则表达式模式匹配器替换,并且在正则表达式“”中由零长度字符标识,并且它存在于任何非零长度字符周围。

因此,在幕后,您的代码将按如下方式执行

Pattern.compile("".toString(), Pattern.LITERAL).matcher("asdfgh").replaceAll(Matcher.quoteReplacement("1".toString()));

输出变为

1a1s1d1f1g1h1

答案 2

与Andy Turner的精彩评论一起,您对的调用实际上是使用.因此,这里发生了正则表达式替换。匹配发生在第一个字符之前、字符串中每个字符之间以及最后一个字符之后。String#replace()String#replaceAll()

^|a|s|d|f|g|h|$
 ^ this and every pipe matches to empty string ""

您正在进行的匹配是零长度匹配。在 中使用的 Java 正则表达式实现中,其行为如上例所示,即匹配每个字符间位置以及第一个字符之前和之后的位置。String.replaceAll()

下面是一个更详细地讨论零长度匹配的参考:http://www.regexguru.com/2008/04/watch-out-for-zero-length-matches/

零宽度或零长度匹配是与任何字符都不匹配的正则表达式匹配。它仅匹配字符串中的某个位置。例如,正则表达式 \b 在 1,2 中匹配 1 和 。