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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 3872982 中级黑马   /  2015-11-5 14:46  /  820 人查看  /  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 个回复

倒序浏览
其实我一直都是懂的
回复 使用道具 举报
学习了,日哥果然牛叉
回复 使用道具 举报
本帖最后由 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. }
复制代码

上边代码表示的是如果不在函数中作交换,引用型数据类型的地址是改变的。
回复 使用道具 举报
1379号监听员 发表于 2015-11-5 22:38
在函数中交换:引用数据类型形参指向的地址改变了,而实际参数并没有改变;基本数据类型形参的值改变了,跟 ...

格式出了点错,将就着看吧,我自己总结的东西,大神请指教
回复 使用道具 举报
好,说得不错
回复 使用道具 举报
楼主在类里面写的方法无效.
回复 使用道具 举报
6666666666666666666
回复 使用道具 举报
这个比指针好点..
回复 使用道具 举报
传值,只有传值
回复 使用道具 举报
好像很厉害。不过现在看起来感觉好深奥
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马