Java中是引用传递还是值传递?

前言

在学习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: 0
X: 0 Y: 0
X: 100 Y: 100
X: 0 Y: 0

根据输出结果,可以发现实际参数pnt1的值被修改了,pnt2的属性没有变,也就是pnt1盒pnt2的交换失败了!这里最容易被疑惑。

pnt1和pnt2肯定是对象引用,当把pnt1和pnt2传入到tricky()方法当中,

由于java是值传递,也就类似于复制,相当于复制和一个和pnt1一样的行参变量arg1,它也拥有了一个和pnt1变量同一指向的引用。图一展示了通过值传递之后两个引用指向同一个地址。

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

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

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

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

图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"); //memory reference 50
        Balloon blue = new Balloon("Blue"); //memory reference 100

        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) { //baloon=100
        balloon.setColor("Red"); //baloon=100
        balloon = new Balloon("Green"); //baloon=200
        balloon.setColor("Blue"); //baloon = 200
    }

    //Generic swap method
    public static void swap(Object o1, Object o2){
        Object temp = o1;
        o1=o2;
        o2=temp;
    }
}

由于之前分析过一个例子,这里我就不详细分析具体的每一个步骤。

大家可以去看该例子的原文出处,有每一步的分析过程,而且还有视频详细讲解(应该是要翻墙)

例子分析3

例子3分析链接:Java is Pass by Value and Not Pass by Reference

关于引用的知识,大家可以看我的文章 堆和栈

结语

最近太忙人也有点懒散所以很久没更新博客了,得赶快恢复过来。有问题请留言。点赞只需一秒,动力却是永恒,给我点个赞吧!期待你的关注!

时间: 2024-08-24 20:25:42

Java中是引用传递还是值传递?的相关文章

理解Java中的引用传递和值传递

关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习和分析一下,着急可以先看最后的结论. >>基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型.基本类型的变量保存原始值,即它代表的值就是数值本身:而引用类型的变量保存引用值,"引用值"指向内存空间的地

(转载)理解Java中的引用传递和值传递

关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习和分析一下,着急可以先看最后的结论. 1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型.基本类型的变量保存原始值,即它代表的值就是数值本身:而引用类型的变量保存引用值,"引用值"指向内存空间的地址,代表了某

Java中没有引用传递只有值传递(在函数中)

◆传参的问题 引用类型(在函数调用中)的传参问题,是一个相当扯的问题.有些书上说是传值,有些书上说是传引用.搞得Java程序员都快成神经分裂了.所以,我们最后来谈一下“引用类型参数传递”的问题. 如下例子,假设现在要把刚才创建的那一坨字符串打印出来,我们会使用如下语句: StringBuffer str = new StringBuffer(); System.out.println(str); //这个语句又是什么意思捏?这时候就两说了. 第一种理解:可以认为传进函数的是str这个指针,指针说

关于java中是引用传递还是值传递的问题!!!经常在笔试中遇到,今天终于弄明白了!

关于JAVA中参数传递问题有两种,一种是按值传递(如果是基本类型),另一种是按引用传递(如果是對象).首先以两个例子开始:1)public class Test2 { public static void main (String [] args) { StringBuffer a = new StringBuffer ("A"); StringBuffer b = new StringBuffer ("B"); operate (a,b); System.out.

Java技术_Java千百问(0039)_引用传递和值传递有什么区别

点击进入_更多_Java千百问 1.什么是值传递 值传递,是将内存空间中某个存储单元中存放的值,传送给另一个存储单元.(java中的存储单元并不是物理内存的地址,但具有相关性) 例如: //定义了一个改变参数值的函数 public static void changeValue(int x) { ??x = x *2; } public class TestMain{ //调用该函数 int num = 5; System.out.println(num); changeValue(num);

Java Object 引用传递和值传递

Java Object 引用传递和值传递 @author ixenos Java中的引用传递: 除了在将参数传递给方法(或函数)的时候是"值传递",传递对象引用的副本,在任何用"="向引用对象变量赋值的时候都是"引用传递",传递对象的引用给另一个变量. 参数传递,传递引用的副本,这看起来是引用传递,实则是传递了副本,这已经是值传递的概念了: 变量赋值,传递引用,这算引用传递 Java参数传递中没有引用传递都是值传递 1.在 Java 应用程序中永

请注意,java中没有引用传递-----转载

1 说明:本文的适用对象为java初学者.如果有读者发现文章中有叙述不妥之处,请指正. 2 3 今天在论坛上有人提了一个关于java中调用函数时有没有引用传递的问题,可谓是吵的不可开交.有人说java只有值传递,也有人说java既有值传递也有引用传递,那么java中到底有没有引用传递呢,下面我来分析一下. 4 5 一.首先来明确一下"值传递"和"引用传递的"区别 6 7 值传递:是对所传递参数进行一次副本拷贝,对参数的修改只是对副本的修改,函数调用结束,副本丢弃,原

请注意:java中没有引用传递

说明:本文的适用对象为java初学者.如果有读者发现文章中有叙述不妥之处,请指正. 今天在论坛上有人提了一个关于java中调用函数时有没有引用传递的问题,可谓是吵的不可开交.有人说java只有值传递,也有人说java既有值传递也有引用传递,那么java中到底有没有引用传递呢,下面我来分析一下. 一.首先来明确一下"值传递"和"引用传递的"区别 值传递:是对所传递参数进行一次副本拷贝,对参数的修改只是对副本的修改,函数调用结束,副本丢弃,原来的变量不变(即实参不变)引

java引用传递和值传递

关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习和分析一下,着急可以先看最后的结论. 1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型.基本类型的变量保存原始值,即它代表的值就是数值本身:而引用类型的变量保存引用值,"引用值"指向内存空间的地址,代表了某