在说这个问题之前,我们先来看一下形式参数和实际参数概念。
形式参数:方法声明时的参数(小括号里的参数),就好比数学中的未知数X。
实际参数:调用方法时真正传入方法里的数据。
值传递:就是在调用方法时,实际参数把它的值传递给对应的形式参数。在这个时候,内存中就存在两个相等的基本数据类型,即形式参数和实际参数。在该方法中的操作都是对形参这个值进行修改,不影响实际参数的值。
引用传递:也称为传地址。方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址;在方法执行中,形参和实参内容相同,指向同一块内存地址,方法执行中对引用的操作将会影响到实际对象。
public class Num {
public int b=99;
public void num(int i){
i++;
System.out.println(i);
}
public void num1(){
b++;
System.out.println(b);
}
}
public class Test {
public static void main(String[] arg) {
Num s = new Num();
int a = 99;
s.num(a); //值传递
System.out.println(a);
s.num1(); //引用传递
System.out.println(s.b);
}
}
运行结果:
可以看出,通过值传递,在修改类方法里的值时,不会影响原来所赋的初值;而通过引用传递,在修改类方法里的值时,则会影响原来所赋的初值。
因为String不属于基本数据类型。String类是不可变(final)的,对String类的任何改变,都是返回一个新的String类对象.这样的话把String类的引用传递给一个方法,该方法对String的任何改变,对原引用指向的对象没有任何影响,这一点和基本数据类型相似。
public class S {
public void st(String str){
str=str+"world";
System.out.println(str);
}
public void st(StringBuffer str){
str.append("World");
System.out.println(str.toString());
}
}
public class Test {
public static void main(String[] arg) {
S s=new S();
//String类似基本类型,值传递,不会改变实际参数的值
String st="hello";
//StringBuffer和StringBuilder等是引用传递
StringBuffer st2=new StringBuffer("Hello");
s.st(st);
System.out.println(st);
s.st(st2);
System.out.println(st2.toString());
}
}
运行结果:
对String和StringBuffer的操作产生了不同的结果。
由此得出结论:
(1)基本数据类型传值,对形参的修改不会影响实参;
(2)引用类型传引用,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象;
(3)String的特殊处理,可以理解为传值,最后的操作不会修改实参对象。