String:内部用final的char数组实现,是一个final类,也就是说不能被继承,所以他一旦被实例化就无法被修改。
String需要特别注意的有:
-
replaceFirst、replaceAll、replace区别
-
String 对"+" 的重载
-
String.valueOf和Integer.toString的区别
1.replaceFirst、replaceAll、replace区别
public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
对比这三个方法的源码可得,String.replaceFirst和String.replaceAll用的是同一种正则规则compile(String regex)初始化,而replace用的是compile(String regex,int flags),替换方法String.replaceAll和String.replace都是用的Martcher.replaceAll(String) ,而String.replaceFirst用的是Martcher.replaceFirst(String)方法。
/**
* Compiles the given regular expression into a pattern with the given
* flags.
* 使用给定的标志将给定的正则表达式编译为模式。
* @param regex
* The expression to be compiled
*
* @param flags
* Match flags, a bit mask that may include* 标志如下:
* {@link #CASE_INSENSITIVE}, {@link #MULTILINE}, {@link #DOTALL},
* {@link #UNICODE_CASE}, {@link #CANON_EQ}, {@link #UNIX_LINES},
* {@link #LITERAL}, {@link #UNICODE_CHARACTER_CLASS}
* and {@link #COMMENTS}
*
* @return the given regular expression compiled into a pattern with the given flags
*/
public static Pattern compile(String regex, int flags) {
return new Pattern(regex, flags);
}
String.replace()使用的是Pattern.LITERAL。
/**
* Enables literal parsing of the pattern.
*
* <p> When this flag is specified then the input string that specifies
* the pattern is treated as a sequence of literal characters.
* Metacharacters or escape sequences in the input sequence will be
* given no special meaning.
*
* <p>The flags CASE_INSENSITIVE and UNICODE_CASE retain their impact on
* matching when used in conjunction with this flag. The other flags
* become superfluous.
*
* <p> There is no embedded flag character for enabling literal parsing.
* @since 1.5
*/
public static final int LITERAL = 0x10;
由注释可得,输入序列中的元字符或转义序列将没有特殊含义。即String.replace正则表达式不起作用,被强转为普通的字符串。
而String.replaceFirst和String.replaceAll使用的是常规Pattern构造函数,所以正则表达式是会起作用。
接下来再看看Matcher.replaceAll,Matcher.replaceFirst源码
public String replaceAll(String replacement) {
reset();
boolean result = find();
if (result) {
StringBuffer sb = new StringBuffer();
do {
appendReplacement(sb, replacement);
result = find();
} while (result);
appendTail(sb);
return sb.toString();
}
return text.toString();
}public String replaceFirst(String replacement) {
if (replacement == null)
throw new NullPointerException("replacement");
reset();
if (!find())
return text.toString();
StringBuffer sb = new StringBuffer();
appendReplacement(sb, replacement);
appendTail(sb);
return sb.toString();
}
明显,Matcher.replaceAll使用do-while循环替换匹配的字符串,而Matcher.replaceFirst只做了一次匹配替换。即String.replaceAll和String.replace将会替换字符串中所有能匹配上的字符串,而String.replaceFirst只会替换第一次匹配上的字符串。
2.String 对"+" 的重载
文章开头说过,String是一个final类,用final char[]实现,所以一旦赋值,String将不可变。所以String类中每一个修改String的方法其实都是生成了新的String对象。
String a = "create " + "a "; //①
String string = a + "final " + "String!"; //②
①在编译期就会直接编译成String a = "create a ";
②在编译期会编译成new StringBuilder().append("create a ").append("final ").append("String").toString();
String result = "";
for(int i = 0; i < strArray.length; i++)
result += strArray[i]; //当strArraylist很大时,很产生很多的StringBuilder对象,因为每一个循环都会创建一个。
StringBuilder result1 = new StringBuilder();
for(int i = 0; i < strArray.length; i++)
result1.append(strArray[i]); //正确用法
3.String.valueOf和Integer.toString的区别
String.valueOf()方法可以将各种类型转换成String,内部实现了多种类型的String的处理方式。
public static String valueOf(boolean b) {
return b ? "true" : "false";
}public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}public static String valueOf(char c) {
char data[] = {c};
return new String(data, true);
}public static String valueOf(int i) {
return Integer.toString(i);
}......
由源码得String.valueOf(int)内部其实是调用了Integer.toString();