关于Java的引用和函数参数传递

Java中没有了指针,这有时给程序员带来了些许不便。Java的语言设计者强调,这种不便可以通过Java的引用特性得到弥补。即对于Java的任何对象,我们可以申明对象变量,但不产生实例,这样,把该变量指向具有实际实例的对象,即可实现同一实例对象的多个变量引用,如:

int x[]={1,2,3,4,5}, y[];

y=x;

for(int i=0; i<y.length; i++) System.out.print(“   ”+y[i]);

则完成了通过yx的引用。从这个实际效果看,y在这里就很象C语言中的指针了。只不过对于“指针”y我们不能进行+-这类算数运算,即Java的引用只能指向程序限定的能够访问的现存对象,所以Java的实现者认为它是灵活同时也是安全的。

但对于C或者C++中能够通过函数简单实现的两个数交换问题,即C++如下函数:

void swap(int &x, int &y) { int t; t=x; x=y; y=t; }

Java中是否能够实现呢?

按照Java的规定,Java的函数参数在传递的时候有两种方式。对于基本类型,如intdouble等作为函数参数传递时,采取的是传值方式。而对于对象,如数组、字符串等作为参数传递时,采用的是引用方式,即此时在函数中对传递的对象的修改将完全影响原对象。那能否对于对象利用引用完成值的交换呢?下面的程序充分地演示了这个问题:

public class test {

  public static void main(String[] arg) {

    int x1[]={1,2,3},x2[]={3,2,1};

    swap(x1,x2);//采用swap函数,即直接利用参数引用进行交换

    System.out.print("swap->X1:/t"); printarr(x1);

    System.out.print("swap->X2:/t"); printarr(x2);

    swapArray(x1,x2);//采用swapArray函数,利用对于对象的值的修改进行交换

    System.out.print("swapArr->X1:/t"); printarr(x1);

System.out.print("swapArr->X2:/t"); printarr(x2);

Object t;

    t=x1; x1=x2; x2=(int[])t;//在非函数调用中直接利用引用进行交换

    System.out.print("Tswap->X1:/t"); printarr(x1);

    System.out.print("Tswap->X2:/t"); printarr(x2);

  }

  public static void swap(Object x, Object y) {//直接利用参数引用交换

    Object t=x;

    x=y;

    y=t;

  }

  public static void swapArray(int x[], int y[]) {//对引用对象的值进行修改完成交换

    if(x.length!=y.length) return;

    int t[]=x.clone();

    for(int i=0; i<x.length; i++) x[i]=y[i];

    for(int i=0; i<y.length; i++) y[i]=t[i];

  }

  public static void printarr(int x[]) {//打印数组

    for(int i=0; i<x.length; i++) System.out.print(x[i]+"  ");

    System.out.println();

  }

}

在函数swap中,我们直接利用参数进行交换。在函数swapArray中,我们通过修改参数指向的两个数组的值进行交换。而在main函数没有进行函数参数传递的情况下,我们直接利用参数的引用进行了一次交换。

程序的运行结果如下:

swap->X1:     1  2  3 

swap->X2:     3  2  1 

swapArr->X1: 3  2  1 

swapArr->X2: 1  2  3 

Tswap->X1:   1  2  3 

Tswap->X2:   3  2  1 

从运行结果我们可以清楚地看到,函数swap实际没有完成交换,而函数swapArray和直接在main中利用引用进行的交换是成功的。从这里我们可以得知,虽然Java的引用可以实现CC++的指针的类似的效果,这在主函数中的引用交换得到了证明。但是一但进行了函数的参数传递,这种引用方式的交换便实效了。虽然它的交换方式和主函数中利用Object引用t进行的交换方式相同。猜测其原因(因为我不是Java的实现者),只能说明,函数中的引用变量和主函数中调用的变量是不相同的。即在调用swap函数时,虽然将x1的引用传递给了xx2传递给了yxy进行了交换,但x1x2并没有进行交换。也就是说,在函数swap申明参数xy时,实际另外真正的生成了与x1x2完全不相干的引用,只不过xy都同样指向了x1x2罢了,即此时,数组对象x1x2同时分别有两个指针xx1yy1指向它们。这样的结果当然不能完成如CC++类似的交换。唯一的办法是如swapArray函数中一样,不要试图交换,只能试图修改参数所指向的两个对象的值来达到交换的效果。

所以我得出的一个相关的结论是:Java永远也不能实现如CC++一样的swap函数。

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Java中,函数参数传递的方式主要有以下几种: 1. 值传递(Pass by Value):函数调用时,将实参的值复制一份给形参,函数内部对形参的修改不会影响实参的值。这是Java中默认的参数传递方式。 示例代码: ``` public class Test { public static void main(String[] args) { int num1 = 10; int num2 = 20; swap(num1, num2); System.out.println("num1 = " + num1 + ", num2 = " + num2); } public static void swap(int a, int b) { int temp = a; a = b; b = temp; } } ``` 输出结果为:num1 = 10, num2 = 20,因为函数内部的交换操作只是交换了形参a和形参b的值,并不影响实参num1和num2的值。 2. 引用传递(Pass by Reference):函数调用时,将实参的引用传递给形参,形参和实参指向同一块内存地址,函数内部对形参的修改会影响实参的值。Java中没有显式支持引用传递的语法,但可以通过使用对象来实现引用传递。 示例代码: ``` public class Test { public static void main(String[] args) { int[] arr = {1, 2, 3}; changeArr(arr); System.out.println(Arrays.toString(arr)); } public static void changeArr(int[] a) { a[0] = 4; a[1] = 5; a[2] = 6; } } ``` 输出结果为:[4, 5, 6],因为changeArr函数中对形参a的修改会直接影响实参arr的值。 3. 对象传递(Pass by Object):在Java中,对象也是引用类型,函数调用时,将实参对象的引用传递给形参对象,形参和实参指向同一块内存地址,函数内部对形参对象的修改会影响实参对象的值。 示例代码: ``` public class Test { public static void main(String[] args) { Person p = new Person("Tom"); changeName(p); System.out.println(p.getName()); } public static void changeName(Person person) { person.setName("Jerry"); } } class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ``` 输出结果为:Jerry,因为changeName函数中对形参person的修改会直接影响实参p所指向的Person对象的name属性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值