对一道面试题的思考(java中的引用传递)

//说明输出结果:
public class Example {
  String str = new String("good");
  char[] ch = {'a','b','c'};
  public static void main(String[] args) {
     Example ex = new Example();
     ex.change(ex.str, ex.ch);
     System.out.print(ex.str +"and");
     System.out.print(ex.ch);  
  }

  public void change(String str, char ch[]){
     str= "test ok";
     ch[0]= 'g';
  }
}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

这道题的答案是: good and gbc

很多人都说java不存在引用传递,均为值传递,那我们就这么认为好了。
只是对于java中的基础数据类型byte char int long short float double boolean 在调用方法时传递的是其值,而当你要传递的是一个引用类型时,那么传递的就是他的内存地址(也是一种值)。

那么我们就根据下图来看此题的执行过程:

首先创建Example对象ex,创建String对象str,char[]对象ch,()内为其假设内存地址

这里写图片描述

那么当我们调用ex的change方法时,流程如下:
这里写图片描述

首先看change方法中对ch的操作:

ch[0]= 'g';

    1

这里写图片描述
change方法中的形参ch虽然只是ch引用的副本,但是由于其同样指向该内存地址,因此即使在change()方法执行完毕,形参ch被清除(释放),但还是对原数据进行了修改。

再来看看较为特殊的str:

str= "test ok";

    1

这里涉及到了String类型的不可变性,即String一旦被创建就不可修改,但平时使用中我们会觉得也对字符串进行了修改啊,但是在内存中并不是如此,当执行如下代码时,内存如下图所示:

String str = "hello world";
str = "hello";

    1
    2

这里写图片描述

由于String类型是不可变的当我们修改str的值时,相当于重新创建了一个新的字符串,并将引用指向新的字符串,原字符串由于不可到达,最终会被GC回收。

那么当执行change方法时,形参str的内存形式如下图:
这里写图片描述
当change方法执行完毕,该方法被分配的内存空间均得以释放!

而实参str的内存地址依然为3215,那么当输出时,则会输出该内存地址的值。

因此,此题答案为:good and gbc

总结:
在调用方法时,一定要主要区分实参与形参,形参是实参副本,形参在内存里是真实存在的,如本题中的实参str与形参str,虽然同名但却是两个变量(因此形参值的改变对实参没有任何影响),只是形参借用了实参的值而已。当我们调用方法时,形参被创建,当方法执行完成,形参被销毁。
---------------------
作者:givemeidea
来源:CSDN
原文:https://blog.csdn.net/givemeidea/article/details/52292319
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-07-20 22:20  天涯海角路  阅读(230)  评论(0)    收藏  举报