您的位置:首页 > 编程语言 > Java开发

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

2016-01-07 11:45 579 查看
看了一些博客,基本都认为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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: