◆传参的问题

  引用类型(在函数调用中)的传参问题,是一个相当扯的问题。有些书上说是传值,有些书上说是传引用。搞得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. 调用get_str_time(时间), 就能把毫秒的时间转换成格式化的 ,转化时间戳的方法

    function get_str_time(time){ var datetime = new Date(); datetime.setTime(time); var year = datetime. ...

  2. python之操作系统介绍,进程的创建

    操作系统(英语:operating system,缩写作 OS)是管理计算机硬件与软件资源的计算机程序,同时也是计算机系统的内核与基石.操作系统需要处理如管理与配置内存.决定系统资源供需的优先次序.控 ...

  3. vue 父子组件互相传值容易出现的报错

    对于父子组件之间的互相传值,报错如下: [Vue warn]: Avoid mutating a prop directly since the value will be overwritten w ...

  4. SuperMap 三维产品资料一览表

    转自:http://blog.csdn.net/supermapsupport/article/details/68924713 如何能快速地开发项目中的三维功能呢?本文为您提供全方位的三维资料,为您 ...

  5. 即时消息服务框架(iMSF)应用实例之分布式事务三阶段提交协议的实现

    一,分布式事务简介 在当前互联网,大数据和人工智能的热潮中,传统企业也受到这一潮流的冲击,纷纷响应国家“互联网+”的战略号召,企业开始将越来越多的应用从公司内网迁移到云端和移动端,或者将之前孤立的IT ...

  6. loadrunner 运行脚本-Run-time Settings->General->Additional attributes设置

    运行脚本-Run-time Settings->General->Additional attributes设置 by:授客 QQ:1033553122 作用说明 为Vuser脚本提供额外 ...

  7. 测试思想-集成测试 关于接口测试 Part 2

     关于接口测试 by:授客 QQ:1033553122 ------------------接Part 1---------------------- 5.   用例设计思想(举例说明) 如上表,是某 ...

  8. loadrunner 技巧-模拟Run Logic中的随机Action运行

    技巧-模拟Run Logic中的随机Action运行 by:授客 QQ:1033553122   可以这样做,Run-time Settings,删除Action7,然后在其它Action比如Acti ...

  9. 《Inside C#》笔记(十四) 反射

    通过反射可以在运行时动态地获取一个应用的元数据. 一 反射相关的类和方法 与反射相关的类处在System.Reflection命名空间下,包括Assembly.Module.MethodInfo.Fi ...

  10. Java并发编程(三)Thread类的使用

    一.线程的状态 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以下这几个状态:创建(new).就绪(runnable).运行(running).阻塞(blocked).time wait ...