java按值传参与按引用传参_旺旺老师Java学习解决方案_第一季

讲解:按值传参与按引用传参

-------------------------------------------------------------------------------

类中包含方法,方法又分为方法声明和方法实现,方法声明中又有参数列表,参数根据调用后的效果不同,即是否改变参数的原始数值,又可以分为两种:按值传递的参数与按引用传递的参数。

他们的区别是什么呢?上面旺旺老师是说调用后的效果,我们看一个案例说明:比如有个女孩非常喜欢QQ,还给自己起了个浪漫的名字“轻舞飞扬”,飞扬小姐认识了一个网友“痞子蔡”(n年前非常火的一个网络小说《第一次亲密接触》的两个主人公),他们聊的很投缘,有天飞扬小姐竟然把自己的电话号码告诉了痞子蔡,有天痞子蔡竟然电话过来约飞扬小姐见面,考虑到网络的虚幻与现实人心的叵测,飞扬小姐面临着艰难的选择:是否去见网友?

那么见网友就是个方法,方法的参数就是轻舞飞扬,如果痞子蔡是个披着羊皮的狼,那飞扬小姐就可能面临危险,比如身上少些东西或者多些东西,就是说在方法体中有可能改变参数的原始数值。

现实中飞扬小姐只有两种选择,第一,为了爱情奋不顾身,上刀山下火海,再所不辞,但这有可能改变飞扬状态,即数值;第二,委婉拒绝以求自保,但如果痞子蔡为人特别好,比如像旺旺老师这样(呕吐中),她也许会失去一段大好的姻缘。这里,如果科技足够发达,我们可以完全给出第三种选择,轻舞飞扬制作一个自己的替身,即把自己备份一份,然后把备份传入方法体,这样不论痞子蔡对她做了什么都不会对她的源体发生影响,又能检测痞子蔡对自己是否真心。

OK,这里我们就把飞扬小姐本人去见网友叫按引用传递,这样在方法体中发生的改变在方法调用完对参数还有影响,而把让她替身去叫按值传递,这样方法调用完对参数原始数值没有影响,发生改变的只是参数的备份,这份备份在方法调用完会自动消亡,也就是说飞扬的替身在见完网友自动消亡。最后可以简单概括为一句话:按值传递参数数值不变,按引用传递参数数值改变

我们上面刚学习了JAVA的数据类型,则有:值类型就是按值传递的,而引用类型是按引用传递的。下面看一个例子:

public class TestValueAndRef {

    public static void main(String[] args) {

       Student student = new Student();

       student.stuAge = 10;

       int a = 10;

       int arr[] = new int[]{9, 5, 27};

      

       System.out.println("初始值 a = " + a);

       System.out.println("初始值 student.stuAge = " + student.stuAge);

       System.out.println("初始值 arr[0] = " + arr[0]);

      

       TestValueAndRef testValueAndRef = new TestValueAndRef();

       testValueAndRef.change(a, student, arr);

      

       System.out.println("调用函数后 a = " + a);

       System.out.println("调用函数后 student.stuAge = "

+ student.stuAge);

       System.out.println("调用函数后 arr[0] = " + arr[0]);

    }

    public void change(int pa, Student pstu, int[] parr) {

       //方法体中改变值类型pa的值

       pa = pa + 10;

       //方法体中改变引用类型stu,parr的值

       pstu.stuAge = pstu.stuAge + 10;

       parr[0] = parr[0] + 10;

      

       System.out.println("方法体改变后pa = " + pa);

       System.out.println("方法体改变后pa = " + pa);

       System.out.println("方法体改变后parr[0] = " + parr[0]);

    }

}

运行结果:

初始值 a = 10

初始值 student.stuAge = 10

初始值 arr[0] = 9

 

方法体改变后pa = 20

方法体改变后pa = 20

方法体改变后parr[0] = 19

 

调用函数后 a = 10

调用函数后 student.stuAge = 20

调用函数后 arr[0] = 19

 

我们看到,基本数据类型int变量a虽然在方法体中改变了数值,但方法调用完后其原始数值并没有改变。而引用数据类型Student在方法体中改变年龄的数值,方法执行完其数值发生了改变,数组也是引用类型,所以其值也发生了改变。也就是说:按值传递参数数值不变,按引用传递参数数值改变。它们在内存中的变化如下所示:

根据上面讲解的值类型和引用类型的知识,int类型变量在栈中分配一块内存,而studentarr分配两块内存,当方法调用时,创建三个变量pa,pstu,parr这里相当于把栈中的数据全备份一份给这三个数值,则有:

大家看到,不管是按值传递还是按引用传递,都是把栈中的数据备份了一份给参数变量,只不过值类型备份的是具体的数值,而引用类型备份的是内存地址

方法体执行完时:

我们看到,根据pstuparr改变了堆中的具体数值,而pa改变的只是栈中的数值。最后方法调用结束,pstu,pa,parr三个变量消亡,则有:

根据这样的内存变换,您知道按值传递与按引用传递的深层原因了吗?

讲解:特殊的String类

-------------------------------------------------------------------------------

接下来我们看一个特例String类型,虽然它也是引用类型,但数值却不会改变。例:

public class TestString {

    public static void main(String[] args) {

      

       String name = "wangwang";

      

       TestString testString = new TestString();

       System.out.println("方法调用前:" + name);

       testString.change(name);

       System.out.println("方法调用后:" +name);

    }

    public void change(String str) {

       str = "旺旺老师";

       System.out.println("方法体内修改值后:" + str);

    }

   

}

 

运行结果:

方法调用前:wangwang

方法体内修改值后:旺旺老师

方法调用后:wangwang

 

    上例中,虽然参数String是引用数据类型,但其值没有发生改变,这是因为String类是final的,它是定长,我们看初始情况,即String name = "wangwang";这行代码运行完,如下图:

当调用方法时testString.change(name),内存变化为:

在方法体内,参数str赋予一个新值,str = "旺旺老师"因为String是定长,系统就会在堆中分配一块新的内存空间37DF,这样str指向了新的内存空间37DF,而name还是指向36DF37DF的改变对它已没影响。

最后,方法调用结束,str37DF的内存空间消亡。Name的值依然为wangwang,并没有改变。所以String虽然是引用类型参数,但值依然不变

 

其他:旺旺老师视频与电子书下载地址:http://www.verycd.com/groups/@g481346/790989.topic

 

评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值