本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!
在开发过程中,我们经常会遇到对象传递的问题,有时仅仅传递数据,有时却要实现数据同步;这时,就要分清两者间的区别。
public class DelegentDemo { public void changStr(String str) { str = "cde"; } public void addStr(String str) { String bString = new String("cde"); str += bString; } public void contactStr(String str) { String bString = new String("cde"); str.concat(bString); } public void changeInt(int a) { a = 2; } public void addInt(int a) { a += 2; a++; } /** * @param stringBuffer */ private void changStringBuffer(StringBuffer stringBuffer) { // TODO Auto-generated method stub stringBuffer.append("db"); } /** * @param list */ private void newList(List<String> list) { // TODO Auto-generated method stub list = new ArrayList<String>(); } /** * @param list */ private void changeList(List<String> list) { // TODO Auto-generated method stub list.add("cdf"); } public static void main(String[] args) { DelegentDemo delegent = new DelegentDemo(); String str1 = new String("abc"); delegent.changStr(str1); System.out.println("abc传递常量重新赋值cde后:" + str1); delegent.addStr(str1); System.out.println("abc传递常量加值cde后:" + str1); delegent.contactStr(str1); System.out.println("abc传递常量contact值cde后:" + str1); int a = 3; delegent.changeInt(a); System.out.println("3传递常量重新赋值2后:" + a); delegent.addInt(a); System.out.println("3传递常量加值2后:" + a); List<String> list = new ArrayList<String>(); list.add("abc"); delegent.changeList(list); System.out.println("List size=1对象传递加值cdf后的大小:" + list.size()); delegent.newList(list); System.out.println("List size=1 对象置空后的大小:" + list.size()); StringBuffer stringBuffer = new StringBuffer("adb"); delegent.changStringBuffer(stringBuffer); System.out.println("adb传递加值db后"+stringBuffer.toString()); } }
结果如下:abc传递常量重新赋值cde后:abc
abc传递常量加值cde后:abc
abc传递常量contact值cde后:abc
3传递常量重新赋值2后:3
3传递常量加值2后:3
List size=1对象传递加值cdf后的大小:2
List size=1 对象置空后的大小:2
adb传递加值db后adbdb
结论:
1、传递的String常量值改变(包含赋值和加值)后,等于产生一个新的变量,此引用指向新变量,而原引用仍然指向原变量,所以打印原引用,当然值不会发生改变。
例:
public String trim() { int start = offset, last = offset + count - 1; int end = last; while ((start <= end) && (value[start] <= ' ')) { start++; } while ((end >= start) && (value[end] <= ' ')) { end--; } if (start == offset && end == last) { return this; } return new String(start, end - start + 1, value); }不论trim还是contact方法,均如此,这时String被当成基本数据常量来处理常量都存储在栈,Int也是同样原理。
至于容器和对象,如List和StringBuffer,它们是存储在堆里面的,传递引用过去,操作后会改变值。
例:
/** * Adds the specified object at the end of this {@code ArrayList}. * * @param object * the object to add. * @return always true */ @Override public boolean add(E object) { Object[] a = array; int s = size; if (s == a.length) { Object[] newArray = new Object[s + (s < (MIN_CAPACITY_INCREMENT / 2) ? MIN_CAPACITY_INCREMENT : s >> 1)]; System.arraycopy(a, 0, newArray, 0, s); array = a = newArray; } a[s] = object; size = s + 1; modCount++; return true; }size被加1,/** * Returns the number of elements in this {@code ArrayList}. * * @return the number of elements in this {@code ArrayList}. */ @Override public int size() { return size; }因此取size方法时,会增加/** * Constructs a new {@code ArrayList} instance with zero initial capacity. */ public ArrayList() { array = EmptyArray.OBJECT; }而第二个对list进行操作,只是初始化了list对象,只是改变它的值,没改变全局变量的size,而调用clear方法有效/** * Removes all elements from this {@code ArrayList}, leaving it empty. * * @see #isEmpty * @see #size */ @Override public void clear() { if (size != 0) { Arrays.fill(array, 0, size, null); size = 0; modCount++; } }
再看StringBuffer/** * Adds the character array to the end of this buffer. * * @param chars * the character array to append. * @return this StringBuffer. * @throws NullPointerException * if {@code chars} is {@code null}. */ public synchronized StringBuffer append(char[] chars) { append0(chars); return this; }final void append0(String string) { if (string == null) { appendNull(); return; } int length = string.length(); int newCount = count + length; if (newCount > value.length) { enlargeBuffer(newCount); } string._getChars(0, length, value, count); count = newCount; }变量变化时会调用底层,相当于把栈的值改变,而引用仍指向这个对象,当然会它的值会变了