1.问题说明
在C++中,函数调用时有传值调用和传址调用两种方式,但在Java中只有传值调用一种方式。Java中的方法参数为那几种基本数据类型的情况跟C++中一样,传入的只是变量的拷贝。而当参数类型为类对象时,则有可能会误以为是传址调用。
在Java的方法调用中,方法中的参数是以传值的形式进行的,不管它是什么数据类型。如果是基本数据类型,则就是传入该值的一个拷贝;如果是类类型,则传入的是引用的一个拷贝。归根结底还是传的值。
2.基本数据类型作为形参
(1)非数组型基本数据类型作为形参
该种传递实质上传入的是a的一个copy,赋给了形式参数a1,a1的值初始等于a,但无论怎么改变形式参数a1的值,都不会改变实际参数的值。
(2)基本数据类型以数组名形式作为形参
首先了解数组在内存中是如何分配空间的。
int [ ] b={1,2,3,4};
①首先在栈中分配四个int 类型的空间,首地址赋给变量b,可通过b[0]、b[1]、b[2]、b[3]访问数组中数据
②其次,change(b),传进去的实际上是b的地址,即数组的首地址,形式参数b1作为b的一个copy,和b都指向同一个块内存,即数组首地址,所以改变b1[0]、b1[1]等等,就等同于改变该内存中的数据,故形参对该块内存的改变等效于通过实参对该数组的改变。
但是,
3. 引用类型作为形式参数(普通类对象作为形式参数)
以上两种调用方式最常见。
由于引用类型传递实质是对传入变量p的一个copy,所以形式参数p2和实际参数p指向同一块内存,同一个对象,故通过形式参数p2对 对象内部数据的改变,就是改变了实际参数指向对象的内部数据,因为是同一块内存。
但通过
4. String类型作为形式参数
(1)非数组型的String类作为形式参数
String类比较特殊,虽然它也是引用类型,但是存储方式不完全等同于其他引用类型。涉及到String类在内存中存储知识敬请点击这 点击打开链接
在内存中形式参数的变化:
故非数组型String类作为形式参数时,形式参数的改变不会影响实际参数的值。
(2)数组型String类作为形式参数
此原理和数组型基本数据类型作为形参相似。
5.StringBuffer(StringBuilder类作为形参)
StringBuffer类和String类不同,String类的对象中的字符串不能改变,但StringBuffer类对象的字符串可以添加、修改
2.基本数据类型作为形参
(1)非数组型基本数据类型作为形参
int a=1;
change(a);
System.out.println(a); //1
public static void change(int a1){
a1=10;
}
该种传递实质上传入的是a的一个copy,赋给了形式参数a1,a1的值初始等于a,但无论怎么改变形式参数a1的值,都不会改变实际参数的值。
(2)基本数据类型以数组名形式作为形参
int[] b={1,2,3,4};
change(b);
System.out.println(b[0]); //10
public static void change(int[] b1){
b1[0]=10;
b1=new int[]{0,9,8};
}
首先了解数组在内存中是如何分配空间的。
int [ ] b={1,2,3,4};
①首先在栈中分配四个int 类型的空间,首地址赋给变量b,可通过b[0]、b[1]、b[2]、b[3]访问数组中数据
②其次,change(b),传进去的实际上是b的地址,即数组的首地址,形式参数b1作为b的一个copy,和b都指向同一个块内存,即数组首地址,所以改变b1[0]、b1[1]等等,就等同于改变该内存中的数据,故形参对该块内存的改变等效于通过实参对该数组的改变。
但是,
b1=new int[]{0,9,8};
b1新分配一个数组空间,此时,对原内存中数组数据是没有影响的,b1指向其他内存,b仍然指向原内存,故不会对实参b造成影响。
3. 引用类型作为形式参数(普通类对象作为形式参数)
change(p);
public static void change(Point2D p1){
p1=new Point2D(32,43);
}
public static void hange(Point2D p1){
p2.setX(35);
}
以上两种调用方式最常见。
由于引用类型传递实质是对传入变量p的一个copy,所以形式参数p2和实际参数p指向同一块内存,同一个对象,故通过形式参数p2对 对象内部数据的改变,就是改变了实际参数指向对象的内部数据,因为是同一块内存。
但通过
p1=new Point2D(32,43);
这种新创建对象的方式,p1指向新的内存,新的对象,故其操作与实际参数p再无关系,不会使实际参数p指向的对象造成改变。
4. String类型作为形式参数
(1)非数组型的String类作为形式参数
String类比较特殊,虽然它也是引用类型,但是存储方式不完全等同于其他引用类型。涉及到String类在内存中存储知识敬请点击这 点击打开链接
String s=new String("hello");
change(s);
System.out.println(s); //hello
public static void change(String str){
str="world";
}
String s=new String("hello")在内存中的实现:
<span style="font-size:18px;">change(s);</span>
public static void change(String str){
str="world";
在内存中形式参数的变化:
故非数组型String类作为形式参数时,形式参数的改变不会影响实际参数的值。
(2)数组型String类作为形式参数
String[] s2={"abc","cde","edf"};
System.out.println(s2[0]);
change(s2);
System.out.println(s2[0]);
public static void change(String[] s1) {
s1[0]="world";
}
此原理和数组型基本数据类型作为形参相似。
5.StringBuffer(StringBuilder类作为形参)
StringBuffer类和String类不同,String类的对象中的字符串不能改变,但StringBuffer类对象的字符串可以添加、修改
StringBuffer sb=new StringBuffer(s1);
StringBuffer sb2=new StringBuffer(s2);
System.out.println(sb+"---"+s2);//hello---world
change(sb,sb2);
System.out.println(sb+"---"+s2); // world---worldworld
public static void change(String s1, String s2) {
s1=s2; //s1=="world",s1指向s2的缓冲区
s2=s1+s2;// s2="worldworld",s1="worldworld",因为s1和s2指向同一块缓冲区
System.out.println(s1);
System.out.println(s2);
System.out.println("-----------");
}