java中函数是值传递还是引用传递?

lilwm344 8年前
   <p>相信有些同学跟我一样,曾经对这个问题很疑惑。在网上也看了一些别人说的观点,评论不一。有说有值传递和引用传递两种,也有说只有值传递的,这里只说下个人见解</p>    <p>先看一个例子</p>    <pre>  <code class="language-java">public class Test1 {        public static void main(String[] args) {          int a = 10;          changeNum(a);          System.out.println("main a=" + a);      }            static void changeNum(int a) {          a = 100;          System.out.println("changeNum a=" + a);      }  }  </code></pre>    <p>结果:</p>    <p>changeNum a=100</p>    <p>main a=10</p>    <p>说明对于基本的数值类型其实传递的是一份数值的拷贝,传入函数之后跟原来的值就没有关系了,在函数中改变这个数的值也不会影响到原来的值。</p>    <p>再看一个例子</p>    <pre>  <code class="language-java">public class P {      String name = "P";      public P(String name) {          this.name = name;      }      @Override      public String toString() {          return name;      }  }    public class Test {      static P p1 = new P("p1");      public static void main(String[] args) {          P p = new P("P");                   System.out.println("before change p:" + p.toString);          changeObj(p);          System.out.println("after change p:" + p.toString());      }        static void changeObj(P p) {          p = new P("pp");          System.out.println("change p:" + p.toString());          //p = p1;          //System.out.println(p.toString());      }  }  </code></pre>    <p>这个例子中的运行结果会是什么呢?</p>    <p>在这个例子中传入的是一个对象类型的数据。</p>    <p>我们先来猜想一下:如果传入的是一个对象的引用,在函数中改变了这个引用所指向的对象,那么外部的引用"p"应该是指向了新创建的P("pp")的对象才对</p>    <p>所以猜想的结果是:</p>    <p>before change p:P</p>    <p>change p:pp</p>    <p>after change p:pp</p>    <p>那让我们来实际运行一下看看结果,实际的结果是:</p>    <p>before change p:P</p>    <p>change p:pp</p>    <p>after change p:P</p>    <p>想猜想的不一样!!!</p>    <p>这就让我们很疑惑了,为什么函数没有改变引用所指向对象呢?</p>    <p>其实是这样的,首先要理解“=”赋值操作的意义,</p>    <p>对于基本类型来说“=”赋值操作是直接改变内存地址上的值,</p>    <p>而对引用类型来说“=”赋值其实是改变引用变量所指向的内存地址。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6dd964df961e9e057e7e3086c2bcd39e.png"></p>    <p>赋值操作后</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/d9f2d9d16db1b654e28f1c536413bf54.png"></p>    <p>引用的赋值并没有对原来的对象造成影响,"hello"对象仍然是存在的,只是str又指向了新的"world"对象</p>    <p>理解了赋值操作后,现在来说下函数的参数传递</p>    <p>函数的参数实际上就是函数内部的一个局部变量,从外部传值给这个参数实际上就是一个赋值的过程。</p>    <p>来看看第一个例子,传一个定义一个int类型名称为a的形式参数,其实完全可以把名称改为b</p>    <p>然后把外部变量a的值传递给函数的变量,就是赋值。基本类型的赋值就是把外部a变量的10赋值给函数变量a,所以这其实是两个变量,两者之间没有任何关系,</p>    <p>所以对函数内部变量的改变也不会对外部的变量造成影响。</p>    <p>再来说下引用类型的传递,其实是一个道理。</p>    <p>在传递的时候是把一个对象的内存地址赋值给函数内部的引用类型的局部变量</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/5673d08760d63676af1f8d7af3ed1d07.png"></p>    <p>如上图所示,两个变量是指向同一个对象的。</p>    <p>在第二个例子中,我们在函数内部新创建了一个对象,并重新赋值给内部变量p,其实是改变了内部变量的引用所指向的对象,如下图所示</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/76495a8c14ce4812303725af93b548cb.png"></p>    <p>所以对外部的p变量是没有影响的。</p>    <p>总结:</p>    <p>函数参数传递其实是一个赋值的过程,基本类型传递的是数值,引用类型传递的引用对象的内存地址。</p>    <p>另外一点要特别注意,函数的参数其实是函数内部的局部变量。不要跟外部变量混淆</p>    <p> </p>    <p> </p>    <p>来自:http://www.cnblogs.com/taixuyingcai/p/6373423.html</p>    <p> </p>