String字符串替换的一个诡异问题

将字符串中的数字替换成$D 

但愿将如下字符串中的数字替换为$D字符 
java

引用正则表达式


   ab1cd2 
app



咱们知道String有3个用于字符替换的方法,分别是: 
spa

  • String replace(CharSequence target, CharSequence replacement):将字符串中出现的target替换成replacement;.net

  • String replaceAll(String regex, String replacement):regex是一个正则表达式,将字符串中匹配的子字符串替换为replacement;设计

  • String replaceFirst(String regex, String replacement):和replaceAll(..)相似,只不过只替换第一个出现的地方。orm



因为咱们但愿全部替换,所以使用以下方法: 
代码1:StringReplaceTest 
事件

Java代码 开发

  1. public class StringReplaceTest {  字符串

  2.     @Test   

  3.     public void testReplace(){  

  4.         String str = "ab1cd2";  

  5.         System.out.println(str.replaceAll(str, "$D"));  

  6.     }  

  7. }  



小小代码现诡异异常 

运行StringReplaceTest,控制台却没有返回正确的结果,而是抛出以下的异常: 

引用


java.lang.IllegalArgumentException: Illegal group reference 
at java.util.regex.Matcher.appendReplacement(Matcher.java:713) 
at java.util.regex.Matcher.replaceAll(Matcher.java:813) 
at java.lang.String.replaceAll(String.java:2189) 
at com.hsit.euler.qform.engine.jdbc.StringReplaceTest.testReplace(StringReplaceTest.java:17) 



比较诡异吧,难道是JDK的BUG??? 

剥丝入茧,原来如此 

其实String的replaceAll()及replaceFirst()方法内部都是调用java.util.regex.Matcher的String replaceAll(String replacement)方法的。让咱们把刚才的诧异放在一边,好好看下这个方法的Javadoc,掐头去尾,主要是这段: 

引用


     * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in 
     * the replacement string may cause the results to be different than if it 
     * were being treated as a literal replacement string. Dollar signs may be 
     * treated as references to captured subsequences as described above, and 
     * backslashes are used to escape literal characters in the replacement 
     * string. 



原来是咱们的替换目标串中包含了$这个特殊的字符,由于替换串使用这个引用正则表达式匹配的组,$0表明匹配项,$1表明第1个匹配分组,$1表明第2个匹配分组--终于真相大白了,是咱们闯了雷区了 

来看一个例子加深一个印象: 

Java代码 

  1. @Test   

  2. public void testReplace2(){  

  3.     String str = "刘备是张飞的小弟";  

  4.     System.out.println(str.replaceAll("(刘备)是(张飞)""$2是$1"));  

  5.     //=>张飞是刘备的小弟  

  6. }  



李鬼出来,李逹进去 
李鬼现形,处理起来天然简单: 

Java代码 

  1. @Test   

  2. public void testReplace(){  

  3.     String str = "ab1cd2";  

  4.     System.out.println(str.replaceAll(str, "\\$D"));  

  5.     //=>ab$Dcd$D  

  6. }  




小评一下 

若是JDK能够再分析一下$,将$N即N是数字时才对其进行特殊处理,不然就不当成特殊字符,是否是更好一些呢? 

也许这样并很差,必须这样形成Matcher方法为了这个小几率事件作不少复杂的检查,结果是得不偿失的。仍是遇到特殊字符报异常,让开发者去处理更好些,这是28原来取舍得当的一个API设计。既然$是特殊字符,开发者绕过便可。

相关文章
相关标签/搜索