JAVA学习【3】对JAVA值传递的理解
2016-01-07 11:45
579 查看
看了一些博客,基本都认为Java 编程语言只有值传递参数。
在编程过程中发现方法调用对象进行处理并返回后,对象中的值也发生了变化,因此找了一些代码分析。
【程序段1】
a,b
xy,y
程序来源 http://www.cnblogs.com/xiaoQLu/archive/2013/04/10/3011561.html
为了理解该程序,下面逐一分析。
没有争议的是,基本类型变量(byte/short/int/long/float/double/boolean/char)在函数调用时按值传递。
【程序段2】
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】
运行结果:
yes
由上可知,函数调用String类也是值传递。
【程序段4】值得注意
yes
由上可知,函数调用类的String类型成员变量也是值传递。
【程序段5】
理所当然,仅作对比。
【程序段6】值得注意
【程序段7】
运行结果: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】
yes
no!
no!
由上可知,数组的传递是引用传递,而传递单个基本类型变量是值传递!
当然如果理解数组变量的值是地址的话,也可以说数组的传递是值传递。
然后,我又换了int类型,发现基本类型int不会改变变量的值,但是int数组会改变其中的值。
【程序段9】
1
5
由上可知,数组的传递是引用传递,而传递单个基本类型变量是值传递!当然如果理解数组变量的值是地址的话,也可以说数组的传递是值传递。
【程序段10】
CI@1db9742
由上可知,数组变量num的确实是其地址,因此可以说数组的传递是值传递。
这样也解释了http://guhanjie.iteye.com/blog/1683637评论中的争论问题,即
【程序段11】
运行结果:
good and gbc
在编程过程中发现方法调用对象进行处理并返回后,对象中的值也发生了变化,因此找了一些代码分析。
【程序段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
相关文章推荐
- Java HashMap工作原理【图文版】
- Java注释Override、Deprecated、SuppressWarnings详解
- 将java开发的wordcount程序部署到spark集群上运行
- JavaEE_SSM_Mybatis Mybatis 学习指南
- Java权限基础
- JAVA反射机制之一
- java 类加载器(class loader)深入探讨
- 设计模式-责任链模式(Java)
- 2 Maven-安装和配置
- eclipse相关知识点
- WIN10 Eclipse LUNA的JDK配置
- Spring定时任务的几种实现--推荐spring task
- 搭建struts2环境
- 已有的java web项目如何搞到eclipse中去
- RMI使用小例
- java.lang.OutOfMemoryError: Java heap space 的解决
- java错误和异常
- java 学习笔记(一)
- JAVA 学习笔记(二)
- Java clone() 浅克隆与深度克隆