字符串地址问题
定义字符串时的地址
在java中字符串用String定义,用不同方法定义的字符串储存位置不同,具体如下:
String str1 = "hello";
String str2 = new String("hello");
String str3 = "he"+"llo";
String str4 = new String("he")+new String("llo");
如下图,
str1储存位置在堆上的常量池
str2在队上新建了一个对象,将字符串储存在该位置
str3定义方式会先在常量池中寻找是否存在“hello”字符串,如果存在,指向该地址,反之新建一个“hello”
str4先在堆上建立两个对象存放“he”“llo”,新建一个对象存放两者拼接的值“hello”,str4指向的地址是存放“hello”的地址
String str1 = "hello";
String str2 = "world";
String str3 = "helloworld";
System.out.println(str3 == (str1+str2));
System.out.println(str3 == ("hello"+"world"));
输出结果为false、true,原因如下:
str1,str2,str3均指向变量池中的地址
第一条输出语句中比较的是str3和str1,str2的地址
第二条输出语句中拼接后的字符串为“helloworld”,所以和str3指向的地址是相同的
String str1 = new String("hello");
String str2 = "hello";
String str3 = "he"+new String("llo");
String str4 = "he"+"llo";
char[] array = {'h','e','l','l','o'};
String str5 = new String(array);
向字符串追加值
在java源代码中String类用final修饰,表明String 类是一个不可变类,你不能试图去修改原来的值,如果要新加值,会产生一个新的对象,如下:
String str1 = "abcde";
String str2 = "abcde";
str1 = str1+"fg";
要修改原本字符串的值,还可以用StringBuffer类或StringBuilder类定义字符串,用类中的append方法可以给字符串中追加值,而不创建新的对象,代码如下:
StringBuffer stringBuffer = new StringBuffer("hello");
stringBuffer.append("world");//追加
System.out.println("=============stringBuilder==============");
StringBuilder stringBuilder = new StringBuilder("my");
stringBuilder.append("world");//追加
System.out.println(stringBuilder);
StringBuffer类 有关键词synchronized修饰,表明线程安全,适用于多线程
StringBuilder类只能用于单线程
循环增加值
public void add1(String[] str1) {
String str2 = "";
for(int i = 0; i < str1.length;i++) {
// str2 = str2+str1[i];
StringBuilder stringBuilder = new StringBuilder(str2);
stringBuilder.append(str1[i]);
str2 = stringBuilder.toString();
}
}
public String add2(String[] str) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < str.length; i++) {
stringBuilder.append(str[i]);
}
return stringBuilder.toString();
}
用add1方法将str1的值增加到str2中,但会产生许多对象,影响效率
用add2方法只产生一个对象,一般用此方法增加值
.intern()方法
String string = new String("abcdef").intern();
String string2 = "abcdef";
System.out.println(string == string2);//true
intern()方法就是在创建了对象“abcdef”后,如果常量池中没有该值,则创建堆中对象的引用,此时string,string2指向的地址都是常量池中的地址
String string = new String("abcdef");
string.intern();
String string2 = "abcdef";
System.out.println(string == string2);//false
代码第二行用了intern方法,在常量池中创建了“abcdef”,但string指向的地址还是堆中的地址,string2指向常量池中的地址
String str1 = new String("ab")+new String("cdef");
str1.intern();
String str2 = "abcdef";
//str1.intern();
System.out.println(str1 == str2);//true
当调用str1.intern()时,常量池中没有“abcdef”,所以在常量池中生成堆中对象的引用,常量池的引用和str1引用的地址相同