6,参数传递机制
参数属于局部变量。当对象调用方法时,参数被分配内存空间,并要求调用者向参数传递值,即方法被调用时,参数变量必须有具体的值。
Java中的参数传递,无论是基本类型,还是引用类型,他们传递的都是一份副本。基本类型传递的是值本身的副本,引用类型传递的是地址的副本。
6.1基本类型的参数传递
public class Test {
public static void main(String[] args) {
int a = 6;
int b =9;
swap(a, b);
System.out.println("main方法里面,a="+a+";b="+b);
}
public static void swap(int a,int b){
int temp =a ;
a = b;
b = temp;
System.out.println("swap方法内,a="+a+";b="+b);
}
}
当程序执行swap()方法时系统进入swap方法,并将main方法中的a、b变量作为参数值传入swap方法,传入swap方法的只是a、b的副本,而不是a、b本身,进入swap方法后,系统中产生了4个变量,这四个变量在内存中的存储示意图如图1:
在main方法中调用swap方法时,main方法还没有结束。
因此系统分别为main方法和swap方法分类两块栈区,分别用于保存main方法和swap方法的局部变量。
main方法中的a、b变量作为参数值传入swap方法,实际上再swap方法栈区中重新产生了两个变量a、b,并将main方法栈区中的a、b变量的值,分别赋给swap方法栈区的a、b参数(就是swap方法的a、b形参进行了初始化)。
此时,系统存在两个a变量、两个b变量,只是存在于不同的方法栈区中而已。
值传递的实质:
上面的交换程序,main方法栈区中a、b的值并没有任何改变,程序改变的只是swap方法栈中的a、b。当系统开始执行方法时,系统为形参执行初始化,就是把实参变量的值赋给方法的形参变量,方法里操作的并不是实际的实参变量。简而言之,方法中形参改变但是实参并不发生同样改变。
值传导(基本类型的参数传导)是单向传导,形参改变不影响实参。
6.2引用类型的参数传递
双向传导,形参改变,实参发生同样改变。当参数是引用类型时,“传值”传递的是变量中存放的“引1用”,而不是变量所引用的实体。
class DataSwap {
public int a;
public int b;
}
public class Test {
public static void swap(DataSwap ds){
int temp = ds.a;
ds.a=ds.b;
ds.b=temp;
System.out.println("swap方法内,a="+ds.a+";b="+ds.b);
//ds = null ;// 把ds直接赋为null,让它不再指向任何有效地址。
}
public static void main(String[] args) {
DataSwap ds = new DataSwap();
ds.a=6;
ds.b=9;
swap(ds);
System.out.println("main方法内,a="+ds.a+";b="+ds.b);
}
}
//交换实参
class MyValue {//定义一个类MyValue
public int val;//在类中定义一个公有成员变量val
}
public class Main {
public static void swap(MyValue m,MyValue n) {//m和n是形参
int tmp = m.val;
m.val = n.val;
n.val = tmp;//在swap方法中创建两个myValue类型的形参变量m和n,分别指向a和b,也就是说他们同样存放的是两个数的地址
}
public static void main(String[] args) {//java程序入口地址,程序从main方法开始执行
MyValue a = new MyValue();
MyValue b = new MyValue();//创建两个myValue类型的形参变量a,b;
a.val = 10;
b.val = 20;//对a,b赋值;
System.out.println("交换前:a=="+a.val+" b=="+b.val);
swap(a,b);//调用静态方法swap,传参(a==10,b==20作为实参),实际上等于传入了两个数的地址,因为a和b分别指向了两个对象,并且存放的是堆空间上两个对象的地址
System.out.println("交换后swap方法和main函数中:a=="+a.val+" b=="+b.val);
}
}
(1)在调用成员方法时应注意以下 4 点:
- 对无参成员方法来说,是没有实际参数列表的(即没有 paramList),但方法名后的括号不能省略。
- 对带参数的成员方法来说,实参的个数、顺序以及它们的数据类型必须与形式参数的个数、顺序以及它们的数据类型保持一致,各个实参间用逗号分隔。实参名与形参名可以相同,也可以不同。
- 实参也可以是表达式,此时一定要注意使表达式的数据类型与形参的数据类型相同,或者使表达式的类型按 Java 类型转换规则达到形参指明的数据类型。
- 实参变量对形参变量的数据传递是“值传递”,单向传递即只能由实参传递给形参,而不能由形参传递给实参。程序中执行到调用成员方法时,Java 把实参值复制到一个临时的存储区(栈)中,形参的任何修改都在栈中进行,当退出该成员方法时,Java 自动清除栈中的内容
6.3可变参数
可变参数(The variable arguments)是指在声明方法时不给出参数列表中从某项开始直至最后一项参数的名字和个数,但这些参数的类型必须相同。 可变参数使用“…”表示若干个参数,这些参数的类型必领相同,并且最后一个参数必须是方法的参数列表中的最后一个参数。
例如:
publicvoidf(int...x)
参数代表可以通过下标运算来表示参数列表中的具体参数,即x【0】,x【1】,……,x【m-1】分别表示×代表的第1个至第m个参数。
7,实列变量和类变量
7.1实例变量和类变量的声明
在声明成员变量时,用关键宇static给予修饰的称作类变量,否则称作实例变量。
类变量也称为static变量,静态变量。
class Num {
float x;//实例变量
static int y;//类变量
}