2017-01-27 139 views
13

我很困惑與代碼空字符串

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'(在字符串中)之後出現這種情況,則應該有兩個'1'進入第二行輸出(一個用於'a'的結尾,另一個用於's'的開始)。

現在我檢查字符串是否在這些鏈接中表示爲char [] In Java, is a String an array of chars?String representation in Java我的答案爲YES。

於是,我就一個空字符''分配給char變量,但它給我一個編譯器錯誤,

無效字符常量

同樣的過程給出了一個編譯器錯誤,當我嘗試在char[]

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

所以我對三件事情感到困惑。

  1. 空字符串如何由char []表示?
  2. 爲什麼我得到上述代碼的輸出?
  3. 字符串s1在第一次初始化時如何在char []中表示?

對不起,如果我在我的問題的任何部分錯了。

+3

我會從'字符串#replaceAll'而不是從預計'字符串替換# ' –

+2

@TimBiegeleisen剛剛經過測試,它實際上產生的結果只是'String#replace' – Enigo

+2

* *如何表示一個空字符串*「 - 'char [] empty = {};' –

回答

5

按照Andy Turner的精彩評論,您撥打String#replace()實際上是使用String#replaceAll()實施的。因此,這裏有一個正則表達式替換。匹配發生在第一個字符之前,字符串中的每個字符之間和最後一個字符之後。

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

您所做的匹配是零長度匹配。在String.replaceAll()中使用的Java正則表達式實現中,其行爲如上例所示,即匹配每個字符間位置以及第一個字符之前和最後一個字符之後的位置。

這裏是一個更詳細地討論的零個長度匹配的參考:http://www.regexguru.com/2008/04/watch-out-for-zero-length-matches/

零寬度或零長度匹配正則表達式匹配不匹配的任何字符。它只匹配字符串中的一個位置。例如。正則表達式\ b在1和1,2之間匹配。

+1

我想我們都可以看到,但問題是**爲什麼**會發生?在字符之間有一個空的'String'的目的是什麼?或者這可能是'String#replace()'方法的缺點? – Dth

+0

So ** @ Tim Biegeleisen **首次初始化時,String s1的char []表示形式是什麼 –

+0

但是不是主體('String.replace(CharSequence,CharSequence)')中的方法實際上應該是根據其JavaDoc,不使用正則表達式來進行匹配? 'replaceAll'方法確實使用了正則表達式,它在JavaDoc中聲明瞭它,但是替換(CharSequence,CharSequence)並沒有提到任何地方的正則表達式,它實際上是說 - 替換這個字符串中與**文本**目標相匹配的每個子字符串序列..._ 。這讓我感到困惑。 – SantiBailors

2

這是因爲它執行了與傳遞給replace()的模式/替換的正則表達式匹配。

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

替換該字符串與指定文字替換序列字面靶 序列匹配的每個子字符串。從字符串到年底, 例如開頭的 置換進行,以「b」的字符串中替換的「aa」,「AAA」將導致 「BA」,而不是「AB」。

參數:

目標炭的值序列 被替換

置換焦炭的置換值序列

返回:將得到的字符串

時拋出如果目標 或者替換爲空。

由於: 1.5

請詳細閱讀以下鏈接...(也可以通過源代碼瀏覽)。

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java#String.replace%28java.lang.CharSequence%2Cjava.lang.CharSequence%29

一個正則表達式,如「」將字符串中的每一個可能的空字符串相匹配。在這種情況下,恰好是在開始和結束處以及在字符串中的每個字符之後的每個空白空間。

+0

引用中的文檔引用了哪個方法(_將該字符串與給定的正則表達式..._的匹配分開)? – SantiBailors

+1

抱歉,錯誤(草率)複製和粘貼。糾正。 –

+1

謝謝,所以現在它是'replace(CharSequence,CharSequence)'的JavaDoc。這突出了問題(在我看來):方法的文檔根本沒有提及與regex的匹配,而'replaceAll'的文檔卻沒有。 – SantiBailors

6

徒添添Biegeleisen回答一些更多的解釋。

從Java 8中,replace方法在java.lang.String中類的代碼

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 
+1

感謝您的偵探+1 –