◆传参的问题

  引用类型(在函数调用中)的传参问题,是一个相当扯的问题。有些书上说是传值,有些书上说是传引用。搞得Java程序员都快成神经分裂了。所以,我们最后来谈一下“引用类型参数传递”的问题。

  如下例子,假设现在要把刚才创建的那一坨字符串打印出来,我们会使用如下语句:

StringBuffer str = new StringBuffer();
System.out.println(str); //这个语句又是什么意思捏?这时候就两说了。

  第一种理解:可以认为传进函数的是str这个指针,指针说白了就是一个地址的值,说得再白一点,就是个整数。按照这种理解,就是传值的方式。也就是说,参数传递的是指针本身,所以是传值的。

  第二种理解:可以认为传进去的是StringBuffer对象,按照这种理解,就是传引用方式了。因为我们确实是把对象的地址(也就是引用)给传了进去。

  费了这么多口水,其实不论是传引用还是传值,都可以讲得通,关键取决于你是如何看待参数所传递的东西。这就好比量子力学中“光的波粒二象性”,如果你以粒子的方式去测量它,它看起来像粒子;如果你以波动的方式去观测它,它看起来像波动。

/**
* @description Java中没有引用传递只有值传递
*
* @author Alexia
* @date 2013-10-16
*
*/
class Person { private String name; private String sex; public Person(String x, String y) {
this.name = x;
this.sex = y;
} // 重写toString()方法,方便输出
public String toString() {
return name + " " + sex;
} // 交换对象引用,这里的p1和p2是swapObject这个函数的变量(局部变量),
// p1、p2接收的就是传递进来的一个堆内存的地址,改变p1、p2的指向只是改变了这两个局部变量的指向。
// 实际的全局变量还是没变的
public static void swapObject(Person p1, Person p2) {
Person tmp = p1;
p1 = p2;
p2 = tmp;
} // 交换基本类型
public static void swapInt(int a, int b) {
int tmp = a;
a = b;
b = tmp;
} // 交换对象数组
public static void swapObjectArray(Person[] p1, Person[] p2) {
Person[] tmp = p1;
p1 = p2;
p2 = tmp;
} // 交换基本类型数组
public static void swapIntArray(int[] x, int[] y) {
int[] tmp = x;
x = y;
y = tmp;
} // 改变对象数组中的内容
public static void changeObjectArray(Person[] p1, Person[] p2) {
Person tmp = p1[1];
p1[1] = p2[1];
p2[1] = tmp;
// 再将p1[1]修改
Person p = new Person("wjl", "male");
p1[1] = p;
} // 改变基本类型数组中的内容
public static void changeIntArray(int[] x, int[] y) {
int tmp = x[1];
x[1] = y[1];
y[1] = tmp;
x[1] = 5;
}
} public class ByValueTest { public static void main(String[] args) { // 建立并构造两个对象
Person p1 = new Person("Alexia", "female");
Person p2 = new Person("Edward", "male"); System.out.println("对象交换前:p1 = " + p1.toString()); //Alexia female
System.out.println("对象交换前:p2 = " + p2.toString()); //Edward male // 交换p1对象和p2对象
Person.swapObject(p1, p2);
// 从交换结果中看出,实际对象并未交换
System.out.println("对象交换后:p1 = " + p1.toString()); //Alexia female
System.out.println("对象交换后:p2 = " + p2.toString()); //Edward male // 建立两个对象数组
Person[] arraya = new Person[2];
Person[] arrayb = new Person[2]; // 分别构造数组对象
arraya[0] = new Person("Alexia", "female");
arraya[1] = new Person("Edward", "male");
arrayb[0] = new Person("jmwang", "female");
arrayb[1] = new Person("hwu", "male"); System.out.println("对象数组交换前:arraya[0] = " + arraya[0].toString() + ", arraya[1] = "
        + arraya[1].toString()); //Alexia female,Edward male
System.out.println("对象数组交换前:arrayb[0] = " + arrayb[0].toString() + ", arrayb[1] = "
        + arrayb[1].toString()); //jmwang female,hwu male // 交换这两个对象数组
Person.swapObjectArray(arraya, arrayb);
System.out.println("对象数组交换后:arraya[0] = " + arraya[0].toString() + ", arraya[1] = "
        + arraya[1].toString()); //Alexia female,Edward male
System.out.println("对象数组交换后:arrayb[0] = " + arrayb[0].toString() + ", arrayb[1] = "
        + arrayb[1].toString()); //jmwang female,hwu male // 建立两个普通数组
int[] a = new int[2];
int[] b = new int[2]; // 给数组个元素赋值
for (int i = 0; i < a.length; i++) {
a[i] = i;
b[i] = i + 1;
} System.out.println("基本类型数组交换前:a[0] = " + a[0] + ", a[1] = " + a[1]); //0,1
System.out.println("基本类型数组交换前:b[0] = " + b[0] + ", b[1] = " + b[1]); //1,2 // 交换两个基本类型数组
Person.swapIntArray(a, b);
System.out.println("基本类型数组交换后:a[0] = " + a[0] + ", a[1] = " + a[1]); //0,1
System.out.println("基本类型数组交换后:b[0] = " + b[0] + ", b[1] = " + b[1]); //1,2 // 改变对象数组的内容
Person.changeObjectArray(arraya, arrayb);
System.out.println("对象数组内容交换并改变后:arraya[0] = " + arraya[0].toString() + ", arraya[1] = "
        + arraya[1].toString()); //Alexia female,wjl male
System.out.println("对象数组内容交换并改变后:arrayb[0] = " + arrayb[0].toString() + ", arrayb[1] = "
        + arrayb[1].toString()); //jmwang female,Edward male // 改变基本类型数组的内容
Person.changeIntArray(a, b);
System.out.println("基本类型数组内容交换并改变后:a[0] = " + a[0] + ", a[1] = " + a[1]); //0,5
System.out.println("基本类型数组内容交换并改变后:b[0] = " + b[0] + ",b[1] = " + b[1]); //1,1
}
}

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

  【相当于传递进来的栈内存的值,栈内存只存放地址和基本数据内容,是不可在函数中改变的】

Java中没有引用传递只有值传递(在函数中)的更多相关文章

  1. 理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...

  2. (转载)理解Java中的引用传递和值传递

      关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天 ...

  3. Java中的引用传递和值传递

    Java中的引用传递和值传递 关于Java的引用传递和值传递,在听了老师讲解后,还是没有弄清楚是怎么一回事,于是查了资料,所以在这里与大家分享,有不对的地方,欢迎大家留言. java中是没有指针的,j ...

  4. Java Object 引用传递和值传递

    Java Object 引用传递和值传递 @author ixenos Java没有引用传递: 除了在将参数传递给方法(或函数)的时候是"值传递",传递对象引用的副本,在任何用&q ...

  5. java到底是引用传递还是值传递?

    今天我们来讲讲一个在学习中容易误解的问题,面试中也偶尔问到,java方法调用时到底是值传递还是引用传递? 首先,请大家来做一个判断题,下面的3个问题是否描述正确 1. java基本数据类型传递是值传递 ...

  6. Java千百问_05面向对象(011)_引用传递和值传递有什么差别

    点击进入_很多其它_Java千百问 1.什么是值传递 值传递,是将内存空间中某个存储单元中存放的值,传送给还有一个存储单元.(java中的存储单元并不是物理内存的地址,但具有相关性) 比如: //定义 ...

  7. java引用传递和值传递

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习 ...

  8. Java当中的内存分配以及值传递问题内存解析

    首先必须说明作为Java程序员对于内存只要有大致的了解就可以了,如果你对Java当中的某一个知识点在不需要分析内存分配过程的情况下可以掌握,那就大可不必去研究内存.如果你对知识点已经掌握,那么你应该把 ...

  9. Java方法的参数传递方式为: 值传递

    Java方法的参数传递方式为: 值传递 对于基本数据类型作为参数传递时, 是"按值传递", 这点都认识很清楚. 但是, 当对象或者说引用作为参数传递, Java 的参数传递方式是& ...

随机推荐

  1. csharp: read system DSN configured get Driver Names on windows

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  2. NFS共享权限挂载

    mount -t nfs 192.168.2.203:/data/lys /lys -o proto=tcp -o nolock mount 172.16.2.18:/home/arcgisserve ...

  3. JavaScript大杂烩14 - 使用JQuery(上)

    JQuery意义 - Why? 为什么要使用JQuery,从我个人来说,就是这么几点:简化代码 + 统一行为 + 功能强大 + 搭配方便. 简化代码是从写代码的角度来说的,实现同样的功能,如果用Jav ...

  4. python 序列化pickle 和 encode的区别

    我们把变量从内存中变成可存储或传输的过程称之为序列化. 序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上. 反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即un ...

  5. 【PAT】B1003 我要通过!

    我觉得这是PAT中最坑的一道题,表述令人很不适应 分析过程: 条件1.只有P,A,T三种字符 条件2.xPATx正确,x可以是空串,或者由A组成的字符串 条件3.如果aPbTc是正确的,aPbATca ...

  6. Linux初学 - Centos7忘记root密码的解决办法

    开机进入启动界面后,要按照屏幕的下方的操作提示迅速按下“e”键. 按下“e”键后即来到启动文件界面,这时按键盘上面的方向键“下”,一直到文件底部,在"LANG=zh_cn.UTF-8&quo ...

  7. February 7th, 2018 Week 6th Wednesday

    We are all resigned to death: it is life we aren't resigned to. 我们可以屈从于死神,但我们却不能让生活任意摆布. Of all the ...

  8. C语言变量定义与数据溢出(初学者)

    1.变量定义的一般形式为:类型说明符.变量名标识符等:例:int a,b,c;(abc为整型变量) 在书写变量定义时应注意以下几点: (1)允许在一个类型说明符后,定义多个相同类型的变量.各变量之间用 ...

  9. jQuery-jqprint.js打印插件使用高版本jQuery时问题

    使用jqprint打印插件的网页demo代码: <!doctype html> <html> <head> <meta charset="utf-8 ...

  10. 阿里八八β阶段Scrum(4/5)

    今日进度 黄梅玲: 图表绘制与实时更新的完成 刘晓: 数据分析表格部分生成完成 张岳: 初步完成简易的桌面控件 陈裕鹏: 事件添加TAG标签的功能完成,此外信息抽取算法也基本完成并PULL,但与项目产 ...