一、我们都知道Java中只有值传递,所以String也一定是值传递。
二、String是对象类型,把它当做方法形参进行值传递的时候,会拷贝其地址副本,我们在方法中对它进行修改为什么没有生效?使用StringBuffer表现出的结果为什么与String不同?
-
如下是String的测试代码
-
如下是StringBuffer的测试代码
三、String源码解读
- 我们首先看看String的几段关键代码,首先它拥有4个成员变量。
要点001: value[]是用来保存字符的,但是它被final修饰了。
要点002: final修饰的成员变量仅在第一次初始化时被赋值,以后不可更改
要点003: 由于final修饰的是数组,所以value[]的地址值不可能再发生变化。它里面存储的char值依然可以改变
- 我们再看看String中的concat方法是如何执行的
- 如果你能修改到String中的value[],我们采用反射的方式对value进行修改,这样外层的s1才会变化!
- String的结论:String没有提供可以修改其成员变量value[]的API,所以我们把s1当做形参传入方法时,只要不人为改变它成员变量value[]的值,方法执行完之后对外层的s1不会产生任何影响!
- 注意:我们熟知的+运算符,在Java中只有String重写了这个运算符,它的底层走的是AbstractStringBuilder的append方法!与StringBuffer的append方法是一样的。
四、StringBuffer源码解读
-
先看成员变量,它继承自AbstractStringBuilder
-
再看看AbstractStringBuilder的成员变量有哪些
-
然后看看关键的append方法,先执行ensureCapacityInternal,然后执行str.getChars 方法。
-
我们先看ensureCapacityInternal方法,它又调用了Arrays.copyOf方法
-
看看Arrays.copyOf 方法在干嘛
-
ensureCapacityInternal执行完之后,下一步就是执行str.getChars方法了
-
StringBuffer总结:value、count没有被final修饰,所以可以被更改。append方法就是修改了value以及count的值,所以把StringBuffer当做形参传入方法,执行changeStr后,外层的StringBuffer值也会受到影响!