zoukankan      html  css  js  c++  java
  • java参数传值方式

     java参数有值类型和引用类型两种。所以java参数的传值也就从这两个方面分析。
    从内存模型来说参数传递更为直观一些,这里涉及到两种类型的内存:栈内存(stack)和堆内存(heap)。
     
    基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。
    引用类型作为参数传递时,传递的是引用地址。所以在改变引用类型的值时,原值会改变。(String类型特殊,单独说)

    基本类型作为参数传递

    基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。

    代码如下:

     1 public class ParameterTransfer {
     2         public static void main(String[] args) {
     3             int num = 30;
     4             System.out.println("调用add方法前num=" + num);
     5             add(num);
     6             System.out.println("调用add方法后num=" + num);
     7         }
     8 
     9         public static void add(int param) {
    10             param = 100;
    11         }
    12     }
    View Code

    代码的运行结果如下:

    调用add方法前num=30
    调用add方法后num=30
    num的值在运行add()方法前后值并未改变,为什么呢?
    当执行了int num = 30;这句代码后,程序在栈内存中开辟了一块地址为AD8500的内存,里边放的值是30,内存模型如下图:

    执行到add()方法时,程序在栈内存中又开辟了一块地址为AD8600的内存,将num的值30传递进来,此时这块内存里边放的值是30,执行param = 100;后,AD8600中的值变成了100。内存模型如下图:

    引用类型作为参数传递

    引用类型作为参数传递时,传递的是引用地址。所以在改变引用类型的值时,原值会改变

    代码如下:

     1  public class ParameterTransfer {
     2         public static void main(String[] args) {
     3             String[] array = new String[] {"huixin"};
     4             System.out.println("调用reset方法前array中的第0个元素的值是:" + array[0]);
     5             reset(array);
     6             System.out.println("调用reset方法后array中的第0个元素的值是:" + array[0]);
     7         }
     8 
     9         public static void reset(String[] param) {
    10             param[0] = "hello, world!";
    11         }
    12 
    13     }
    View Code

    运行的结果如下:

    调用reset方法前array中的第0个元素的值是:huixin
    调用reset方法后array中的第0个元素的值是:hello, world!

     

    当程序执行了String[] array = new String[] {"huixin"}后,程序在栈内存中开辟了一块地址编号为AD9500内存空间,用于存放array[0]的引用地址,里边放的值是堆内存中的一个地址,示例中的值为BE2500,可以理解为有一个指针指向了堆内存中的编号为BE2500的地址。堆内存中编号为BE2500的这个地址中存放的才是array[0]的值:huixin。

    当程序进入reset方法后,将array的值,也就是对象的引用BE2500传了进来。这时,程序在栈内存中又开辟了一块编号为AD9600的内存空间,里边放的值是传递过来的值,即AD9600。可以理解为栈内存中的编号为AD9600的内存中有一个指针,也指向了堆内存中编号为BE2500的内存地址,如图所示:
    这样一来,栈内存AD9500和AD9600(即array[0]和param的值)都指向了编号为BE2500的堆内存。
    在reset方法中将param的值修改为hello, world!后,内存模型如下图所示:
    改变对象param的值实际上是改变param这个栈内存所指向的堆内存中的值。param这个对象在栈内存中的地址是AD9600,里边存放的值是BE2500,所以堆内存BE2500中的值就变成了hello,world!。程序放回main方法之后,堆内存BE2500中的值仍然为hello,world!,main方法中array[0]的值时,从栈内存中找到array[0]的值是BE2500,然后去堆内存中找编号为BE2500的内存,里边的值是hello,world!。所以main方法中打印出来的值就变成了hello,world!
    无论是基本类型作为参数传递,还是对象作为参数传递,实际上传递的都是值,只是值的的形式不用而已。第一个示例中用基本类型作为参数传递时,将栈内存中的值30传递到了add方法中。第二个示例中用对象作为参数传递时,将栈内存中的值BE2500传递到了reset方法中。当用对象作为参数传递时,真正的值是放在堆内存中的,传递的是栈内存中的值,而栈内存中存放的是堆内存的地址,所以传递的就是堆内存的地址。这就是它们的区别。
    注意:在Java中,String是一个引用类型,但是在作为参数传递的时候表现出来的却是基本类型的特性,即在方法中改变了String类型的变量的值后,不会影响方法外的String变量的值。原因可能有以下两个:
    • 一个是String实际上操作的是char[],可以理解为String是char[]的包装类。
    • 二是给String变量重新赋值后,实际上没有改变这个变量的值,而是重新new了一个String对象,改变了新对象的值,所以原来的String变量的值并没有改变。

    参考文章:http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html

  • 相关阅读:
    雷林鹏分享:EJB安全
    雷林鹏分享:EJB事务管理
    雷林鹏分享:EJB Blobs/Clobs
    雷林鹏分享:EJB嵌入对象
    雷林鹏分享:EJB拦截器
    Linux 学习
    数学知识总结
    信贷风控模型开发----模型流程&好坏样本定义
    信贷风控模型开发----模型简介
    TreeMap源码剖析
  • 原文地址:https://www.cnblogs.com/uodut/p/6430630.html
Copyright © 2011-2022 走看看