A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© 3872982 中级黑马   /  2015-11-5 14:46  /  980 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

学过编程的都知道,在其他语言中都有诸如指针,引用传递来实现对函数实参里值的修改,但是在java中,既没有指针,又没有引用传递,那么java参数传递是怎么工作的呢?我们能否对其中的值进行修改呢?java中只有值传递,这个值指的是实参的地址的拷贝,得到这个拷贝地址后,你可以通过它修改这个地址的内容(引用不变),因为此时这个内容的地址和原地址是同一地址,但是你不能改变这个地址本身使其重新引用其它的对象,也就是值传递,可能说的不是很清楚,下面给出一个完整的能说明情况的例子吧



  1. package test;

  2. /**
  3. * @description Java中没有引用传递只有值传递
  4. */
  5. class Person {

  6.     private String name;

  7.     private String sex;

  8.     public Person(String x, String y) {
  9.         this.name = x;
  10.         this.sex = y;
  11.     }

  12.     // 重写toString()方法,方便输出
  13.     public String toString() {

  14.         return name + " " + sex;
  15.     }

  16.     // 交换对象引用
  17.     public static void swapObject(Person p1, Person p2) {
  18.         Person tmp = p1;
  19.         p1 = p2;
  20.         p2 = tmp;
  21.     }

  22.     // 交换基本类型
  23.     public static void swapInt(int a, int b) {
  24.         int tmp = a;
  25.         a = b;
  26.         b = tmp;
  27.     }

  28.     // 交换对象数组
  29.     public static void swapObjectArray(Person[] p1, Person[] p2) {
  30.         Person[] tmp = p1;
  31.         p1 = p2;
  32.         p2 = tmp;
  33.     }

  34.     // 交换基本类型数组
  35.     public static void swapIntArray(int[] x, int[] y) {
  36.         int[] tmp = x;
  37.         x = y;
  38.         y = tmp;
  39.     }

  40.     // 改变对象数组中的内容
  41.     public static void changeObjectArray(Person[] p1, Person[] p2) {
  42.         Person tmp = p1[1];
  43.         p1[1] = p2[1];
  44.         p2[1] = tmp;
  45.         
  46.         // 再将p1[1]修改
  47.         Person p = new Person("wjl", "male");
  48.         p1[1] = p;
  49.     }

  50.     // 改变基本类型数组中的内容
  51.     public static void changeIntArray(int[] x, int[] y) {
  52.         int tmp = x[1];
  53.         x[1] = y[1];
  54.         y[1] = tmp;

  55.         x[1] = 5;
  56.     }
  57. }

  58. public class ByValueTest {

  59.     public static void main(String[] args) {

  60.         // 建立并构造两个对象
  61.         Person p1 = new Person("Alexia", "female");
  62.         Person p2 = new Person("Edward", "male");

  63.         System.out.println("对象交换前:p1 = " + p1.toString());
  64.         System.out.println("对象交换前:p2 = " + p2.toString());
  65.         
  66.         // 交换p1对象和p2对象
  67.         Person.swapObject(p1, p2);
  68.         // 从交换结果中看出,实际对象并未交换
  69.         System.out.println("\n对象交换后:p1 = " + p1.toString());
  70.         System.out.println("对象交换后:p2 = " + p2.toString());

  71.         // 建立两个对象数组
  72.         Person[] arraya = new Person[2];
  73.         Person[] arrayb = new Person[2];

  74.         // 分别构造数组对象
  75.         arraya[0] = new Person("Alexia", "female");
  76.         arraya[1] = new Person("Edward", "male");
  77.         arrayb[0] = new Person("jmwang", "female");
  78.         arrayb[1] = new Person("hwu", "male");

  79.         System.out.println('\n' + "对象数组交换前:arraya[0] = "
  80.                 + arraya[0].toString() + ", arraya[1] = "
  81.                 + arraya[1].toString());
  82.         System.out.println("对象数组交换前:arrayb[0] = "
  83.                 + arrayb[0].toString() + ", arrayb[1] = "
  84.                 + arrayb[1].toString());
  85.         
  86.         // 交换这两个对象数组
  87.         Person.swapObjectArray(arraya, arrayb);
  88.         System.out.println('\n' + "对象数组交换后:arraya[0] = "
  89.                 + arraya[0].toString() + ", arraya[1] = "
  90.                 + arraya[1].toString());
  91.         System.out.println("对象数组交换后:arrayb[0] = "
  92.                 + arrayb[0].toString() + ", arrayb[1] = "
  93.                 + arrayb[1].toString());

  94.         // 建立两个普通数组
  95.         int[] a = new int[2];
  96.         int[] b = new int[2];

  97.         // 给数组个元素赋值
  98.         for (int i = 0; i < a.length; i++) {
  99.             a[i] = i;
  100.             b[i] = i + 1;
  101.         }

  102.         System.out.println('\n' + "基本类型数组交换前:a[0] = " + a[0] + ", a[1] = " + a[1]);
  103.         System.out.println("基本类型数组交换前:b[0] = " + b[0] + ", b[1] = " + b[1]);

  104.         // 交换两个基本类型数组
  105.         Person.swapIntArray(a, b);
  106.         System.out.println('\n' + "基本类型数组交换后:a[0] = " + a[0] + ", a[1] = " + a[1]);
  107.         System.out.println("基本类型数组交换后:b[0] = " + b[0] + ", b[1] = " + b[1]);
  108.         
  109.         // 改变对象数组的内容
  110.         Person.changeObjectArray(arraya, arrayb);
  111.         System.out.println('\n' + "对象数组内容交换并改变后:arraya[1] = " + arraya[1].toString());
  112.         System.out.println("对象数组内容交换并改变后:arrayb[1] = " + arrayb[1].toString());
  113.         
  114.         // 改变基本类型数组的内容
  115.         Person.changeIntArray(a, b);
  116.         System.out.println('\n' + "基本类型数组内容交换并改变后:a[1] = " + a[1]);
  117.         System.out.println("基本类型数组内容交换并改变后:b[1] = " + b[1]);
  118.     }
  119. }
复制代码
程序运行结果如下:




结论:不管是对象、基本类型还是对象数组、基本类型数组,在函数中都不能改变其实际地址但能改变其中的内容。

评分

参与人数 1技术分 +1 收起 理由
洋葱头头 + 1

查看全部评分

10 个回复

正序浏览
好像很厉害。不过现在看起来感觉好深奥
回复 使用道具 举报
传值,只有传值
回复 使用道具 举报
这个比指针好点..
回复 使用道具 举报
6666666666666666666
回复 使用道具 举报
楼主在类里面写的方法无效.
回复 使用道具 举报
好,说得不错
回复 使用道具 举报
1379号监听员 发表于 2015-11-5 22:38
在函数中交换:引用数据类型形参指向的地址改变了,而实际参数并没有改变;基本数据类型形参的值改变了,跟 ...

格式出了点错,将就着看吧,我自己总结的东西,大神请指教
回复 使用道具 举报
本帖最后由 1379号监听员 于 2015-11-5 22:42 编辑

在函数中交换:引用数据类型形参指向的地址改变了,而实际参数并没有改变;基本数据类型形参的值改变了,跟实际参数也没什么关系。
所以在函数中经过形参这么一搅合,交换等于啥也没干
在函数中改变属性值:引用数据类型把地址赋给形参,形参根据地址改变属性的值,所以最终实参的属性发生变化;基本数据类型,因为是把数值赋给了形参,改变的只是形参的值,跟实参毛关系没有。
所以在函数中改变属性,基本数据类型不改变,引用数据类型改变。
写了一段代码作为补充:

  1. class Car {

  2. private String color;
  3. private int num;
  4. Car(){}
  5. Car(String color,int num){
  6. this.color = color;
  7. this.num = num;
  8. }
  9. public void run(){
  10. System.out.println(color+"的有"+num+"个轮子的小车跑起来了");
  11. }
  12. public static void swap(Car c1,Car c2) {
  13. Car c3 = c1;
  14. c1 = c2;
  15. c2 = c3;
  16. }

  17. }
  18. class Demo_CarTest {
  19. public static void main(String[] args) {
  20. Car c1 = new Car("红色",4);
  21. Car c2 = new Car("黄色",3);
  22. System.out.println("交换前");
  23. c1.run();
  24. c2.run();
  25. Car c3 = c1;
  26. c1 = c2;
  27. c2 = c3;
  28. System.out.println("交换后");
  29. c1.run();
  30. c2.run();
  31. /*
  32. System.out.println("调用函数交换后");
  33. Car.swap(c1,c2);
  34. c1.run();
  35. c2.run();
  36. */
  37. }
  38. }
复制代码

上边代码表示的是如果不在函数中作交换,引用型数据类型的地址是改变的。
回复 使用道具 举报
学习了,日哥果然牛叉
回复 使用道具 举报
其实我一直都是懂的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马