面试:String相关问题总结
目录
1. String 是否可以被修改
这个问题其实有两个关注点:
- String的实例化对象的引用地址能否被修改
- String的实例化对象引用的值能否被修改
- 引用地址能否被修改,答案是可以。见**【2】**。
- 一个实例化String对象的值能否被修改,答案是不可以。
String设计的初衷就是将其作为常量使用的,一旦将其创建便不能修改它的值。
在源码中,String内部存储值的属性被final修饰,在初始化后value的引用地址就不能被修改了,而且String内部也并未提供任何可以修改value指定下标处值的任何方法,同时由于String本身也被final修饰,String类无法被继承,因此替换String的某个字符的操作也无法实现。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
private int hash; // Default to 0
public String() {
this.value = "".value;
}
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
}
延伸话题:
Q:那你说说final关键字有什么作用
A:final关键字修饰在不同的地方有不同效果:
- 【类】类不可继承
- 【方法】方法不可重写
- 【属性】属性上值不可修改、引用地址不可更换且需赋初值
Q:final修饰的属性真的不能修改吗
A:通过反射可以强制修改,但是由于虚拟机优化,修改可能不会起作用(这一点参考**【3】**)
2. String的值不可以被修改,为什么又可以被重新赋值呢,这是否有所矛盾?
问题如下所示:
String s = "Apple";
s = "Mango";
不矛盾。
这里首先要明白一个前提:这里s是一个对象,而"Apple"是另一个对象;由于s没有被final修饰,也就是说它的引用地址是可以改变的。而"Apple"它是一个字符串常量,它才是那个无法被变更的对象。
-
这里的s,实际上就是一个对象,它只是保存了"Apple"这个常量的引用地址,修改s的值为"Mango"时,实际上只是在常量池新建了一个常量"Mango",同时将s的引用地址指向了"Mango"。
-
String创建后不可修改,指的是"Apple"这个String常量一旦被创建就不可以被修改了。任何指向它的对象,获取到的值将一直是"Apple"。
3. 直接赋值和new的区别
如下所示的两条语句有何区别:
String s1 = "Apple";