前几天接到阿里巴巴的电话面试,被虐的一塌糊涂。当时问我打印字符串可以用这种方式System.out.println(“a” + “b” + “c”),但是一般我们不用这种方式,而要用StringBuffer,这是为什么?我说String内部存放字符串的数据结构是char型数组,这个char型数组是final型的,一旦被定义就不能被修改,所以这种方式打印字符串要new三次对象,而且对象在常量池也是一直存在的,这样很浪费空间。而StringBuffer内部也是一个char型数组,这个char型数组没有被final修饰,可以直接把字符串添加进去。他又问我怎么添加的?我就蒙了,没有具体看,今天看了源码,才发现自己当时真的是胡说八道。所以今天专门抽出时间看看StringBuffer的源码,并对源码进行解析。
StringBuffer类和StringBuilder类
public final classStringBuffer(StringBuilder)
extends AbstractStringBuilder
implementsjava.io.Serializable, CharSequence
1. 这个类final类型的,不能被继承,不能被修改;
2. 继承了AbstractStringBuilder抽象类,这个抽象类中提供了很多方法,查看源码可以看到StringBuffer中的方法基本上都调用了这个类中的方法。为什么要写这个抽象类作为父类呢?我认为这个抽象类主要是为StringBuffer和StringBuilder提供公共的方法,因为StringBuilder是线程不安全的,直接调用了父类的方法,而StringBuffer中每个方法都加了synchronized,保证了线程安全,其他全部一样。
3. 实现java.io.Serializable,让当前类可以被序列化。
4. 实现了CharSequence接口,这个接口其实是String的父类,也就是说String类也实现了这个接口,提供了四个方法。我们再遇到他的时候,可以当做String类型。
1.初始化方法。
publicStringBuffer()
publicStringBuffer(int capacity)
publicStringBuffer(String str)
publicStringBuffer(CharSequence seq)
四个构造方法的特点:
1.这四个方法内部都调用了父类的有参构造方法:
AbstractStringBuilder(intcapacity){};
2.提供的参数 capacity = 实际长度 + 16。比如StringBuffer()的长度是16,,
StringBuffer(int capacity)的长度是capacity = capacity + 16….
3.在父类方法中初始化了char型数组。
特别之处:
publicStringBuffer(String str)
publicStringBuffer(CharSequence seq)
这两个方法在初始完数组之后,把参数添加到了数组中,也就是初始化了数组的值,至于怎么添加的请看append(…)方法。