String是常量,string类是用final修饰的,其对象一旦创建不能修改
string是引用类型,栈内存中存放的是引用地址,引用的值存放在堆内存中。
修改string实际是在堆内存中创建了新的string对象然后指向引用地址。
string str = "yuwei";
str = "yuxinhua";
第一行,栈中创建一个str,在堆内存字符串常量池中寻找是否有"yuwei"这个字符串内容,如果有则str直接指向这个内容,没有则在常量池中新建这个内容yuwei,指向str;
第二行,同样先寻找常量池中是否有yuxinhua这个字符串,有则(没有则创建)str引用不在指向yuwei,重新指向yuxinhua这个字符串。
通过string str = 常量;创建string对象时会先在字符串常量池寻找是否有这个字符串,有则指向这个地址,没有则创建后指向这个地址。
常量字符串的"+"操作:编译阶段会直接合成一个字符串,例如string str = "yu"+"wei";编译的时候直接合成语句string str = "yuwei";于是去常量池中寻找是否存在yuwei。从而进行创建或引用。
对于final修饰的字符串。编译期间直接进行了常量转换
final string a = "yu";
final string b = "wei";
string str = a + b;
因为a和b是常量字符串,在编译的时候,第三条语句直接替换成了string str = "yu"+"wei";也就是string str = "yuwei"。直接去常量池中师傅存在yuwei。
string.intern();将字符串添加到常量池中
java7之前:调用一个string对象intern()方法会先在字符串常量池中找是否有这个字符串,如果有则返回其地址(字符串常量池中地址)。
如果没有则创建一个该字符串副本,放到字符串常量池中,返回字符串在常量池中地址。
java7开始:如果没有则是把该字符串在堆中对应的地址复制到字符串常量池中,不再是放进去一个字符串副本。
String str1 = new String("yu")+new String("wei");
String str2 = "yuwei";
str1.intern();
System.out.print(str1==str2);//false
String str1 = new String("yu")+new String("wei");
str1.intern();
String str2 = "yuwei";
System.out.print(str1==str2);//true
startswith():判断当前字符串是否是与另一个指定的字符串开头。
indexOf():返回指定字符或者字符串在字符串中第一次出现地方的索引,如果没有则返回-1.
string字符串拼接三种方式:
1、“+”操作符
String对象后面跟着一个"+"时,不管"+"后面时什么数据类型,都会转化成字符串(调用该对象的toString()方法),string + 实际是stringbuilder的append()方法完成的。
str += "a"相当于 str=new stringbuilder(str).append("a").tostring();这会产生一个新的str对象,指向原来str对象在栈中的引用地址。
变慢的原因在new stringbuilder()和tostring()。效率低下。
当"+"连接的是两个常量时,效率高。
string = "yu"+"wei";
或者
final string a = "yuwei";
final string b = "yuxinhua";
string c = a+b;
这两种情况下使用“+”操作符效率才高。
2、concat 方式
当两个变量都是String类型而且部位null时,可以使用concat。理论上,此拼接效率最高
3、append()方式
stringbuilder和stringbuffer使用append()方法追加字符串。在原有对象的基础上追加而不是新建对象,在使用tostring方法返回string对象。stringbuilder线程不安全,stringbuffer反之。
三种方法效率:append()>concat>"+",但是当"+"连接的是常量时,效率高。
操作少量数据且不经常变化使用string,频繁修改使用stringbuilder或者stringbuffer,多线程使用stringbuffer,单线程stringbuilder。