String类
1.含义
String类被称为“不可修改的字符串常量类”。
2.底层实现
String类底层的修饰代码。
String字符串底层内部维护了一个byte[]数组,使用final关键字修饰,数组中的值一旦被声明,就不能被再次赋值。
接下来就分析一下内存中的执行过程,明明值相同为什么结果会不一样。
String类属于引用数据类型,按地址进行传递。
前两步的值相同,在常量池中共用一个地址addar1,第三步新建了一个对象,需要在对内存中开辟一个空间,发现值和常量池中的值一样,就将常量池的地址也拿来引用一下,最后将堆内存地址addS1给新的变量s3。
第四步将s3的引用地址指向进行了改变s3指向常量堆中的addar2,第五步就相当于把内存中的地址也指向了addar2。
3.关于String类的面试题
String类是按照什么数据类型进行传递的?
按引用数据类型进行传递。
那么按引用数据类型传递形参,会不会对实参产生影响呢?
不会,String类是不可以修改的字符串常量,修改形参只能让形参重新指向内存中另一块新的地址。
4.关于String类常用的一些方法。
StringBuffer类和StringBuider类
1.含义
StringBuffer类和StringBuider类是可以“修改的字符串常量”。
2.底层实现
StringBuffer类和StringBuider类都是AbstractStringBuider的子类。
StringBuffer和StringBuider内部实际上是一个由byte[ ] 类型的可变数组,没有使用final关键字修饰,所以它的值是可以改变的。
3.默认长度以及如何扩容
既然都继承了AbstractStringBuider类,且内部都由一个byte类型的数组属性,那么数组的默认长度也一定相同。请观看下图:
那么当数组容量大于默认容量时,又是怎么进行扩容的呢?扩容多少呢?
如何进行扩容?
每次都扩容一个是很慢的,那数组内部到底扩容多少呢?
通过append()方法进行追加的时候,如果添加的元素容量大于默认容量,这是数组会进行扩容,且扩容的大小为:原数组长度*2+2;请观看下图:
问题又来了,如果数据实际存储的容量为5000多,空间容量为10000多,那么剩余的空余容量岂不是浪费了吗?
我们可以使用trimToSize()方法,去除空余元素,防止空余元素占用不必要的空间。
4.StringBuffer类和StringBuider类的区别
StringBuffer类线程安全,被synchronized关键字修饰,效率低。
StringBuider类线程不安全,内部没有使用synchronized关键字修饰,效率高。
多线程程序中,如果考虑线程安全问题,则使用StringBuffer类。
多线程程序中,如果不考虑线程安全问题,则使用StringBuider类。
单线程程序中,如果不考虑线程安全问题,使用StringBuffer类和使用StringBuider类都一样。
初次阐述肯定有不如意的地方,读者发现后请留言,在下再做修改。