java学习之基础篇 参数传递[转]

时间:2021-12-08 16:27:50
java学习之基础篇(1)参数传递
2008年06月30日 星期一 下午 09:50

(一)在讲参数传递之前,让我们来看看java中堆与栈的含义

Java把内存划分成两种:一种是栈内存,一种是堆内存。

在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配,包括函数中的参数,局部变量等。

当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆内存用来存放由new创建的对象和数组。

在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。

引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

(二)理解了堆与栈的含义后,对于理解参数传递是有必要的

(1)java中参数的传递是值传递。也就是说:方法的形参先申请自己的存储空间,运行时把方法调用时的实参值复制给形参的方式。这个种方式对于基本类型变量和引用变量都适用。

对于基本类型变量:

把实参值复制给形参,所以值参传递时形参在方法中的改变不影响实参。如果这句话不理解,可以换一种方式来记就可以了:对于基本数据类型,比如int、 long、char之类的类型,是传递值的,如果你在方法中修改了值,方法调用结束后,那个变量的值没用改变。

对于引用类型变量:

也是把值复制给形参,但是这次复制的值只是实参引用变量,即实参在栈中存放的值,这个值就是对象在堆中的首地址,此时实参和形参共用同一个堆空间,也就是共用同一个堆地址。如果方法中改变了堆地址所代表的内容,也就是对象的内容,那么实参同时改动,如果方法中改变的只是堆地址(注意:不是堆地址代表的内容),那么实参是不变的。如果这句话不理解,可以换一种方式记忆:对于引用类型变量(包括数组):如果你在方法中修改了它的成员的值,那么这个修改是生效的,方法调用结束后,它的成员是新的值,但是如果你把这个引用变量指向一个新的对象,方法调用结束后,原来的引用还是指向原来的对象,原来的对象内容不变。

(2)看几个有关的例子:

例子一:

public class Tester {
public static void main(String[] args) {
int primitive = 2;
changePrimitive(primitive);
//primitive的值依然是2
MyClass myClass = new MyClass();
changeObject(myClass);
//myClass仍然指向的是执行changeObject之前的那个对象
//但是myClass.i等于3了
}

public static void changePrimitive(int primitive) {
primitive = 3;
}

public static void changeObject(MyClass myClass) {
myClass.i = 3;
myClass = new MyClass();
}
}

class MyClass {
int i;
}

例子二:

public class wo{
public static void main (String args[]) throws IOException
{
StringBuffer a = new StringBuffer ("A");
StringBuffer b = new StringBuffer ("B");
operate (a,b);
System.out.println(a+"     "+b);
}
static void operate (StringBuffer x, StringBuffer y) {
x.append(y);
   }
}

运行结果:AB B

为什么?

答:要知道x.append(y)的意思是改变形参x的内容,因为内容改变,所以实参a所指代的对象内容同步改变

y=x 的意思是改变形参y在栈中的内容,而栈中的内容是对象在堆中的首地址,而首地址内容没有改变,因

此实参a所指代的对象内容不变,打印后仍然为B