Java 非空字符串中的空字符串

Java 非空字符串中的空字符串,java,arrays,string,char,Java,Arrays,String,Char,我被一个密码弄糊涂了 public class StringReplaceWithEmptyString { public static void main(String[] args) { String s1 = "asdfgh"; System.out.println(s1); s1 = s1.replace("", "1"); System.out.println(s1); } } 输出为: a

我被一个密码弄糊涂了

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'
(字符串中)之后出现这种情况,那么在输出的第二行应该有两个
'1'
(一个用于'a'的结尾,另一个用于's'的开头)

现在我检查了字符串在这些链接中是否表示为char[],得到的答案是肯定的

因此,我尝试将一个空字符
'
分配给
char
变量,但它给了我一个编译器错误

无效字符常量

当我尝试使用
char[]

char[] c = {'','a','','s'};  // CTE
所以我对三件事感到困惑

  • 空字符串如何用char[]表示
  • 为什么我会得到上面代码的输出
  • 首次初始化字符串s1时,字符串s1如何在char[]中表示

  • 如果我在问题的任何部分都错了,很抱歉。

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

    ^ a | s | d | f | g | h|$
    ^此管道和每个管道都与空字符串“”匹配
    
    您正在进行的匹配是零长度匹配。在
    String.replaceAll()
    中使用的Java正则表达式实现中,其行为如上面的示例所示,即匹配每个字符间位置以及第一个字符之前和最后一个字符之后的位置

    下面是一个更详细地讨论零长度匹配的参考:

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


    这是因为它对传递给replace()的模式/替换进行正则表达式匹配

    替换此字符串中与文字目标匹配的每个子字符串 具有指定的文字替换序列的序列。这个 例如,替换从字符串的开头一直进行到结尾 例如,将字符串“aaa”中的“aa”替换为“b”将导致 “ba”而不是“ab”

    参数:

    以字符值序列为目标 取而代之

    替换字符值的替换顺序

    返回:结果字符串

    抛出:如果目标为NullPointerException 或替换为空

    自: 1.5

    请在下面的链接中阅读更多。。。(也可以浏览源代码)


    诸如“”之类的正则表达式将匹配字符串中所有可能的空字符串。在这种情况下,它恰好是字符串中每个字符开头、结尾和后面的每个空格。

    只是对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
    

    我本可以从
    String#replaceAll
    中得到这个结果,但不是从刚刚测试的
    String#replace
    @TimBiegeleisen中得到的,它实际上是通过
    String#replace
    “如何表示空字符串”
    char[]empty={}
    IMO询问一个字符串中有多少空字符串有点像被零除。我很惊讶它只插入一个
    1
    ,而不是零。毕竟,
    “ab”==“a”+“b”==“a”+“b”
    等等;所以说他们之间有一个空字符串似乎。。。武断。我想我们都可以看到,但问题是为什么会发生这种情况?在字符之间有一个空的
    字符串
    ,目的是什么?或者这可能是
    String#replace()
    方法的一个错误?那么@Tim Biegeleisen当字符串s1第一次初始化时,它的char[]表示是什么,但是根据它的JavaDoc,subject(
    String.replace(CharSequence,CharSequence)
    )中的方法不应该在不使用正则表达式的情况下进行匹配吗?
    replaceAll
    方法确实使用正则表达式,并且在其JavaDoc中声明了这一点,但是
    replace(CharSequence,CharSequence)
    在任何地方都没有提到正则表达式,它实际上表示替换这个字符串中与文本目标序列匹配的每个子字符串。“是的,这也是我的想法。谷歌的Java架构师安迪·特纳(Andy Turner)似乎认为
    replaceAll
    是在幕后使用的。在任何情况下,该行为都是零长度正则表达式替换。
    ^$
    表示整个字符串中没有任何内容,因此只有空字符串匹配。搜索
    无界意味着查找字符串中每个字符之间的边界。有意义吗?感谢您的检测工作+1您的报价中的文档引用了哪种方法(将此字符串围绕给定正则表达式的匹配项拆分…)?抱歉,复制和粘贴错误(仓促)。更正。谢谢,现在是
    replace(CharSequence,CharSequence)
    的JavaDoc。这突出了一个问题(在我看来):该方法的文档根本没有提到与regex的匹配,而
    replaceAll
    的文档提到了。
    1a1s1d1f1g1h1