个人笔记。
String可以说是Java中最常见的词之一,与他相关的还是StringBuffer和StringBuild,这俩之后再说,现在先说说String即字符串。Java之中万物皆对象,String也不例外。而且Java中的String是不可变的。
1.关于String不可变我当初刚学java是存有疑问
String s = "aaa"; s="bbb"; print.out(s); //输出bbb
这段代码里String s明明发生改变,为啥说String 不可变。 在这里解释一下,这里变的只是引用 ,而非改变堆内存中的实际值。例如:
String s = "aaa"; String s2 = s.replace("a","b"); out.print(s2); //输出bbb out.print(s1); //输出aaa
这里可以看出replace方法会产生一个新字符串,而原字符串并没有发生改变。下面从源码角度来分析为什么String对象是不可变的。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; }
打开String源码,可以看到String是个final类,表明它不可继承,用于存储值的char数组也是final类型,表明它不可被改变,但仅用final还不够,因为final修饰的数组虽然不可改变引用,但其本身值是可变。例如:final char value[] = {1,2,3}; value[1] = 4; 这时数组内值变为{1,4,3}。为了防止这种情况,Sun公司就把String类设置为不可继承,并在char数组前用private修饰,并且小心的编写String类的所有方法,保证每个方法都没有改动数组的值。
上文有提String类的所有方法都没改动Array都值,下面就来详细说明一下。
以replace 方法为例
public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } return new String(buf, true); } } return this; }
可以发现如果oldchar!= newchar 则会返回一个新的String对象。
3.字符串比较。
equals(str) 和“==”的区别,equals方法是比较两个字符串的内容是否相等,“==”是比较两个字符串在内存中地址是否是同一个引用。
常用比较方法:equals(str) 和equalsIgnoreCase(str) ,两个方法同为比较,最大的区别就在于一个区分大小写,一个忽略大小写。