"不可变"的String类!
String类定义两种的方法:
String类是我们特别熟悉的一个类,关于它我们也经常用到,而我们知道我们定义String类时,我们有两种方式:
1.String a=“123”;
2.String a=new String(“123”);
那么这两种方式有什么区别么?
我们就通过程序比较一下:
两种方式的区别:
我们看到了第一种方式定义了a和b,第二种方式定义了c和d,而他们的区别就在于:
第一种方式:是因为在方法区内存中的"字符串静态池"中定义了"123",然后当后面再用到它的时候,直接用就可以了。
而第二种方法:采用的是new对象的方式,所以说c和d的内存地址并不一样,所以当a==b和c==d比较时,他们的结果是不同的。
所以说,当我们比较两个字符串是否相同时,我们不能使用= = 的方法,因为= =比较的是内存地址是否相同,我们需要使用equals方法。
下面就是代码:
如图:使用equals方法就可以清楚的比较出定义的字符串是否相等(特别注意:<mark>因为String已经重写了equals方法!!</mark>)。
相关的重点问题解答:
接下来有几个<mark>重点问题(面试可能会被问到)</mark>:
问题1:下列共创建了几个对象。
String c=new String("456");
String d=new String("456");
答:三个对象:因为是采用创建对象的方法定义字符串,所以有两个对象,还有一个是在JVM中的方法区的字符串静态池中创建的,所以有三个。
问题2:String为什么是不可变的?
答:因为根据java源代码,String中有一个byte[ ]数组,而这个数据是由final修饰的,数组一旦创建长度不可变,而且因为final导致不可再指向其他对象,所以String不可变,“abc"无法变成"abcd”。
问题3:StringBuilder和StringBuffer为什么可变?
答:同理问题2,但是StringBuilder和StringBuffer中的byte数组没用final修饰,它们的初始化容量大约是16,存满时会进行扩容,底层调用了数组拷贝的方法(system.arraycopy()…),所以它们适合进行字符串的频繁拼接。