把一个变量带进一个方法,该方法执行结束后,它的值有时会改变,有时不会改变。一开始会觉得--“好神奇呀”。当我们了解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. SELinux开启和关闭

    1.查看SELinux状态 /usr/sbin/sestatus -v 2.关闭SELinux (1)临时关闭(不用重启机器): setenforce 0 #设置SELinux成为permissive ...

  2. Vultr新加坡机房速度怎么样?值得购买吗?最新评测!

    2016年9月,Vultr vps开通了新加坡Singapore机房线路.与知名的竞争对手Digitalocean和Linode一样,新加坡机房对亚洲速度友好,是讨用户欢心的一个进步. 但是,vult ...

  3. erlang虚拟机代码执行原理

     转载:http://blog.csdn.NET/mycwq/article/details/45653897 erlang是开源的,很多人都研究过源代码.但是,从erlang代码到c代码,这是个不小 ...

  4. 关于_cmd

    实际上是该方法名(@selector的名称). 比如: - (void)someCategoryMethod { NSString *string = objc_getAssociatedObject ...

  5. DiskGenius(磁盘分区/数据恢复) 32位 V4.9.1 免费绿色版

    软件名称: DiskGenius(磁盘分区/数据恢复) 32位 软件语言: 简体中文 授权方式: 免费软件 运行环境: Win 32位/64位 软件大小: 19.5MB 图片预览: 软件简介: Dis ...

  6. python第五天

    反射 hasattr,getattr class Foo: static_name = 'nba' def __init__(self): self.name = 'alex' def show(se ...

  7. hdu1034

    #include<stdio.h>const int MAXN=1000;int a[MAXN];int main(){ int n; int i; while(scanf("% ...

  8. 4-Bom&Dom总结篇

    其实Bom就是指浏览器的东西,比如弹窗啊.浏览器信息啊等 而Dom则是指文档的东西,就是浏览器里边html的东西,如元素啊.属性啊.事件什么的 但Bom的唯一顶层对象window又包含Dom的顶层对象 ...

  9. [NYLG-OJ] 77 开灯问题(白书例题)

    #include<stdio.h> int main() { int a[1010]={0}; //储存灯的开闭情况 int n,k,i,j; scanf("%d%d" ...

  10. 初级AD域渗透系列

      net group /domain 获得所有域用户组列表 net group “domain admins” /domain 获得域管理员列表 net group “enterprise admi ...