java引用传值的问题

    碰到一道面试题,查了好多资料才把这个问题弄明白,在此做个记录,纯属个人理解,仅供参考,如有问题,欢迎指正。

    先把题目贴出来:

public class Test {
    public static void main(String[] args){
    	int i=1;
    	change(i);
    	System.out.println(i);
    }
    static void change(int i){
    	i+=1;
    }
}
what is the result?
A:0      B:1      C:2      D:Compile time error

    答案是B,而非C。类似的题目还有如下:

public class Base {
	private String name;
	private String sex;
	
	public Base(String x,String y){
		this.name=x;
		this.sex=y;
	}
	
	public String toString(){
		return name+","+sex;
	}
	//更改对象属性
	public static void Update(Base b){ 
		b.name="name3";
		b.sex="f";
	}
	//交换对象引用
	public static void Swap(Base b1,Base b2){
  	 Base temp=b1;
  	 b1=b2;
  	 b2=temp;
  	 System.out.println("In The Swaping:b1<"+b1+">\tb2<"+b2+">");  //交换方法中输出交换效果
    }
	
      public static void main(String[] args){
    	  Base b1=new Base("name1","m");
    	  Base b2=new Base("name2","f");
    	  System.out.println("Before Swaping:b1<"+b1+">\tb2<"+b2+">"); //调用交换方法前效果
    	  Swap(b1,b2); //调用交换方法
    	  System.out.println("After   Swaping:b1<"+b1+">\tb2<"+b2+">");  //调用交换方法后效果
    	  Update(b1);
      	  System.out.println("After    Update:b1<"+b1+">\tb2<"+b2+">");  //调用交换方法后效果
      }
}/*output
Before Swaping:b1<name1,m>	b2<name2,f>
In The Swaping:b1<name2,f>	b2<name1,m>  //在方法中交换成功
After  Swaping:b1<name1,m>	b2<name2,f> //执行交换方法后却没有实现交换?
After   Update:b1<name3,f>	b2<name2,f>  //交换没有成功,更改操作却成功了,Why?
*/

    Java中的变量分基本类型和引用类型。基本类型即boolean、char、int、short、long、double、string等八种类型,此外的为引用类型。C++中的函数参数传递有值传递、引用传递和地址传递。引用是指向对象的内存地址。值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数,如(来自百度百科)。

#include<iostream.h>
void fun(int a)
{
a=10; //修改参数
}
int main()
{
int a=20;
fun(a); //调用fun函数
cout<<a<<endl; //输出变量,变量的值没改变
return 0;
}

引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

void swap(int *a,  int *b)
{
	int t = *b;
	*b = *a;
	*a = t;
	cout <<"In Swap:"<< *a <<","<< *b<<endl; //交换函数中
}
int _tmain(int argc, _TCHAR* argv[])
{
	int i = 5;
	int j = 9;
	cout << "Before Swap:" << i << "," << j<< endl;//交换前
	swap(&i,&j);
	cout <<"After Swap:"<< i <<","<< j<<endl;  //执行交换函数后
	system("pause");
}/*output:
 Before Swap:5,9
 In     Swap:9,5
 After  Swap:9,5  //实际值已发生更改
 */

    在C++中可以通过指针来完成引用传递和地址传递,但在Java中是没有指针的,因此在Java方法参数传递中只有值的传递。对象作为方法参数时,传递的对象的引用,但并非是C++中的引用传递,而是传递的是“引用”的值,所以本质上还是值传递。将上面程序修改如下:

void swap(int *a,  int *b)
{
	int *t = b;
	b = a;
	a = t;
	cout <<"In Swap:"<< *a <<","<< *b<<endl; //交换函数中
}
int _tmain(int argc, _TCHAR* argv[])
{
	int i = 5;
	int j = 9;
	cout << "Before Swap:" << i << "," << j<< endl;//交换前
	swap(&i,&j);
	cout <<"After Swap:"<< i <<","<< j<<endl;  //执行交换函数后
	system("pause");
}/*output:
 Before Swap:5,9
 In     Swap:9,5
 After  Swap:5,9  //实际值没有发生更改
 */

    此函数实现的本质与前两题JAVA考题是一样的,方法中发生交换的是封装在Java中的C++指针,而对于实际对象没有影响。根据值传递的概念,当一个对象实例作为一个参数被传递到方法中时,参数值为该对象的“引用”一个副本。所以,在交换方法中成功交换的均是该对象引用的副本,如图:

   

    由于引用值更换不变,故在方法中输出效果为正常交换,而此并未改变原引用,所以最后对象的值还是不变。但是方法中作为副本的引用同样指向实际对象,故而对象属性可以在被调用的方法中改变,但对象的原引用是不会改变的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值