JAVA学习【3】对JAVA值传递的理解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/tiandawangliang/article/details/50475224

看了一些博客,基本都认为Java 编程语言只有值传递参数。

在编程过程中发现方法调用对象进行处理并返回后,对象中的值也发生了变化,因此找了一些代码分析。

【程序段1】

<span style="font-size:18px;"><span style="font-size:18px;"><span style="font-size:18px;">public class MyCode2{

    public static void main(String[] args) {
        String a = "a";
        String b = "b";
        operator(a, b);
        StringBuilder x = new StringBuilder("x");
        StringBuilder y = new StringBuilder("y");
        operator(x, y);
        System.out.println(a + "," + b);
        System.out.println(x + "," + y);
    }

    public static void operator(String a, String b) {
        a += b;
        b = a;
    }

    public static void operator(StringBuilder a, StringBuilder b) {
        a.append(b);
        b = a;
    }
}</span></span></span>
运行结果:

a,b

xy,y

程序来源 http://www.cnblogs.com/xiaoQLu/archive/2013/04/10/3011561.html

为了理解该程序,下面逐一分析。


没有争议的是,基本类型变量(byte/short/int/long/float/double/boolean/char)在函数调用时按值传递。

【程序段2】

<span style="font-size:18px;"><span style="font-size:18px;">public class MyCode1{
	public static void main(String[] args){
		int num1 = 1;
		int num2 = 2;
		System.out.println("Line1->num1:"+num1+" num2:"+num2);
		swap1(num1,num2);
		System.out.println("Line3->num1:"+num1+" num2:"+num2);
	}

	private static void swap1(int num1, int num2){
		int temp;
		temp = num1;
		num1 = num2;
		num2 = temp;
		System.out.println("Line2->num1:"+num1+" num2:"+num2);
	}
}</span></span>
运行结果:

Line1->num1:1 num2:2

Line2->num1:2 num2:1

Line3->num1:1 num2:2

由上可知,函数swap1()调用属于基本数据类型的int变量x时,内存空间中分配了一个存储单元y用于保存存储单元x中的值,可以认为y是x的副本或者拷贝,但两者的存储单元并不相同,改变x值并不能改变y改变y值并不能改变x值。因此,函数调用int变量是值传递


再看下一程序

【程序段3】

<span style="font-size:18px;">public class MyCode4{
	public static void main(String args[]){
		String str = "yes";
		change(str);
		System.out.println(str);
	}

	private static void change(String str){
		str = "no";;
	}
}</span>

运行结果:

yes

由上可知,函数调用String类也是值传递


【程序段4】值得注意

<span style="font-size:18px;"><span style="font-size:18px;">public class MyCode2{

	String str = new String("yes");

	public static void main(String args[]){
		MyCode2 code1 = new MyCode2();
		code1.change(code1.str);
		System.out.println(code1.str);
	}

	public void change(String str) {
		str = "no";
	}
}</span></span>
运行结果:

yes

由上可知,函数调用类的String类型成员变量也是值传递。


【程序段5】

<span style="font-size:18px;"><span style="font-size:18px;">public class MyCode2{
	String str = new String("yes");
	
	public static void main(String args[]){
		MyCode2 code1 = new MyCode2();
		code1.str = "no";
		System.out.println(code1.str);
	}
}</span></span>
运行结果:no

理所当然,仅作对比。


【程序段6】值得注意

<span style="font-size:18px;">public class MyCode4{
	String str = "yes";
	public static void main(String args[]){
		MyCode4 code1 = new MyCode4();
		change(code1);
		System.out.println(code1.str);
	}

	private static void change(MyCode4 code1){
		code1.str = "no";
	}
}</span>
运行结果:no

【程序段7】

<span style="font-size:18px;">public class MyCode4{
	int num = 1;
	public static void main(String args[]){
		MyCode4 code1 = new MyCode4();
		change(code1);
		System.out.println(code1.num);
	}

	private static void change(MyCode4 code1){
		code1.num = 2;
	}
}</span>

运行结果:2

由上可知,函数调用类(除了上面【程序段3】中的String类)不是值传递。

这也说明了String的特殊性,runoob.com网站上有这样一条”注意:String类是不可改变的,所以你一旦创建了

String对象,那它的值就无法改变了“。此处留白,后续分析。


从程序段【2】~【7】就可以得出程序段【1】的结果,同时也说明了几个问题

1、String的特殊性

2、函数调用类(除去String类)对象不是值传递

      而基本类型变量(byte/short/int/long/float/double/boolean/char)在函数调用时按值传递

3、函数调用类的类型成员变量(基本类型和String类型)是值传递。

这显然和”Java 编程语言只有值传递参数“不符合,一种说法认为,将类(暂时认为除了String)的对象作为参数

传递时,对象的值就是它的地址,引用等同于对象,这样的话,对象的传递是值传递也是引用传递,因为两者是一样

的。(只是本人的理解,感觉以后会被自己推翻)


上文主要强调程序分析,需要注意的是值传递和引用传递的概念,百度得到:

引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

因此,程序也是基于形参会不会影响到实参来判断是否是值传递。


此外,在对http://guhanjie.iteye.com/blog/1683637下面评论中的一个例子分析时,发现数组也有类似特性。

【程序段8】

<span style="font-size:18px;">public class MyCode4{
	char[] ch = { 'y', 'e', 's' };

	public static void main(String args[]){
		MyCode4 code1 = new MyCode4();
		System.out.println(code1.ch);
		code1.change(code1.ch);
		System.out.println(code1.ch);
		code1.change2(code1.ch[0]);
		System.out.println(code1.ch);
	}

	public void change(char ch[]){
		ch[0] = 'n';
		ch[1] = 'o';
		ch[2] = '!';
	}
	public void change2(char ch){
			ch = 'y';
	}
}</span>
运行结果:

yes

no!

no!

由上可知,数组的传递是引用传递,而传递单个基本类型变量是值传递!

当然如果理解数组变量的值是地址的话,也可以说数组的传递是值传递。


然后,我又换了int类型,发现基本类型int不会改变变量的值,但是int数组会改变其中的值。

【程序段9】

<span style="font-size:18px;">public class MyCode2{
	int num = 1;
	int[] dat={2,3};

	public static void main(String args[]){
		MyCode2 code1 = new MyCode2();
		code1.changeNum(code1.num);
		System.out.println(code1.num);

		code1.changeDat(code1.dat);
		System.out.println(code1.dat[0]);
	}

	public void changeNum(int num) {
			num = 2;
	}
	public void changeDat(int[] dat) {
			dat[0] = 5;
	}
}</span>
运行结果:
1

5

由上可知,数组的传递是引用传递,而传递单个基本类型变量是值传递!当然如果理解数组变量的值是地址的话,也可以说数组的传递是值传递。


【程序段10】

<span style="font-size:18px;">public class MyCode1{
	public static void main(String[] args){
		int[] num = {1,2,3};
		System.out.println(num);
	}
}</span>
运行结果:
CI@1db9742

由上可知,数组变量num的确实是其地址,因此可以说数组的传递是值传递。


这样也解释了http://guhanjie.iteye.com/blog/1683637评论中的争论问题,即

【程序段11】

<span style="font-size:18px;">public class MyCode3{
	String str = new String("good");
	char[] ch = { 'a', 'b', 'c' };

	public static void main(String args[]){
		MyCode3 ex = new MyCode3();
		ex.change(ex.str, ex.ch);
		System.out.print(ex.str + " and ");
		System.out.print(ex.ch);
	}

	public void change(String str, char ch[]){
		str = "test ok";
		ch[0] = 'g';
	}
}</span>

运行结果:
good and gbc



展开阅读全文

没有更多推荐了,返回首页