java中有没有引用传递?
2015-09-08 23:26
405 查看
一、首先来明确一下"值传递"和"引用传递的"区别
值传递:是对所传递参数进行一次副本拷贝,对参数的修改只是对副本的修改,函数调用结束,副本丢弃,原来的变量不变(即实参不变)
引用传递:参数被传递到函数时,不复制副本,而是直接将参数自身传入到函数,函数内对参数的任何改变都将反映到原来的变量上。
二、对引用传递的认识误区
为什么有很多人认为java有引用传递呢?一种情况是有人认为调用函数时其参数有可能是引用(如上面的p),所以java有引用传递,这部分人对引用传递根本没有正确的认识;而另一种情况看似有道理,但是仔细分析也是不正确的的,他们往往会用如下的代码来证明他们的观点:
示例二:
[java] view
plaincopy
class Demo{
int a;
public Demo(int a){
this.a=a;
}
}
public class TestQuote{
public static void main(String args[]){
Demo d1=new Demo(1);
Demo d2=new Demo(2);
System.out.println(d1.a);
System.out.println(d2.a);
function(d1,d2);
System.out.println(d1.a);
System.out.println(d2.a);
}
private static void function(Demo d1,Demo d2){
int a;
a=d1.a;
d1.a=d2.a;
d2.a=a;
}
}
他们的观点如下:执行上面的代码,调用function()函数以前输出的结果是1、2,调用function()函数之后输出的结果会是2、1,可见在函数内对d1和d2的改变反映到了原来的变量上,要不是不会输出2、1的。
这种解释是很迷惑人的,看上去好像很正确,下面的代码会很好的反驳上面的观点:
示例三:
[java] view
plaincopy
class Demo{
int a;
public Demo(int a){
this.a=a;
}
}
public class TestQuote{
public static void main(String args[]){
Demo d1=new Demo(1);
Demo d2=new Demo(2);
System.out.println(d1.a);
System.out.println(d2.a);
function(d1,d2);
System.out.println(d1.a);
System.out.println(d2.a);
}
private static void function(Demo d1,Demo d2){
Demo temp;
temp=d1;
d1=d2;
d2=temp;
}
}
执行上面的代码,调用function()前后程序输出的都是1、2,此程序试图通过调用function()交换d1和d2,但是没有成功,为什么呢?因为d1和d2是值传递,function()中的d1和d2是main()函数中d1和d2的副本,调用完function()不会对main()中的变量产生影响。再看示例二中,function()函数内改变的并不是d1和d2本身的值,而是d1和d2指向的对象的值,调用完function()后d1和d2仍然指向函数调用前的堆地址,即函数参数是栈中的d1和d2,而不是堆中d1和d2指向的对象,即使你在函数中改变了堆中的对象,但没有改变函数参数的值。所以示例二并不是什么引用传递;可见java中只有值传递。
但是网上有很多针对"java值传递和引用传递进行的区别"的文章,如果读者看到的话一定要清楚,其中所说的引用传递是不正确的,他们所说的引用传递就是示例二中的那种情况。不幸的是,网上有很多文章都把示例二中的那样的传递看做引用传递,如果读者看到知道是什么意思就行了。
值传递:是对所传递参数进行一次副本拷贝,对参数的修改只是对副本的修改,函数调用结束,副本丢弃,原来的变量不变(即实参不变)
引用传递:参数被传递到函数时,不复制副本,而是直接将参数自身传入到函数,函数内对参数的任何改变都将反映到原来的变量上。
二、对引用传递的认识误区
为什么有很多人认为java有引用传递呢?一种情况是有人认为调用函数时其参数有可能是引用(如上面的p),所以java有引用传递,这部分人对引用传递根本没有正确的认识;而另一种情况看似有道理,但是仔细分析也是不正确的的,他们往往会用如下的代码来证明他们的观点:
示例二:
[java] view
plaincopy
class Demo{
int a;
public Demo(int a){
this.a=a;
}
}
public class TestQuote{
public static void main(String args[]){
Demo d1=new Demo(1);
Demo d2=new Demo(2);
System.out.println(d1.a);
System.out.println(d2.a);
function(d1,d2);
System.out.println(d1.a);
System.out.println(d2.a);
}
private static void function(Demo d1,Demo d2){
int a;
a=d1.a;
d1.a=d2.a;
d2.a=a;
}
}
他们的观点如下:执行上面的代码,调用function()函数以前输出的结果是1、2,调用function()函数之后输出的结果会是2、1,可见在函数内对d1和d2的改变反映到了原来的变量上,要不是不会输出2、1的。
这种解释是很迷惑人的,看上去好像很正确,下面的代码会很好的反驳上面的观点:
示例三:
[java] view
plaincopy
class Demo{
int a;
public Demo(int a){
this.a=a;
}
}
public class TestQuote{
public static void main(String args[]){
Demo d1=new Demo(1);
Demo d2=new Demo(2);
System.out.println(d1.a);
System.out.println(d2.a);
function(d1,d2);
System.out.println(d1.a);
System.out.println(d2.a);
}
private static void function(Demo d1,Demo d2){
Demo temp;
temp=d1;
d1=d2;
d2=temp;
}
}
执行上面的代码,调用function()前后程序输出的都是1、2,此程序试图通过调用function()交换d1和d2,但是没有成功,为什么呢?因为d1和d2是值传递,function()中的d1和d2是main()函数中d1和d2的副本,调用完function()不会对main()中的变量产生影响。再看示例二中,function()函数内改变的并不是d1和d2本身的值,而是d1和d2指向的对象的值,调用完function()后d1和d2仍然指向函数调用前的堆地址,即函数参数是栈中的d1和d2,而不是堆中d1和d2指向的对象,即使你在函数中改变了堆中的对象,但没有改变函数参数的值。所以示例二并不是什么引用传递;可见java中只有值传递。
但是网上有很多针对"java值传递和引用传递进行的区别"的文章,如果读者看到的话一定要清楚,其中所说的引用传递是不正确的,他们所说的引用传递就是示例二中的那种情况。不幸的是,网上有很多文章都把示例二中的那样的传递看做引用传递,如果读者看到知道是什么意思就行了。
相关文章推荐
- Java简单注册格式验证(正则表达式)
- java基础 iterator
- java第三弹--组合模式
- [笔记][Java7并发编程实战手册]5.Fork\Join(Java1.7新特性)框架
- java中的参数传递
- Java简单万年历
- [笔记][Java7并发编程实战手册]4.11-4.12在执行器中分离任务的启动和结果的处理和处理在执行器中被拒绝的任务
- 搭建Android开发环境(eclipse)
- 配置eclipse4ee
- JAVA基础
- Ehcache是现在最流行的纯Java开源缓存框架
- java中有关异常处理的问题
- String.Format大全(C# Java)
- mybatis报错 There is no getter for property named 'xx' in 'class java.lang.String
- java日志需要知道的几件事(commons-logging,log4j,slf4j,logback)
- Java try、catch、finally及finally执行顺序
- JAVA学习笔记之数据类型
- eclipse ibatis abator插件
- java 面向对象思想
- java String类分析