- java中没有地址传递,java中都是基于值的传递。
- 由于java中“对基本类型的变量是不支持引用传递的”,所以根本不能像c/c++那样直接传地址。
- java只能用对象做参数,传递的是对象的地址。
因此,java实现swap的方案中,不管哪种方式,都是通过对象传递的方式来实现的。
基本类型变量作为参数传递的话,是直接把变量值复制过去;
引用类型作为参数传递的话,是把引用里面的值复制过去 。
对于解决方案的选择,这个不一定的,需要看你那边的编码规范,如果没有硬性要求,个人建议还是使用反射与包装类,这样方便你后期维护。
1、通过数组对象交换
public class TestSwap {
public static void main(String[] args){
int a = 3;
int b = 5;
System.out.println("交换前:"+"a="+a+" b="+b);
//以数组接收后赋值,注意赋值顺序,注意对应关系
int[] arr = swap(a,b);
a = arr[0];
b = arr[1];
System.out.println("交换后:"+"a="+a+" b="+b);
}
//交换
private static int[] swap(int x, int y){
//以数组形式返回
return new int[]{y,x};
}
}
2、通过类对象属性交换
public class TestSwap {
// 定义类变量
private int a = 3;
private int b = 5;
public static void main(String[] args) {
TestSwap ts = new TestSwap();
System.out.println("交换前:"+"a="+ts.a+" b="+ts.b);
//对象调用
ts.swap();
System.out.println("交换后:"+"a="+ts.a+" b="+ts.b);
}
//交换 只能运用在对象只有两个类变量时,交换这两个确定的变量
private void swap() {
int temp = this.a;
this.a = this.b;
this.b = temp;
}
}
3、通过自定义包装类对象交换
//MyInteger: 与Integer有些类似,但是其对象可以变值
class MyInteger {
private int x; // 将x作为唯一的数据成员
public MyInteger(int xIn) { x = xIn; } // 构造器
public int getValue() { return x; } // 得到值
public void setValue(int xIn) { x = xIn;} // 改变值
}
public class Swapping {
// swap: 传对象引用
static void swap(MyInteger rWrap, MyInteger sWrap) {
// 变值过程
int t = rWrap.getValue();
rWrap.setValue(sWrap.getValue());
sWrap.setValue(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);
}
}
-
java中的基本数据类型传递属于引用传递,并不会像c/c++实现指针传递;
-
通过包装类对象配合反射可以实现数据的交换。
4、通过反射与非类成员包装对象
public classTest{
public static void main(String[] args) throws Exception{
Integer a = 1;
Integer b = 2;
System.out.println("before : a=="+a+";b=="+b);
swap(a,b);
System.out.println("after : a=="+a+";b=="+b);
}
public static void swap(Integer num1,Integer num2) throws IllegalAccessException,NoSuchFieldException{
Field field = num1.getClass().getDeclaredField("value");
field.setAccessible(true);
int temp = num1;
field.set(num1,num2);
field.set(num2,new Integer(temp));
}
}
5、通过反射与类成员包装对象
java 反射 getDeclaredField 获取私有保护字段, 再setAccessible(true)取消对权限的检查 实现对私有的访问和赋值。
package test;
import java.lang.reflect.Field;
public class Test {
//将属性声明为包装类型
private Character from;
private Character pass;
private Character to;
public static void main(String[] args) {
Test test = new Test('A', 'B', 'C');
test.swap(test.from, test.to);
System.out.println(test.toString());
}
Test(Character from, Character pass, Character to) {
this.from = from;
this.pass = pass;
this.to = to;
}
// 交换
private void swap(Character num1, Character num2) {
try {
Field field = num1.getClass().getDeclaredField("value");
field.setAccessible(true);
try {
char temp = num1;
field.set(num1, num2);
field.set(num2, new Character(temp));
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return "Test [from=" + from + ", pass=" + pass + ", to=" + to + "]";
}
}