本人原来是做C和C++开发的,最近项目需要开始搞android的开发,
接触新平台总会遇到一些编程语言观念上不一样的问题,像值传递和引用传递在拥有指针的C/C++中是个方便好办的事情,
但在Java里貌似就没那么方便了,不过这样做的一个好处是可以降低程序耦合性,
以下是我作为菜鸟的一些尝试的心得,若不正确,望提出指正。
先简单说说C中的几种传递吧,
1. 值传递,
int a = 9;
int b = a; //a =9 , b = 9
b = 10; //a = 9, b = 10
func(a); //After fun(), a = 9;
void func(int i)
{
i++;
}
值传递实际上是直接将变量的内容复制一个副本,新变量与原变量将没有任何关联,对新变量的修改也不会影响原变量。
2.地址传递,
int *pInt = (int *)malloc(1*sizeof(int)); //pInt指向堆上的一块内存区A。
memset(p,0,1*sizeof(int));
pInt[0] = 10; //赋值。
func(&pInt); //函数内修改pInt[0]的值。 运行func()之后 pInt[0]的值为9
void func(int *p)
{
p[0] = 9;
}
地址传递可以看做是把指针指向的地址值做了份拷贝,函数体内获得的地址值和原地址值是一样的,因此修改指向的内容将会影响原来的变量指向的内容。
3.引用传递,
int a = 8;
int &b = a; //b作为a的引用,b必须在定义时初始化。 a=b=8;
func(a); //After func(a), a=9;
void func(int &c)
{
c = 9;
}
引用其实是原变量的一个别名,可以理解成一个变量有两个名字,因此对任何一个变量的操作都将影响原变量。
接下来再说说重点,java中的值传递和引用传递。
下面是个简单例子:
定义了一个简单的基本类:
public class NodeBase {
private int id = 0;
private String name = null;
public NodeBase(){
}
public NodeBase(int id, String name){
this.id = id;
this.name = name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
String str = "Node:"+getName()+", Id="+getId();
return str;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
以下是个简单的测试类:
public class SimpleTest {
public void swapTest(){
int iA = 8;
int iB = 9;
String sA = "abc";
String sB = "def";
NodeBase nA = new NodeBase(5,"A");
NodeBase nB = new NodeBase(6,"B");
Log.v("MyDebug", "B4Swap:iA:"+iA+",iB:"+iB+",sA:"+sA+",sB:"+sB+","+nA.toString()+","+nB.toString());
swapInt(iA, iB);
swapString(sA, sB);
swapNode(nA, nB);
Log.v("MyDebug", "Swapped:iA:"+iA+",iB:"+iB+",sA:"+sA+",sB:"+sB+","+nA.toString()+","+nB.toString());
modifyInt(iA);
modifyString(sA);
modifyNode(nA);
Log.v("MyDebug", "Swapped:iA:"+iA+",sA:"+sA+","+nA.toString());
}
public void swapNode(NodeBase a, NodeBase b){
NodeBase tmp = a;
a = b;
b = tmp;
}
public void swapString(String a, String b){
String c = a;
a = b;
b = c;
}
public void swapInt(int a, int b){
int c = a;
a = b;
b = c;
}
public void modifyInt(int i){
i = 10;
}
public void modifyString(String s){
s = "ghi";
}
public void modifyNode(NodeBase n){
n.setId(7);
n.setName("C");
}
}
在MainActivity中运行
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
test();
}
public void test(){
SimpleTest simpleTest = new SimpleTest();
simpleTest.swapTest();
}
}
测试结果输出:
程序中定义了个基本类,主要为了便于观察对象的成员变量在函数体内修改的效果。
程序作了3次输出,
第一次输出为初始化时的数据,
第二次输出是执行交换函数后的数据,
第三次输出时 在函数体内修改变量内容后的输出。
从结果看,最后的输出只有在函数体内修改对象的成员变量会影响原对象的成员变量。
因此可以得出java中的参数传递是采用值传递方式,
当java中通过参数传递对象时,实际上传递的是对象地址的副本(个人理解是java编译器对对象传递的操作方式类似于C++对指针传递的操作),
它仍然是值传递,因此在函数体内对对象进行修改时,修改的对象和原对象所指向的堆区域是相同的,所以会影响原对象。
第二次输出前,程序作了交换处理,其实交换的都是副本(包括地址的副本),并不影响原变量和对象。
第三次输出的 修改String 对象的函数
public void modifyString(String s){
s = "ghi";
}
实际上相当于对变量s作了一次新的对象赋值,也不会影响原对象sA。
基于上面的理解,
NodeBase nB = new NodeBase(6,"B");
NodeBase nC = nB;
nC.setId(12);
nC.setName("C");
执行这几条语句后nB.toString()输出是多少呢?
第一次写技术文章,有点乱,见谅!!
星空剑圣@CSDN