Java数据传递实验


本文来自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;
    }
变量变化时会调用底层,相当于把栈的值改变,而引用仍指向这个对象,当然会它的值会变了


原文地址:https://www.cnblogs.com/fengju/p/6174419.html