`
j小虫
  • 浏览: 18488 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java的值传递与引用传递

    博客分类:
  • java
阅读更多

对于如下代码:

public class Test {
    
    public static void main(String[] args) {
        int i = 0 ;
        Test test = new Test();
        test.valueMethod(i);
        System.out.println(i);       
    }
    
    private void valueMethod(int a){
        a = 5;
    }
}
 

 

运行结果是0,由于参数是基本类型,因此调用时我们传递的是一个值,所以是java中的值传递,它传递的是一个值的副本,因此,在这个局部方法中对传进来的值的修改是不会影响外部变量的,它修改的是副本的值而不是外部成员i的值。

 

而对于如下代码

public class Test {
	
	public static void main(String[] args) {
		DO dos = new DO();
		dos.setX1(3);
		Test test = new Test();
		test.paraMethod(dos);
		System.out.println(dos.getX1());
		
	}
	private void paraMethod(Object o){
		DO oo = (DO)o;
		oo.setX1(5);
	}
}

class DO{
	private int x1 ;
	public int getX1() {
		return x1;
	}
	public void setX1(int x1) {
		this.x1 = x1;
	}
	
}

 运行结果却是5,这是因为值传递时候,传递的是值的拷贝,而引用传递时,也是引用的拷贝,它意味着外部变量和局部变量的指针指向同一个对象,当你在局部方法内修改那个对象的值时,实际上是修改的堆中的值,因此外部变量的值也修改了

 

 

再看如下代码:

public class Test {
	
	public static void main(String[] args) {
		DO dos = new DO();
		dos.setX1(3);
		Test test = new Test();
		test.paraMethod(dos);
		System.out.println(dos.getX1());
		
	}
	private void paraMethod(Object o){
		DO oo = new DO();
		oo.setX1(8);
		o = oo;
	}
}
class DO{
	private int x1 ;
	public int getX1() {
		return x1;
	}
	public void setX1(int x1) {
		this.x1 = x1;
	}
	
}

 它的运行结果还是3,有的人就奇怪了,这个和第二个不是类似么,为什么这里没有修改它的值呢

其实知道画堆栈图的人把这里画出来就明白了

 

 

dos是栈中的一个引用,它指向了堆中的x1所代表的值3

1.当你用上面第2段代码时,实际上是拷贝了一个引用传递到局部方法中,我们暂且称这个引用为dos2,dos和dos2都指向了堆中的3,当我们修改dos2的值的时候实际上就是把这个3给改成了5,因此,dos的x1这个值就变成了5。

2.当你用上面第3段代码时,实际拷贝的是一个引用传递到局部方法中,我们也暂且称这个引用为dos2,dos和dos2都指向了堆中的3,现在我在局部方法体中重新定义了一个oo,这个oo又是一个栈中的指针,它指向了堆中的另外一个值为8的堆空间,我把这个引用赋给dos2时,实际上就只是把dos2的指针给变了,而dos继续指向它原来的3,因此最后的结果就为三拉。

 

 

最后总结一下,目前java传递有2种观点

一种是值传递观点,他们认为java只有值传递,没有引用传递,就算参数是一个引用,它也是引用值的副本,所以是值传递

另一种是基本类型为值传递,引用类型就是引用传递。

 

我个人比较支持第一种,不过这个一直都有争议,没有正确答案~~~~。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics