Java运行时会维护一个String Pool(String池), 也叫“字符串区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。
字符串的拼接
一般的字符串我们使用+拼接,例如
String s = “abc” + “d”;
输出的结果是"abcd"
String s1 = "a";
String s2 = "b";
String s3 = s1+s2;
对于字符串变量的相加(s1 + s2),本质上是先创建 new StringBuilder(),调用 append 方法进行拼接,最后调用 toString(),实际上还是 new String()。
这里要说到字符串的不可改变,并不是说这个字符串不能进行加减,而是字符串的内容一旦申明,就不能被改变,在声明的时候,String就会创建一个相应的对象,例如s1创建“a”,s2创建“b”,这是在已经在String池出现的,后面的s3的+,会在String池中新开辟一个“ab”。或者换一种说法,哪怕我改变了s1的值,String池中的“a”还是存在的。
做类似于+=的操作后,实际上是指向了新的地址,原来的空间里面的内容还是没有改变。
StringBuffer和StringBuilder
这两个都是用来拼接字符串的,但是有区别。
对于经常变化的字符串,我们推荐使用StringBuffer,下面是它的使用方法
StringBuffer buffer = new StringBuffer();
buffer.append("hello");
buffer.append("world");
创建StringBuffer,然后用append你要拼接的字符串
StringBuffer和StringBuilder的区别
StringBuilder与StringBuffer的用法完全一致,唯一的区别是StringBuffer是线程安全的,而StringBuilder不是线程安全的。所以StringBuilder的性能要比StringBuffer要好。
单线程推荐使用StringBuilder,多线程使用StringBuffer。
就比如上面,字符串需要经常变化就用StringBuffer,而如果用的比较少,或者就使用一次,用来拼接循环的,比如下面这个,我只是想要字符串的循环拼接,就最好使用StringBuilder。
StringBuilder sb = new StringBuilder();
for (Map.Entry<Character,Integer> entry : list) {
Integer value = entry.getValue();
sb.append(entry.getKey()).append("(").append(value).append(")\t");
}
字符串的比较
1、”==”表示判断该两个字符串是否为同一对象,即在内存中的地址是否一样。如果一样则返回true 否则返回false; 和我们通常的是否为同一对象的是一样的。
2、boolean equals(ObjectanObject) 将此字符串与指定的对象比较。注意此时比较的是内容是否相等(字符串类对此方法进行了覆写)。
例如:
s1和s2的指向地址不一样,s1指向堆中的地址,而s2指向String池中的地址,但是它们的内容相等,所以equals比较会是true。
String s1= new String(“abc”); String s2 = “abc”
s1==s2 //false
s1.equals(s2); //true
附上关于字符串String的常用方法
(比较重要的我会加粗)
1.字符与字符串:
public String(char[] value)--------------------------全部字符数组变为String类
public String(char[] value,int offset,int count)-----部分字符数组变为String
public char charAt(int index)------------------------返回指定位置上的字符
public char[] toCharArray()--------------------------字符串变为字符数组
2.字节数组与字符串:
public String(byte[] bytes)--------------------------全部字节数组变为字符串
public String(byte[] bytes,int offset,int length)----部分字节数组变为字符串
public byte[] getBytes()-----------------------------字符串变为字节数组
public byte[] getBytes(String charsetName)throws UnsupportedEncodingException-----------------转码
3.字符串比较:
public boolean equals(String anObject)---------------字符串内容的比较,区分大小写
public boolean equalsIgnoreCase(String anotherString)不区分大小写完成字符串内容的比较
public int compareTo(String anotherString)-----------判断字符串的大于,小于,等于
4.字符索引:
public boolean contains(String s)--------------------判断指定的子字符串是否存在
public int indexOf(String str)-----------------------从头查找指定的子字符串是否存在,存在则返回字符串第一次出现的的索引,不存在则返回-1
public int indexOf(String str,int fromIndex)---------从指定位置开始检索,没找到则返回-1
public int lastIndexOf(String str)-------------------从后向前查找字符串的位置
public int lastIndexOf(String str,int fromIndex)-----从指定位置开始由后向前查找
public boolean startsWith(String prefix)-------------判断是否以指定字符串开头
public boolean endsWith(Sting suffix)----------------判断是否以指定字符串结尾
5.字符串替换:
public String replaceAll(String regex,String replacement)满足条件的内容全部替换
public String replaceFirst(String regex,String replacement)替换第一个满足条件的内容
6.字符串截取:
public String subString(int beginindex)--------------从头截取到尾
public String subString(int beginindex,int endindex)-截取中间的部分内容
7.字符串拆分: public String[] split(String regex)------------------全拆分
public String[] split(String regex,int limit)--------拆分成指定的个数
8.其他方法:
public boolean isEmpty()-----------------------------判断是否是空字符串,不是null
public int length()----------------------------------取得字符串内容的长度
public String toLowerCase()--------------------------所有内容变为小写
public String toUpperCase()--------------------------所有内容变为大写
public String trim()--------------------------------去掉左右空格,中间的无法去掉