java中值传递还是引用传递探究

来源:互联网 发布:如何理财 知乎 编辑:程序博客网 时间:2024/06/05 11:43
原文链接:http://blog.csdn.net/yissan/article/details/52896198

Java 中是引用传递还是值传递,让我们来一探究竟! —— 由 Cool 分享

前言

在学习Java编程语言过程中最容易让你产生误解的问题之一就是 java是值传递还是引用传递。今天就来围绕这个话题揭开迷雾。

概念

首先先来认识一下什么是值传递什么是引用传递。

  • 值传递: 将方法实际参数值复制到另一个变量,然后复制的对象被传递,这就是为什么它被称为“值传递”

  • 引用传递:将实际参数的引用传递给该方法,这就是为什么它被引用称为“传递”的原因。

例子分析1

问题:如果java是使用引用传递的话,为什么在函数中 变量的交换会没有卵用呢?答案:java通过引用来操作对象,并且所有Object类型的变量都是引用一个地址。但是,java传递方法参数并不是引用传递,而是值传递。

来个例子,大家感受一下:

public void badSwap(int var1, int var2){  int temp = var1;  var1 = var2;  var2 = temp;}

当badSwap()方法结束,原先作为实际参数传递进来的变量仍然是它们原来的值,也就是这个方法然无卵用。如果把这个方法的参数由int改变成Object类,结果依然一样。因为java是通过值传递来传递对象引用的。这么说可能不太清晰,再来一个例子。

public void tricky(Point arg1, Point arg2){  arg1.x = 100  arg1.y = 100  Point temp = arg1  arg1 = arg2  arg2 = temp}public static void main(String [] args){  Point pnt1 = new Point(0,0)  Point pnt2 = new Point(0,0)  System.out.println("X: " + pnt1.x + " Y: " +pnt1.y)  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y)  System.out.println(" ")  tricky(pnt1,pnt2)  System.out.println("X: " + pnt1.x + " Y:" + pnt1.y)  System.out.println("X: " + pnt2.x + " Y: " +pnt2.y)}

构造了两个对象pnt1和pnt2,并且初始的x,y值都是0。之后传入tricky()方 
法,在方法中修改行参args1的x,y的值,之后交换行参的指向。

执行main方法 ,输入如下

X: 0 Y: 0X: 0 Y: 0X: 100 Y: 100X: 0 Y: 0

根据输出结果,可以发现实际参数pnt1的值被修改了,pnt2的属性没有变,也就是pnt1盒pnt2的交换失败了!这里最容易被疑惑。 
pnt1和pnt2肯定是对象引用,当把pnt1和pnt2传入到tricky()方法当中, 
由于java是值传递,也就类似于复制,相当于复制和一个和pnt1一样的行参变量arg1,它也拥有了一个和pnt1变量同一指向的引用。图一展示了通过值传递之后两个引用指向同一个地址。

图1 
图1。方法中被传入对象引用参数之后,一个对象至少会有两个引用

上面的例子由于两个变量的引用都指向了同一个对象,所以在方法中修改对象的值会生效。但是由于arg1是copy的一个变量,所以交换的话只是交换了arg1的指向,这就是为什么交换会失败的原因。

图2展示了仅仅是方法参数里的引用交换了,而并不是原始的参数交换。

如果需要成功交换pnt1和pnt2的引用,只能在外部直接修改他们的引用即可。

图2 
图2:java通过值传递,copy了一个和pnt1一样的变量,他们拥有同样的引用。在方法调用之后,仅仅是交换了arg1和arg2的引用。

在国内可能有大部分的人清楚传递的规律,但是他们依然习惯是基本类型是值传递,引用类型变量就是引用传递,因为方法中的参数的确有了外部变量的引用。这个看个人理解。我更偏向于是值传递:通过值传递之后方法里的参数拥有了和实际参数一样的值(基础类型为值,对象类型为引用),所以才拥有了引用。而如果是引用传递的话,那就是是直接传递一个存放于堆区的对象给(也就是直是复制了一个对象)。当然这只是我个人的认识。

例子分析2

public class Test {    private static int  a;    private int b;    public static void main(String[] args) {        System.out.println(a);        modify(a);        System.out.println(a);        return;    }    private static void modify(int a) {        a++;    }}

知道了java是值传递的,结果很清楚了

输出a的值肯定不变。

java总是通过值传递而不是引用传递,再来一个例子

例子分析3

public class Balloon {    private String color;    public Balloon(){}    public Balloon(String c){        this.color=c;    }    public String getColor() {        return color;    }    public void setColor(String color) {        this.color = color;    }}

Balloon类拥有一个color属性。

public class Test {    public static void main(String[] args) {        Balloon red = new Balloon("Red");         Balloon blue = new Balloon("Blue");         swap(red, blue);        System.out.println("red color="+red.getColor());        System.out.println("blue color="+blue.getColor());        foo(blue);        System.out.println("blue color="+blue.getColor());    }    private static void foo(Balloon balloon) {         balloon.setColor("Red");         balloon = new Balloon("Green");         balloon.setColor("Blue");     }        public static void swap(Object o1, Object o2){        Object temp = o1;        o1=o2;        o2=temp;    }}
答案:red blue red
1 0
原创粉丝点击