`

重谈Java的中的参数传递

阅读更多

      最近在复习Java的基础知识,看到自己以前的技术博客里谈到Java中关于参数传递的问题,分析得不够准确,决定再总结一番。

      Java里方法的参数传递方式只有一种:值传递。值传递,就是将实际参数值的副本(复制品)传入方法内,而参数本身不会受到任何影响。

 public class PrimitiveTransferTest
      {
            public static void swap(int a,int b)
             {
                     int temp=a;
                     a=b;
                     b=temp;
                     System.out.println("swap方法里,a的值是"+a+";b的值是"+b);
              }
              public static void main(String args[])
              {
                      int a=6;
                      int b=9;
                      swap(a,b);
                      System.out.println("交换结束后,变量a的值是"+a+";变量b的值是"+b);
               }
          }

 运行结果:

          swap方法里面,a的值是9;b的值是6;

          交换结束后,变量a的值是6;变量b的值是9;

         从运行结果可以看出,main方法里面的变量a和b,并不是swap方法里面的a和b。,也就是说swap方法的a和b只是main方法里面变量a和b的复制品。

 Java程序从main方法开始执行,main方法开始定义了a、b两个局部变量,当程序执行swap方法时,系统进入swap方法,并将main方法中的a、b变量作为参数值传入swap方法,传入swap方法的只是a/b的副本,而不是a、b本身,进入swap方法后系统产生了4个变量,main栈区的a和b,swap栈区的a和b。

        在main方法中调用swap方法时,main方法还未结束。因此,系统分别为main方法和swap方法分配两块栈区,用于保存main方法和swap方法的局部变量。main方法中的a、b变量作为参数值传入swap方法,实际上是在swap方法栈区中重新产生了两个变量a、b,并将main方法栈区中a、b变量的值分别赋给swap方法栈区中a、b参数(就是对swap方法的a、b形参进行了初始化)。此时,系统存在两个a变量,两个b变量,只是存在于不同的方法栈区中而已。两个输出,一个是输出swap方法中的a、b,一个是main方法中的a、b,程序只是改变的是swap方法中的a、b,而main方法中的a、b并没有改变。这就是值传递的实质:当系统开始执行方法时,系统为形参执行初始化,就是把实参变量的值赋给方法的形参变量,方法里操作的并不是实际的实参变量。

       前面是基本类型的参数传递,Java对于引用类型的参数传递,一样采用的是值传递方式。

 class DataWrap
       {
            public int a;
            public int b;
       }
       public class ReferenceTransferTest
       {
            public static void swap(DataWrap dw)
            {
                     int tmp=dw.a;
                     dw.a=dw.b;
                     dw.b=tmp;
                     System.out.println("swap方法里,a 属性的值是"+dw.a+";b属性的值是"+dw.b);
            }
            public static void main(String args[])
            {
                    DataWrap dw=new DataWrap();
                    dw.a=6;
                    dw.b=9;
                    swap(dw);
                    System.out.println("交换结束后,a属性的值是"+dw.a+";b属性的值是"+dw.b);
            }
  }

 运行结果:

     swap方法里,a属性的值是9;b属性的值是6

     交换结束后,a属性的值是9;b属性的值是6

      从运行结果来看,swap方法和main方法的a、b两个属性值都被交换了,这很容易造成一种错觉:调用swap方法时,传入swap方法的就是dw对象本身,而不是它的复制品。但这只是一种错觉。

      程序从main方法开始执行,main方法开始创建了一个DataWrap对象,并定义了一个dw引用变量来指向DataWrap对象,这是一个与基本类型不同的地方。创建一个对象时,系统内存中有两个东西:堆内存中保存了对象本身,栈内存中保存了引用该对象的引用变量。接下来,main方法中开始调用swap方法,main方法并未结束,系统会分别开辟出main和swap两个栈区,用于存放main和swap方法的局部变量。调用swap方法时,dw变量作为实参传入swap方法,同样采用值传递方式:把main方法里dw变量的值赋给swap方法里dw形参,从而完成swap方法的单位形参的初始化。值得指出的是,main方法的dw是一个引用,它保存了DataWrap对象的地址值,当把dw的值赋给swap方法的dw形参后,即让swap方法的dw形参也保存这个地址值,即也会引用到堆内存中的DataWrap对象。当程序在swap方法中操作dw形参时,由于dw只是一个引用变量,故实际操作的还是堆内存中的DataWrap对象。此时,不管是操作main方法里的dw对象,还是操作swap方法里的dw参数,起始都是操作它所引用的DataWrap对象,它们操作的是同一个对象。因此,当swap方法中交换dw参数所引用的DataWrap对象的a、b两个属性时,我们可以看到main方法中dw变量所引用的DataWrap对象的a、b两个属性值也被交换了。

       为了更好地证明main方法中的dw和swap方法中的dw是两个变量,我们在swap方法的最后一行增加如下代码:

      dw=null;//把dw直接赋值为null,让它不再指向任何有效地址

      然后,main方法调用了swap方法后,再次访问dw变量的a、b两个属性,依然可以输出9、6。把swap方法中的dw赋值为null后,swap方法中失去了DataWrap的引用,不可在访问堆内存中的DataWraper对象。但main方法中的dw变量不受任何影响,依然引用DataWrap对象,所以依然可以输出DataWrap对象的a、b属性值。

分享到:
评论

相关推荐

    浅谈Java中方法的参数传值.pdf

    综上所述,通过Java方法参数传递的知识点,我们可以更深入地理解Java程序的运行机制以及变量、数据类型和方法调用之间的关系。这不仅帮助编程者更好地组织代码结构,还能够在调试过程中快速定位问题所在,提高开发...

    浅谈Java中的参数传递问题

    "Java中的参数传递问题详解" Java中的参数传递问题是Java编程语言中一个非常重要的概念,对于初学者和专业开发者都具有重要的参考价值。在这篇文章中,我们将通过示例代码和实践经验,详细介绍Java中的参数传递问题...

    浅谈Java中方法参数传递的问题

    对于 String 类型,虽然它是一个引用类型,但是在方法参数传递中,它的行为类似于基本类型。因为字符串的本质是一个字符数组,在方法区中有专门的一块地方叫字符串常量池用来存储字符串常量。例如: ```java public...

    浅谈Java中方法的参数传值.zip

    总结来说,Java中的方法参数传递涉及到值传递(对于基本类型)和对象引用的值传递(对于对象类型)。理解这些概念有助于编写更高效、可维护的代码。在实践中,要注意区分对象状态的修改和对象引用的改变,以及如何...

    浅谈JAVA内存分配与参数传递

    JAVA参数传递是JAVA编程语言中的一种函数调用机制,决定了函数参数的传递方式。下面对JAVA内存分配和参数传递进行详细的介绍。 JAVA内存分配 JAVA内存分配是指JAVA程序在内存中的存储方式。JAVA内存分配可以分为五...

    浅谈Java中真的只有值传递么

    特殊的是,String虽然是一种引用类型,但在参数传递中表现得像是值传递。这是因为String是不可变的,当我们对String对象进行赋值操作时,实际上创建了一个新的String对象。例如,在例子3中,change()方法中param = ...

    浅谈JavaScript 函数参数传递到底是值传递还是引用传递

    JavaScript中的函数参数传递机制一直以来都是开发者讨论的热点。在传统观念中,JavaScript的参数传递常被误解为引用传递,即类似C++或C中的指针传递。然而,JavaScript的实现其实更为复杂,它包含了值传递和引用传递...

    java jvm调优浅谈

    Java JVM 调优浅谈 Java 虚拟机(JVM)是 Java 语言的核心组件之一,...因为 Java 中没有指针的概念,程序运行永远都是在栈中进行的,因而参数传递时,只存在传递基本类型和对象引用的问题。不会直接传递对象本身。

    谈java图像处理技术

    ### 谈Java图像处理技术 #### Java 2D中的图像处理模型 Java 2D是一种用于绘制图形、处理图像的技术框架,它为开发者提供了一系列高级API,使得图像处理变得更加简单高效。Java 2D中的图像处理模型主要采用即时...

    java web学习_浅谈request对象中get和post的差异

    在输出结果中,我们可以看到 GET 方法的输出结果是通过 URL 传递参数的,而 POST 方法的输出结果是通过 Request 体来传输数据的。 4. 对比分析 在输出页面按下 F12 查看,我们可以看到 GET 方法的请求头中包含参数...

    浅谈Java中的可变参数

    Java中的可变参数(Variable-Argument Parameters)是一个强大的特性,它允许我们在方法声明中使用一个可变数量的参数。这个特性使得我们无需为每个参数数量创建不同的方法重载,简化了代码并提高了可读性。下面我们...

    浅谈JAVA中多线程的实现.pdf

    然后,将这个实现了Runnable接口的对象作为参数传递给Thread类的构造器,从而创建一个Thread类的实例。调用这个Thread实例的start()方法,即可启动线程。 文章中也提供了兔子和乌龟赛跑的Runnable接口版本的实现...

    浅谈JAVA回调机制1

    总之,Java回调机制是提高代码灵活性和可扩展性的重要工具,通过将行为传递给其他对象,我们可以实现更复杂的控制流和异步操作,同时保持代码的清晰和模块化。在实际开发中,合理运用回调可以大大提高代码的可维护性...

    浅谈Java中是否直接可以使用enum进行传输

    Java 中使用 enum 进行传输的可行性分析 在 Java 中,使用枚举类型(enum)来表示状态或状态值是一种非常常见的做法。但是,在将枚举类型用于传输时,需要注意一些问题。在本文中,我们将探讨 Java 中是否可以直接...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    3.4 小结:基本数据类型—— Java中一切数据和运算的基础 63 3.5 习题 65 第4章 Java中的程序执行流程 67 教学视频:1小时57分钟 4.1 顺序执行 67 4.2 使用if-else让程序懂得判断 68 4.2.1 if语句 68 4.2.2 ...

    浅谈为什么java命令运行class文件出现异常共7页.p

    Java命令行运行class文件是Java开发中的基本操作,主要用于测试和执行编译后的Java程序。然而,有时在尝试运行class文件时可能会遇到各种异常情况,这些异常可能是由于多种原因引起的。这里我们将深入探讨可能导致...

    从追MM浅谈Java的23种设计模式

    Java的23种设计模式是软件工程中的一种经典思想,它们是解决常见编程问题的成熟解决方案,被广泛应用于各种项目中。设计模式并不是特定的代码或库,而是对在特定情境下,如何组织代码和交互的一种描述。这些模式是...

    浅谈Java在线开放课程建设.pdf

    同时,重要知识点如构造方法、关键字使用、参数传递等需要特别关注,设计多个教学案例来帮助学生理解和掌握。 3. 教学单元视频的制作:制作视频时,应保持教学内容的连贯性和系统性,通过实例讲解知识点,循序渐进...

Global site tag (gtag.js) - Google Analytics