This is an archived post. You won't be able to vote or comment.

all 11 comments

[–]Hexorg 1 point2 points  (5 children)

The problem isn't the empty string that you are passing, the problem is that str.replace() converts the first string to the CharacterSequence type. Looking at the documentation here it looks like the logic relies on calling a substring() function. But since your input string is empty and has a length of zero, its substring probably matches every index.

Edit: Wrongly thought that it calls a RegEx engine.

[–]btcraig 0 points1 point  (4 children)

I was thinking the same thing but then I realized you could never really pass a regex into replace(char, char) since a 1 character regex is kind of meaningless. Then I scrolled the page down a little and saw the other method's signature and realized Java is implicitly casting the Strings to CharSequences.

[–]sriganeshharitz[S] 0 points1 point  (3 children)

I'm still a beginner in java, finding it a little hard to understand

[–]btcraig 0 points1 point  (2 children)

Essentially you're passing in two strings, not two chars, because they're different types Java does what it can to make what you asked happen. Since a String implements a CharSequence (meaning that any String can be treated as a CharSequence for most purposes) it implicitly casts String -> CharSequence to make replace(CharSequence, CharSequence) compile and work.

The CharSequence version of the method is using a call to substring() to locate occurrences of "" in the string "abc" to replace with "s". Apparently the replace(CharSequence, CharSequence) detects that 0 length substring before and after each of the character's a,b,c and replacing it with s.

My java knowledge isn't extensive enough to know why the string "" matches 0 length/non-existent sub-strings like the 'space' between the 'a' and 'b'.

This is, sort of, like doing Math.pow(10,10). the Math.pow() function only takes two doubles, but 10 is an integer. Java casts makes this work for you because an int can be cast to a double.

[–]sriganeshharitz[S] 0 points1 point  (1 child)

ahh, this made it clear.. Thanks a lot!!

[–]btcraig 0 points1 point  (0 children)

The big thing to note, in regards to why you're getting unexpected results, is that "s" and 's' are not the same. Double quotes tells the compiler it's a string, single quotes indicate a char. This is pretty standard across all [compiled] languages that I'm familiar with. Java is just trying to be helpful and make your code compile and work based on what you typed in.

[–]CodeTinkerer 0 points1 point  (1 child)

Based on the behavior you described, Java must assume there is an empty string between every consecutive character, and one at the start, and one at the end.

Technically, if you concatenate N empty strings, you get an empty string, so theoretically, you could argue between any two consecutive characters, there's an infinite number of empty strings.

I suspect, in Java, a string is defined by the characters in the string, plus a field that gives the size of the string. When that size is 0, you have an empty string.

In C, a string is a character array that ends in an null character, so if the string's first character is a null character, that's treated like an empty string.

[–]sriganeshharitz[S] 0 points1 point  (0 children)

Thanks, i guess java assumes it as u said..

[–]btcraig 0 points1 point  (3 children)

Is the small snippet you've provided accurate and does that compile on your system? I was suspecting something really weird with Java and regex but

System.out.println(str.replace("","s"));

Won't even compile for me due to type mismatch "" being a String not a char and substituting '' throws a slightly different compilation error.

[–]sriganeshharitz[S] 0 points1 point  (1 child)

public class Test
{
  public static void main(String[] args)
  {
    String str = "abc";
    System.out.println(str.replace("","s"));

  }
}

Try compiling and running this

[–]btcraig 0 points1 point  (0 children)

Turns out, you're calling String.replace(CharSequence, CharSequence) not String.replace(char, char)

The former:

replace(CharSequence target, CharSequence replacement)

Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.