今天和大家探讨个简单的小问题大笑
Java中函数参数是传值还是传地址
刚接触C语言时有一道题困惑了我好久,就是交换两个数的值,本来以为相当简单,只要把要交换的a,b传进去,在函数里面利用一个中间变量就可以完成参数的交换,但如何修改程序都不行,大家不要笑,曾记否刚开始学习是对于a=b和形参实参我就迷惑了好久,好久-^^-。很明显下面的程序无法完成交换。
#include<stdio.h>
void swap(int,int);
void main(){
inta=5;
intb=7;
printf("a=%d b=%d\n",a,b);//a=5 b=7
swap(a,b);
printf("a=%d b=%d\n",a,b);//a=5 b=7
}
void swap(int a,int b){
inttemp;
temp=a;
a=b;
b=temp;
}
改成传地址很简单利用指针就可以完成两个数的交换
#include<stdio.h>
void swap(int *,int *);
void main(){
inta=5;
intb=7;
printf("a=%d b=%d\n",a,b);//a=5 b=7
swap(&a,&b);//此处传出a,b的地址,利用取地址符
printf("a=%d b=%d\n",a,b);//a=7 b=5
}
void swap(int *a,int *b){//传入地址,就可以完成两个说
inttemp;
temp=*a;
*a=*b;
*b=temp;
}
C#近几年作为脚本语言很火,由于微软的强大实力和VisualStudio号称功能最强大的编译器C#发展的很不错,java中很多特性其实是晚于C#出现的,不能说谁抄袭谁,毕竟java比C#出现的早,如果当初sun不对微软施加压力,微软保持对java的热情,不知道现在会如何。随着微软进一步拥抱linux,听说最近出的2017 VisualStudio已经可以开发android应用了。
C#语言有专门的关键字可以表示是传值还是传地址ref。
static void swap(int a, int b) //这个函数将以传值的方式运行
{
inttemp;
temp=a;
a=b;
b=temp;
}
2
static void swap(ref int i, ref int t) // 这个函数将会以传址的方式进行运算. {int temp;
temp=a;
a=b;
b=temp;
}
函数内部完全相同,结果却是不同的,所以c语言和C#是存在传值传地址的概念的。
Java中程序员无法直接操作指针,对于传值还是传地址很模糊,但我们知道java中变量分为两类,一类是基本变量,一类是引用。其实当我们把实参a,b传进函数后,就相当于把a,b的值分别传给了函数用于接收a,b的局部变量,那么不管是传进去引用还是值,实参a,b的值都不会被改变,因为操作的时函数中接收a,b传递的值的局部变量,函数执行完毕,这两个局部变量也就不存在了。那为什么传进去引用可以修改a,b的值呢,这是不违反我上面说的原理的,传引用相当于把a,b的内存地址传递进函数,函数的局部变量接收了a,b的地址,a,b的引用地址是无法在函数内部被改变的,但是a,b指向的值是可以改变的。
Java中无论传值还是传引用都是传的参数的副本,副本只在函数内部有效。而当传引用时,传进去的是自己副本的地址,地址无法被改变但是地址指向的值可以被改变。所以可以说java中都是在传值。
实例:
publicstaticvoidmain(String[]args){
intnum=4;
test1(num);
System.out.println(num);//4
Stringstr="lidx";
test2(str);
System.out.println(str);//lidx
StringBuffersb=new StringBuffer("lidx");
test3(sb);
System.out.println(sb);//lidxadd
String[]arr={"lidx","lidx"};
test4(arr);
System.out.println(Arrays.asList(arr).toString()+"");//[add,lidx]
Testtest=new Test(4);
test5(test);
System.out.println(test.getAge());//5
}
所以说java中都可以看做是传值,普通类型参数传递的是参数的值的副本,在函数内部值修改副本,无法对原始数据产生影响,当引用作为参数时,传递的是引用类型的地址,函数内部接收引用的地址的副本,对引用地址所指向的值可以进行修改,但引用的地址是无法修改的,相当于引用地址的值无法修改。String和StringBuffer作为参数为什么不同,相信了解String特性的都知道,String生成实例之后他的值无法修改,如果对它进行修改会产生新的对象,所以String的地址传入函数内部,函数内部对它指向的值进行操作,最终却生成了另外一个对象,而上面所说无法对原String的地址修改,所以对于新生成的String对象无法影响原来的String对象,并且它的生命周期只在函数内部。