把一个变量带进一个方法,该方法执行结束后,它的值有时会改变,有时不会改变。一开始会觉得--“好神奇呀”。当我们了解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. 自定义Dialog,从下面弹出

    Window window= getWindow(); 只要 打开一个Activity 就有一个窗口存放这个Activity ,手机又很多个窗口,不只是一个窗口 import android.app. ...

  2. struts2.0中struts.xml配置文件详解

    先来展示一个配置文件 <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration ...

  3. Servle资源注射

    Servle资源注射@WebServlet(name = "DownloadServlet",urlPatterns ="/DownloadServlet" ) ...

  4. jQuery学习笔记(一)--jQuery对象与DOM对象相互转换

    通过标准的JavaScript操作DOM与jQuyer操作DOM的对比,我们不难发现: 通过jQuery方法包装后的对象,是一个类数组对象.它与DOM对象完全不同,唯一相似的是它们都能操作DOM. 通 ...

  5. Submission

    EI: ICIC Express Letters: http://www.icicelb.org/elb/index.html IJICIC: http://www.ijicic.net/ijicic ...

  6. jsp:useBean的使用

    ->Bean的基本要素: 1.必须要有一个不带参数的构造器,在jsp元素创建Bean时会调用空构造器 2.Bean类应该没有任何公共实例变量,也就是说,不允许直接访问实例变量,通过setter/ ...

  7. google谷歌翻译插件-网页一键翻译

    上个月转载的一篇博文,是推荐的四款非常实用的翻译插件,这几天看这个chrome插件网首页有新增了一个google谷歌翻译插件.我能说实话,这款插件比之前推荐的4款翻译插件更好用吗?也不能完全说是更好用 ...

  8. window下面配置sftp

    Windows  下 搭建 基于  ssh 的sftp 服务器,服务器端可以用 freesshd,F-secure server 等,filezilla server不可用,之前傻乎乎的用filezi ...

  9. iOS 解决文本(uitextfield/uitextView)在中间显示而不在顶部显示 问题

    在对应的控制器中设置下面属性 self.automaticallyAdjustsScrollViewInsets = NO; 这样就好了.

  10. Shell学习笔记 ——第二天

    1.显示日期 date  |   cal   cal 2010  cal 2 2010 2.改变文件拥有者 chown 3.改变文件权限 chmod 4.显示当前目录 pwd 5.查看文件尾部内容,并 ...