彻底搞懂String类
String类相关面试题
String类能被继承吗,为什么
String类不能被继承。
在Java中,只要是被定义为final的类,也可以说是被final修饰的类,就是不能被继承的。
String类为什么被final修饰
- 了解 final
final 可以修饰类、方法、变量。
final修饰类:被final修饰的类不能被继承。
final修饰方法:final修饰的方法不能被重写。
final修饰变量:final修饰的变量必须初始化。
- 安全性
字符串在编码中是非常常用的,比如说一些用户名密码都是以字符串的形式存在于内存中,如果字符串是可变的,那么就有引用漏洞可以利用,用于攻陷我们的系统。
字符串不可变,在线程之间共享才是安全的,否则也会引起程序错乱的。 - 效率问题
只有当String类被设计成不可变时,才能实现字符串常量池,使多个字符串引用指向同一个常量池中的字符串,从而提高效率。
当字符串被创建的时候就可以缓存hashcode,所以在当做map的key的时候,字符串的效率往往要高于其他。
String类中的内容一旦声明则不可改变
- Java中一旦创建String对象,那他的值就无法改变了。如果需要对字符串做很多修改,那么应该选择使用StringBuffer&&StringBuilder类。
- 观察下面代码:你可能会认为String类对象s发生了改变,但是实际上而言,String类对象改变的只是其内存地址的指向,而其本身的内容并没有发生改变。
public class Test{ public static void main(String[] args){ String s="hello"; s+="world"; System.out.println(s); } }
下图是该程序运行的内部机制:
程序运行详细解析:
首先程序由上至下运行先把主函数main加载在栈当中,再生产String s对象,"hello"字符串存放在方法区常量池中,然后分配一个地址,s对象就指向相同地址的字符串。然后同理常量池中存放world字符串也分配一个地址,然后前后两个字符串相连接生成"helloworld"字符串并分配新的地址。字后对象s地址发生改变指向“helloworld”字符串,并与之前字符串断开指向的连接。
这样String生成字符串在常量池中会造成很多垃圾,会影响程序运行的时间和内存。
如果希望存放的String类不浪费空间即调整大小,且不用创建新的内存来存放新的对象,可以使用StringBuffer&&StringBuilder类来存放。
和String类不同的是,StringBuffer和StringBuilder类的对象能够被修改多次,且不产生新的未使用对象,当然String对象和上面两者的对象能够相互转换从而使用彼此需要的方法。
String、StringBuilder、StringBuffer区别
String、StringBuilder、StringBuffer都可以用来代表字符串。
String类是不可变类,任何对String的改变都会引发新的String对象的生产;
StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象;
StringBuilder与StringBuffer的原理和操作基本一致,区别在于StringBuffer支持并发操作,线程安全,适合多线程中使用。
StringBuilder不支持并发操作,线程不安全,不适合多线程中使用。
但是StringBuilder在单线程中的性能比StringBuffer高。
因此不必考虑到线程同步问题,我们应该优先使用StringBuilder类;如果要保证线程安全,自然是StringBuffer。
StringBuffer是如何保证线程安全?
直接通过synchronized 关键字来实现同步操作
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
StringBuffer/StringBuilder常用方法
StringBuffer和StringBuilder在使用上几乎一样,所以只写一个。
xxx代表方法出现重载
- append(xxx)
- deleteCharAt(int index)
- insert(xxx)
- reverse()
- setCharAt(int index, char ch)
- trimToSize()
- length()
- setLength(int newLength)
- capacity()
- ensureCapacity(int minimumCapacity)
- getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
方法详解及代码示例
- append()
追加内容到当前StringBuffer对象的末尾。