String:
对String对象的任何改变都不影响到原对象,相关的任何change对象的操作都会生成新的对象。
1、String str="hello world" 和String str=new String("hello world")的区别
前者:str是指向字面常量的引用,"hello world"被存储在运行时常量池
后者:str引用指向一个对象,而创建对象时的构造方法中的形参是指向字面常量的引用。
区别体现在哪儿呢?我们看一下如下案例
String str1="hello world";
String str2=new String("hello world");
String str3="hello world";
String str4=new String("hello world");
str1==str3:因为两个引用指向常量池中同一个字面常量
str1<>str2:因为一个指向常量,一个指向[堆内存]中new出来的对象
str2<>str4:两个new出来的对象,虽然内容相同,但是在[堆内存]中的地址是不同的,所以两个引用不相等。
2、String、StringBuilder、StringBuffer的区别
String:不适合于做字符串拼接运算,字符串对象需要频繁拼接的建议用后两种
StringBuilder跟
StringBuffer的方法基本相同,那为啥要分成两个类呢?
因为:
StringBuffer的方法是线程同步的,有synchronized修饰符
使用建议:当字符串相加操作或者改动小的情况下,用String
当操作多的情况用
StringBuilder,若使用多线程的情况使用
StringBuffer
案例一:
string a; a += "hello";
相当于: a = new StringBuilder();
a.append("hello");
a = a.toString();
结论:
string对象在拼接运算时,jvm会将将a+="hello",优化成上述代码
案例二:string a = "hello2"; string b = "hello"+2;
问:a==b是否成立?
答:true
原因:
"hello"+2会被当成字面常量来处理,因此
在
编译期间会被优化成"hello2",
所以a和b都是指向[字面常量的引用]
案例三:string a = "hello"; string b = "hello2";
string c = a +2;
问:b==c是否成立?
答:false
原因:c=a+2,在拼接运算中,a是对象引用,所以在编译期间string c=a+2不会被优化,这种方式生成的对象是保存在堆上的。
案例四:
final
string a = "hello"; string b = "hello2";
string c = a +2
问:b==c是否成立?
答:true
原因:被final修饰的变量,在编译期间会被替代为真实的值,即string c=a+2,在编译期间会优化成string c="hello"+2
案例五:getHello()方法返回"hello"字符串,
final
string a =
getHello()
; string b = "hello2";
string c = a +2
问:b==c是否成立?
答:false
原因:虽然a变量被final修饰,但是其值是通过调用getHello()方法来赋值,因此它的值只能在运行期间确定,所以编译期间不会被优化,即b和c指向的是不同的对象。
案例六:string a = new String("abc");
问:这段代码[创建]了几个对象?
答:1个
问:这段代码[涉及]了几个对象
答:2个
原因:类加载过程中在运行时常量池中创建了一个“abc"对象,而在运行期间只创建了一个String对象
案例七:string a="hello",string b=new String("hello");string c = b.intern();
问:a==c成立吗?
答:true
原因:b.intern()
方法表示,会在运行时常量池中查找是否有跟b内容相同的"hello"字符串常量,
有则返回字符串常量的引用,
没有则将b的内容存入常量池,并返回一个指向该字符串常量的引用