Java字符串替换和NUL(NULL,ASCII 0)字符?

36

测试别人的代码时,我发现一些 JSP 页面打印出了奇怪的非 ASCII 字符。查看源代码后,我找到了这个片段:

// remove any periods from first name e.g. Mr. John --> Mr John
firstName = firstName.trim().replace('.','\0');

在Java中用空字符替换字符串中的一个字符是否有效?我知道'\0'会终止C字符串。这是否是出现奇怪字符的罪魁祸首?

在Java中,使用空字符替换字符串中的字符是有效的。但是,它可能不会像在C语言中一样终止字符串。如果您试图将空字符插入Java字符串中,它将作为普通字符插入字符串,并且不会影响字符串的长度或任何其他方面。


1
我注意到一些JSP页面打印出了奇怪的非ASCII字符。这个问题的根本原因完全在其他地方。谷歌 “乱码”。 - BalusC
5个回答

91

在Java中,用null字符替换字符串中的一个字符真的有效吗?我知道'\0'会终止C字符串。

这取决于您如何定义“有效”。它是否将目标字符的所有出现替换为'\0'? 绝对可以!

String s = "food".replace('o', '\0');
System.out.println(s.indexOf('\0')); // "1"
System.out.println(s.indexOf('d')); // "3"
System.out.println(s.length()); // "4"
System.out.println(s.hashCode() == 'f'*31*31*31 + 'd'); // "true"

我觉得一切都很正常!indexOf可以找到它,计算长度时也会将其计算在内,它的哈希码计算值为0;这些都符合JLS/API的规定。

但是如果你期望用null字符替换一个字符能从字符串中删除该字符,那么它就不起作用。当然它不会像那样工作。null字符仍然是一个字符!

String s = Character.toString('\0');
System.out.println(s.length()); // "1"
assert s.charAt(0) == 0;

如果你期望使用 null 字符终止一个字符串,那么它也起作用。这在上面的片段中是显而易见的,但在 JLS (10.9. An Array of Characters is Not a String) 中也明确规定:

在 Java 编程语言中,与 C 不同,char 数组不是 StringStringchar 数组都不会以 '\u0000'(NUL 字符)作为终止符。


这是否是出现奇怪字符的罪魁祸首?

现在我们讨论的是完全不同的事情,即字符串在屏幕上的呈现方式。事实上,即使是 "Hello world!" 在使用 dingbats 字体时也会看起来很奇怪。Unicode 字符串在一个区域设置下可能会看起来很奇怪,但在另一个区域设置下却不会。即使包含中文字符的正确渲染的 Unicode 字符串可能对来自格陵兰的人看起来仍然很奇怪。

话虽如此,null 字符可能看起来很奇怪;通常它不是你想要显示的字符。话虽如此,由于 null 字符不是字符串终止符,因此 Java 能够以一种或另一种方式处理它。


现在来解决我们假设的预期效果,即从字符串中删除所有句号,最简单的解决方案是使用 replace(CharSequence, CharSequence) 重载方法。

System.out.println("A.E.I.O.U".replace(".", "")); // AEIOU

这里也提到了replaceAll解决方案,但它需要使用正则表达式,并且需要转义点元字符,因此很可能速度较慢。


2
现在,这是一个很好的解释。而且你也使用了正确的方法来替换这些东西 :) - BalusC

7
可能应该改为
firstName = firstName.trim().replaceAll("\\.", "");

我本来打算用这个来修复它。 - praspa
8
这里的replaceAll就像一把大锤子。你只想用空字符串替换一个字符,根本不需要替换模式。直接使用replace(".", "")即可。 - BalusC

5

我认为应该这样做。要删除这个字符,你应该使用replace(".", "")


4

在Java中用null字符替换字符串中的一个字符,是否有效?

不行。

这会导致奇怪字符出现吗?

很可能是。


2

这确实会导致 "奇怪的字符":

System.out.println( "Mr. Foo".trim().replace('.','\0'));

生成:

Mr[] Foo

在我的Eclipse控制台中,[]显示为一个方框。正如其他人所发表的,使用String.replace()方法。

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