Java中的值传递和引用传递
C和Java使用参数传值是用其实参值来进行初始化形参的值。对于基本变量,C和C++允许显式传递变量的地址(引用传递),在scanf函数中的参数前面的&地址符可以见得。而Java不允许这样做,因为Java对普通类型变量不支持引用传递Java的方法传递只有值传递一种,即将实际的参数值的副本传入方法,而参数不受影响
所以我们写一个测试代码来试验一下:
package test;
class testObj{
private int m = 1;
private String s = "测试obj";
void setM(int m) {
this.m = m;
}
void setS(String s){
this.s = s;
}
String getS(){
return s;
}
}
public class test {
private static void inttest(int n){
System.out.println(n++);
}
private static void testobj(testObj n){
n.setS("testobj");
}
private static void teststring(String[] s){
s[0] = "teststring";
}
public static void main(String[] args){
int n = 0;
test t = new test();
testObj to = new testObj();
to.setS("mainobj");
to.setM(10);
String[] str = new String[]{"mainstring"};
test.inttest(n);
test.testobj(to);
test.teststring(str);
System.out.println(n);
System.out.println(to.getS());
System.out.println(str[0]);
}
}
可以看到结果是普通的int值传递没有改变,而实例化对象和特殊类型String(数组)都发生了改变。因此可以得出结论:变量进行值传递相当于复制一个副本,当然彼此之间没有关系;而引用传递相当于指向的同一个内存地址,任意一个操作都将影响实际对象。对于String这些特殊的不可操作类要特殊对待作为引用类型操作。
Java中Swap交换函数
在C/C++里面交换值的方法:
void swap(int&a ,int&b)
{
int temp;
temp = a;
a = b;
b = temp;
}
而Java中交换:使用C中的引用参数进行的上述交换在Java中不起作用,因为Java没有这些类型的参数。
通过数组交换
但是通常应用程序实际上只需要交换数组中的两个值。在这种情况下,可以传递数组和两个索引以交换为三个参数。这种方法用在算法中比较多如冒泡算法。
private static void swap(int[] Arr,int a, int b){
int temp = Arr[a];
Arr[a] = Arr[b];
Arr[b] = temp;
}
public static void main(String[] args){
int[] Arr = new int[]{1,2,3,4,5};
int a = 0;
int b = 1;
swap(Arr,a,b);
System.out.println(Arr[0]);
System.out.println(Arr[1]);
}
利用类变量传值
Java对于引用类型的参数传递一样采用了值传递。
private static void swap(DataWrap dw){
int temp = dw.a;
dw.a = dw.b;
dw.b = temp;
System.out.println("swap中的顺序: " + " a: " + dw.a + " b: " + dw.b);
}
public static void main(String[] args){
DataWrap dw = new DataWrap();
dw.a = 1;
dw.b = 2;
System.out.println("之前的顺序: " + " a: " + dw.a + " b: " + dw.b);
swap(dw);
System.out.println("之后的顺序: " + " a: " + dw.a + " b: " + dw.b);
}
利用包装器类
static class MyInteger {
private int x; // single data member
public MyInteger(int xIn) { x = xIn; } // constructor
public int getValue() { return x; } // retrieve value
public void insertValue(int xIn) { x = xIn;} // insert
}
public static class Swapping {
// swap: pass references to objects
static void swap(MyInteger rWrap, MyInteger sWrap) {
// interchange values inside objects
int t = rWrap.getValue();
rWrap.insertValue(sWrap.getValue());
sWrap.insertValue(t);
}
public static void main(String[] args) {
int a = 23, b = 47;
System.out.println("Before. a:" + a + ", b: " + b);
MyInteger aWrap = new MyInteger(a);
MyInteger bWrap = new MyInteger(b);
swap(aWrap, bWrap);
a = aWrap.getValue();
b = bWrap.getValue();
System.out.println("After. a:" + a + ", b: " + b);
}
}
利用外部内联的方式
class Exchange{
int i , j;
Exchange(int i, int j){
this.i = i;
this.j = j;
}
public void swap(Exchange exc)
{
int temp = exc.i;
exc.i = exc.j;
exc.j = temp;
}
}
public class TestSwap {
static int a = 3;
static int b = 2;
public static void main(String[] args){
Exchange exc = new Exchange(a,b);
System.out.println("before swap "+"a的值="+a+" b的值="+b);
exc.swap(exc);
a=exc.i;
b=exc.j;
System.out.println("after swap "+"a的值="+a+" b的值="+b);
}
}