JAVA值传递和引用传递

来源:互联网 发布:买别人的淘宝店铺 编辑:程序博客网 时间:2024/06/05 00:48

放在首行的话:正在学习java,有什么不对的地方,请不吝批评指正,万分感谢!


在介绍java的值传递和引用传递之前,想先介绍java的数据类型都有哪些,还有java的各种数据类型在JVM的内存中是怎么样存储的。

一、Java的数据类型

java的数据类型总共有11种,分别是 byte short int long float double boolean char 数组 类 接口。

根据创建时存储方式的不同可以将这11种数据类型分为两大类:
基本类型:byte short int long float double boolean char 
引用类型:数组 类 接口

 二、各种数据类型创建时在JVM内存中的存储方式

首先,JVM的内存分为三部分:栈区、堆区、方法区(还没有深究)。


基本类型在创建的时候,JVM会在栈区划分一块内存来存储它。
引用类型在创建的时候,比如new 一个对象,会先在堆内存中划出一块区域来存储这个对象,然后呢,在栈区划分出一块区域来存储这个对象在堆中的地址。类似于这样:


三、Java的值传递和引用传递

1.值传递

先来运行一段代码:

public class Test{public static void main(String[] args){int a = 10;System.out.println("调用calc方法之前,a = " + a);calc(a);System.out.println("调用calc方法之后,a = " + a);}public static void calc(int a){a = a + 1;}}



得到的结果是什么呢?
调用calc方法之前,a = 10
调用calc方法之后,a = 10

发现,调用calc方法后, main方法中,int类型的变量a的值并没有改变。这是为什么呢?

这里要补充一点的是,在Java中,调用方法时,会将方法压入栈中,创建相应的栈帧。栈帧里会保存很多东西,我们现在只需要知道,会在栈帧中创建形式参数a,并且将实参的赋值给形参。

那么,在我们的代码里,把main方法中的变量a作为calc方法的实际参数传递过去时,实际上是先将实际参数的值10赋给了栈帧中形参a(而不是将实参变量a赋值给了形参变量a),然后在calc方法中,对形参变量a进行了+1的操作,并没有对main方法中的a进行任何的操作。

2.引用传递

再来运行这一段代码:
public class RefTest{public static void main(String[] args){Student s = new Student();s.age = 18;System.out.println("调用calc方法之前,学生s的年龄是:" + s.age);calc(s);System.out.println("调用calc方法之后,学生s的年龄是:" + s.age);}public static void calc(Student s){s.age += 1;}}class Student{public int age;}

得到的结果是什么呢?

调用calc方法之前,学生s的年龄是:18
调用calc方法之后,学生s的年龄是:19

我们来解释一下这是为什么:

在本文的第二大段里,我们了解到,new 一个对象的时候(Student s = new Student();)会先在堆中创建一个对象student,然后把该对象在堆中的地址赋值给引用变量s,存储在栈中。

在将引用变量s作为实参调用calc方法时,实际上是将实参s的值(new出的对象在堆中的地址)赋值给了形参s(回忆之前提到的栈帧),这样形参s和实参s指向的是同一个对象在堆中的地址

也就是说,在calc方法中对形参s指向的对象的属性进行修改时,就是在修改实参s指向的对象的属性。

所以在调用calc方法之后,学生s的年龄是:19。

好了,值传递和引用传递介绍到这里就结束了,不要忘了批评指正哦~





0 0