把一个变量带进一个方法,该方法执行结束后,它的值有时会改变,有时不会改变。一开始会觉得--“好神奇呀”。当我们了解java内存分析的知识后,一切都是那么简单明了了--“哦,这么回事呀”。但是今天的上机课,对于引用变量,我犯了一个错误,下面是代码的简化--

void method(int a[])
{
    int temp[]={1,2,3,4};
    a[0]=5;
    a=temp;
}

在这里,我试图把临时数组变量的值赋给a,从而改变实参的值。

方法传参,分传值和传址,基本数据类型变量的传参传的是值;引用变量传参传的是地址。传入的参数,实际是实参的一份拷贝。因为,当我们调用一个方法时,逻辑上,jvm会开辟一个我们称之为栈区的内存,当方法运行结束后,这段内存也就被释放了。我们传入的实参的拷贝的生命也仅限于这段栈区,这便是局部变量的宿命。对于基本数据变量,由于它的值是存在栈区的,且与调用该方法的函数的栈内存是独立的,所以影响不到该函数。引用变量的值是地址,它指向堆区的某个地址,这是一个被共享的内存。我们对其的操作就是操作堆区的数据(继续看下文,这句话是不严谨的)。

这是之前我对传参的理解。用它来理解今天的问题,也是没有问题的。但却忽略了一个问题。

既然传入引用变量是传址的,那么上面的代码为什么不能如愿改变它的值呢?

当我们注意到上文说,传参实际是实参的一份拷贝,引用变量也是如此,而且,引用变量也是存在栈区的。那么,我的“a=temp”是在栈区上改变数据(他们的值仅是地址,不能影响堆内存的对象),而且是拷贝而来的数据。

于是:被调用的方法,在堆内存的操作在方法执行结束后才是有效的。变量名永远是存在栈区的(独立,不被共享),引用变量也是如此。

同样的:

void alg1(int a[])//引用变量指向堆内存对象上的操作,是可以改变传入参数变量的
{
    int t[]=a;//把a的值,即指向对象的地址赋值给t
    for(int i=0; i<a.length; i++)
        t[i]=i;
}
void alg2(int a[])//虽然看似对该变量的操作,却不是同一个对象的引用了
{
    int t[]=a;//把a的值,即指向对象的地址赋值给t
    a=new int[5];
    for(int i=0; i<a.length; i++)
        a[i]=t[i]*t[i];
}

《算法设计与分析》中对于方法调用的描述:

通常,在一份算法中调用另一个算法时,系统需要在运行被调用算法之前完成3件事:

  (1)将所有实参指针,返回地址等信息传递给调用算法;

  (2)为被调用算法的局部变量分配储存区;

  (3)将控制转换到被调用算法的入口。

在从被调用算法返回调用算法时,系统也相应地要完成3件事:

  (1)保存被调用算法的计算结果;

  (2)释放分配给被调用算法的数据区;

  (3)依照被调用算法保存的返回地址将控制转移到调用算法。

再谈Java方法传参那些事的更多相关文章

  1. java 方法传参方式: 按值调用

    程序设计语言中将参数传递给方法的几种方式: 按名调用(call by name): Algol 语言采用此方式, 已成为历史; 按值调用(call by value): 方法接收到的是调用者提供的 变 ...

  2. Java方法传参,测试在方法内部改变参数内容是否会影响到原值

    我分了三种类型的参数进行测试 一.基本类型 public static void main(String[] args) { System.out.println("验证基本类型int作为参 ...

  3. Java方法传参的问题

    1.基本数据类型(byte,short,int,long,float,double,boolean,char)的值传递,不改变其值 2.引用数据类型的值传递,改变其值 3.String类型虽然是引用数 ...

  4. 浅谈对java中传参问题的理解

    之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...

  5. java的方法传参,最容易混淆的问题!!!

    参数传递 参数传递,可以理解当我们要调用一个方法时,我们会把指定的数值,传递给方法中的参数,这样方法中的参数就拥有了这个指定的值,可以使用该值,在方法中运算了.这种传递方式,我们称为参数传递. 在这里 ...

  6. Java 常用类库一,main方法传参String[] args;获取输入Scanner ;hasNext();hasNextInt()

    1. main方法传参 package com.zmd.common_class_libraries; /** 给mian方法传参测试 */ public class MainArgsTest { p ...

  7. 关于Java函数传参以及参数在函数内部改变的问题——JAVA值传递与引用最浅显的说明!

    看了很多关于阐述JAVA传参到底是值传递还是引用的问题,有些说得很肤浅让人感觉似懂非懂的感觉,但是好像又能解决一些问题,然后就止步了.还有一些则是,讲得很深奥,看着好像很有道理的样子,但是其实还是没怎 ...

  8. javascript 字符串方法传参

    javascript 字符串方法传参由于嵌套的单引号,双引号过多.有点混乱.. 正确方法如下: '   <td align="left"><input type= ...

  9. 对象引用 方法传参 值传递 引用传递 易错点 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

随机推荐

  1. Lintcode解题报告

    1. Num.196 寻找缺失的数 给出一个包含 0 .. N 中 N 个数的序列,找出0 .. N 中没有出现在序列中的那个数. 注意事项 可以改变序列中数的位置. 您在真实的面试中是否遇到过这个题 ...

  2. WPS Office 二次开发简易教程。

    http://bbs.wps.cn/forum.php?mod=viewthread&tid=22004642

  3. Winform_devexpress开发框架主界面设计

    做了好多年的C#开发,从.Net.Winform及第三方的DevExpress.无论什么样的系统,主界面的设计及风格无疑非常重要.从客户的角度考虑,要求功能区清晰,整体美观大方,这样才会有可能从第一视 ...

  4. 【转】gcc/g++ 如何支持c11 / c++11标准编译

     如果用命令 g++ -g -Wall main.cpp  编译以下代码 : 1 2 3 4 5 6 7 8 9 10 11 12 /*     file : main.cpp */ #include ...

  5. linux命令之crontab详解

    crontab命令: crontab -l : 显示定时任务列表 crontab -e: 编辑定时任务 crontab -r : 删除所有定时任务 基本格式 :  * * * * * command  ...

  6. KMP 算法 学习 整理

    我自己整理的KMP算法的PDF文件:http://pan.baidu.com/s/1o8yKIi2提取密码:8291 别的就不多说啥了,感谢来自海子 博客园的 资料--

  7. IOS 基于TCP的socket通信详解(原创)

    最近在整理通信层相关知识,这篇文章是边整理边写的,有些地方可能不够准确,还请各位路过的大牛专家指出来.这次整理的socket通信是基于TCP的,实现方式是GCD形式,以下记录的都是些理论知识,方便自己 ...

  8. Hbase压力测试

    PerformanceEvaluation是HBase自带的性能测试工具,该工具提供了顺序读写.随机读写.扫描等性能测试功能.本文简要介绍HBase PerformanceEvaluation的使用方 ...

  9. ContourLine

    #define MULTI_PLOT true //Determine whether or not to plot multiple iterations. #define X_MAX 1.0 // ...

  10. Ubuntu 14.04 配置FTP

    配置Ubuntu 14.04的FTP服务,通过Windows远程访问Ubuntu 14.04的同时,可以实现windows和Ubuntu之间的文件交换传输.在多用户环境下,每一个用户都可以通过自己的帐 ...