IT技术博客大学习 共学习 共进步

java参数传递分析

JavaRanger 2014-11-19 23:22:02 浏览 2,703 次

   先看基本类型作为参数传递的例子:

public static void main(String[] args) {
        int param =100;
        System.out.println("before change param=" + param);
        changeInt(param);
        System.out.println("after change param=" + param);
    }
    public static void changeInt(int i){
         i = 1;
    }

   基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的,输出的结果证明了这一点:

   before change param = 100

   after change param = 100

   下面再来看看对象作为参数传递的例子:

public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");
        System.out.println("before change param="+sb);
        changeObj(sb);
        System.out.println("after change param="+sb);
    }
    public static void changeObj(StringBuffer sb){
        sb.append("World!");
    }

   先看输出结果:

   before change param = Hello

   after change param = Hello World!

   从结果来看,sb的值被改变了,那么是不是可以说:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。从上面例子的输出结果来看,这样解释是合理。

   现在我们对上面的例子稍加改动一下:

public static void changeObj(StringBuffer strBuf){
        strBuf = new StringBuffer("Hi ");
        strBuf.append("World!");
    }

   按照上面例子的经验:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。你会认为应该输出:

   before change param = Hello

   after change param = Hi World!

   但运行一下这个程序,你会发现结果是这样的:

   before change param = Hello

   after change param = Hello

   这就是让人迷惑的地方,对象作为参数传递时,同样是在方法内改变了对象的值,为什么有的是改变了原对象的值,而有的并没有改变原对象的值呢?这时候究竟是“传值”还是“传引用”呢?

   先看第一个程序

   StringBuffer sb = new StringBuffer(“Hello “);

   这一句执行完后,就会在内存的堆里生成一个sb对象,请看图1:

   1

   如图1所示,sb是一个引用,里面存放的是一个地址“@3a”(这个“@3a”是我举的代表内存地址的例子,你只需知道是个内存地址就行了),而这个地址正是“Hello ”这个字符串在内存中的地址。

   changeObj(sb);

   执行这一句后,就把sb传给了changeObj方法中的StringBuffer strBuf,由于sb中存放的是地址,所以,strBuf中也将存放相同的地址,请看图2:

   2

   此时,sb和strBuf中由于存放的内存地址相同,因此都指向了“Hello”。

   strBuf.append(“World!”);

   执行changeObj方法中的这一句后,改变了strBuf指向的内存中的值,如下图3所示:

   3

   所以,Test2 这个程序最后会输出:

   after change param = Hello World!

   再看第二个程序。

   在没有执行到changeObj方法的strBuf = new StringBuffer(“Hi “);之前,对象在内存中的图和上例中“图2”是一样的,而执行了strBuf = new StringBuffer(“Hi “);之后,则变成了:

   4

   此时,strBuf中存放的不再是指向“Hello”的地址,而是指向“Hi ”的地址“@3b” (同样“@3b”是个例子)了,new操作符操作成功后总会在内存中新开辟一块存储区域。

   strBuf.append(“World!”);

   而执行完这句后,

   5

   通过上图可以看到,由于sb和strBuf中存放地址不一样了,所以虽然strBuf指向的内存中的值改变了,但sb指向的内存中值并不会变,因此也就输出了下面的结果:

   after change param = Hello

   从上面可以知道,Java是将栈里的值拷贝了一份作为参数传到了方法里面。对于基本类型就是传的值了,而对于对象类型就是引用了。不管传的是值还是引用,都是栈里的拷贝。记住这一点应该就不会再有什么疑问了

建议继续学习

  1. Java技术路线 (阅读 7,642)
  2. perl模块Getopt::Std用法及实例-从命令行读取参数模块 (阅读 6,924)
  3. Java应用运维 (阅读 5,224)
  4. 千万不要把 bool 当成函数参数 (阅读 5,121)
  5. Java陷阱(2010版) (阅读 4,001)
  6. Java 常量值修改后不起作用 (阅读 3,902)
  7. 关于在函数调用时传递string引用的必要性 (阅读 3,884)
  8. Java的那些事儿 (阅读 3,762)
  9. Java将Object对象转换为String的总结合集 (阅读 3,703)
  10. Java泛型简明教程 (阅读 3,663)