java 值传递和引用传递

class Demo{
private static int num= 2;
public static void changePri(int a){
a = 10;
}
public static int changeObj(Demo demo){
demo.num = 5;
return demo.num;
}
public static void main(String[] args) {
int a = 12;
changePri(a);
System.out.println(a);//12
Demo demo = new Demo();
changeObj(demo);
System.out.println(demo.num);//5

}
}


这段代码的主要部分调用了两个很相近的方法,changeObj()和changePri()。唯一不同的是它们一个把对象作为输入参数,另一个把Java中的基本类型int作为输入参数。并且在这两个函数体内部都对输入的参数进行了改动。
java中的八大基本数据类型:int long float double short byte char boolean

看似一样的方法,程序输出的结果却不太一样。changeObj()方法真正的把输入的参数改变了,而changePri()方法对输入的参数没有任何的改变。

从这个例子知道Java对对象和基本的数据类型的处理是不一样的。和C语言一样,当把Java的基本数据类型(如int,char,double等)作为入口参数传给函数体的时候,传入的参数在函数体内部变成了局部变量,这个局部变量是输入参数的一个拷贝,所有的函数体内部的操作都是针对这个拷贝的操作,函数执行结束后,这个局部变量也就完成了它的使命,它影响不到作为输入参数的变量。

这种方式的参数传递被称为"值传递"。而在Java中用对象的作为入口参数的传递则缺省为"引用传递",也就是说仅仅传递了对象的一个"引用",这个"引用"的概念同C语言中的指针引用是一样的。当函数体内部对输入变量改变时,实质上就是在对这个对象的直接操作。

class MyDemo {  

public static void operate(StringBuffer x, StringBuffer y) {
x.append(y);
y = x;
System.out.println(x + "," + y);
}

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

结果:
AB,AB
AB,B


解释:  
很明显你这里传递的是地址(引用)传递2个StringBuffer 对象!

注意啦:
x 会指向 a 所指向的内存(可以理解为都指向A),y 会指向 b 所指向的内存,(可以理解为都指向B)
x.append(y); //这句话把 y 指向的值追加给x指向的值,这个时候x 和a 指向的内存都是AB,y指向的内存仍然是B
y=x;//这句话就是把 x 的值 附值给 y, 附的是地址!

这样 a,y,x 同时值向 AB,b仍然指向 B

System.out.println(x+","+y); 这里所以打印 AB,AB
System.out.println(a+","+b); 这里所以打印 AB ,B

引用参数的传递是把原来的地址传递给新的变量,原来引用的仍然在那里!


下面还是例子:

//在函数中传递基本数据类型,     
public class Test {

public static void change(int i, int j) {
int temp = i;
i = j;
j = temp;
}

public static void main(String[] args) {
int a = 3;
int b = 4;
change(a, b);

System.out.println("a=" + a);
System.out.println("b=" + b);
}
}

结果为:
a=3
b=4
原因就是 参数中传递的是 基本类型 a 和 b 的拷贝,在函数中交换的也是那份拷贝的值 而不是数据本身;


public class Test {     

public static void change(int[] counts) {
counts[0] = 6;
System.out.println(counts[0]);
}

public static void main(String[] args) {
int[] count = { 1, 2, 3, 4, 5 };
change(count);
}
}
结果是:6
在方法中 传递引用数据类型int数组,实际上传递的是其引用count的拷贝,他们都指向数组对象,在方法中可以改变数组对象的内容。即:对复制的引用所调用的方法更改的是同一个对象。


这个要和下面的比较下:  
class A {
int i = 0;
}


public class Test {

public static void add(A a) {
a = new A();
a.i++;
}

public static void main(String args[]) {
A a = new A();
add(a);
System.out.println(a.i);
}
}

输出结果是0
在该程序中,对象的引用指向的是A ,而在change方法中,传递的引用的一份副本则指向了一个新的OBJECT,并对其进行操作。
而原来的A对象并没有发生任何变化。 引用指向的是还是原来的A对象。

class A {
int i = 0;
}


public class Test {

public static void add(A a) {
//a = new A();
a.i++;
}

public static void main(String args[]) {
A a = new A();
add(a);
System.out.println(a.i);
}
}

输出结果是1



String 不改变,数组改变  
public class Example {
String str = new String("good");

char[] ch = { 'a', 'b', 'c' };

public static void main(String args[]) {
Example ex = new Example();
ex.change(ex.str, ex.ch);
System.out.print(ex.str + " and ");
System.out.println(ex.ch);
}

public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'g';
}
}
程序3输出的是 good and gbc.
String 比较特别,看过String 代码的都知道, String 是 final的。所以值是不变的。 函数中String对象引用的副本指向了另外一个新String对象,而数组对象引用的副本没有改变,而是改变对象中数据的内容.
对于对象类型,也就是Object的子类,如果你在方法中修改了它的成员的值,那个修改是生效的,方法调用结束后,它的成员是新的值,但是如果你把它指向一个其它的对象,方法调用结束后,原来对它的引用并没用指向新的对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值