◆传参的问题

  引用类型(在函数调用中)的传参问题,是一个相当扯的问题。有些书上说是传值,有些书上说是传引用。搞得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. The open source JavaScript graphing library that powers Plotly

    https://plot.ly/javascript/time-series/ https://plot.ly/javascript/ https://github.com/plotly/plotly ...

  2. filter(ele)过滤数组

    filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素. 例如,在一个Array中,删掉偶数,只保留奇数,可以这么写: function remove(arr) { l ...

  3. ionic 项目中ios上遇到的软键盘输入法自动弹出的问题

    一.  安装插件 cordova plugin add ionic-plugin-keyboard 二. 软键盘显示监听 window.addEventListener('native.keyboar ...

  4. 安卓开发_startActivityForResult的详细用法

    一个需求:一个activity到另一个activity进行一些设置,返回第一个activity的时候 获取第二个activity设置的数据 百度了一下,发现startActivityForResult ...

  5. Flutter 布局(八)- Stack、IndexedStack、GridView详解

    本文主要介绍Flutter布局中的Stack.IndexedStack.GridView控件,详细介绍了其布局行为以及使用场景,并对源码进行了分析. 1. Stack A widget that po ...

  6. MVP模式及性能优化

    1.base BaseActivity public abstract class BaseActivity<V,P extends BasePresenter<V>>exte ...

  7. 【Java入门提高篇】Day28 Java容器类详解(十)LinkedHashMap详解

    今天来介绍一下容器类中的另一个哈希表———>LinkedHashMap.这是HashMap的关门弟子,直接继承了HashMap的衣钵,所以拥有HashMap的全部特性,并青出于蓝而胜于蓝,有着一 ...

  8. SVN——Couldn't perform atomic initialization

    前言   今天早上刚刚打开我的电脑,就被李总他们告知不能正确用SVN从服务器上下载代码了,然后看问题吧.问题其实也是本文的标题,并不难解决,写下来留个记录,顺便也算是一种分享.问题截图如下:    造 ...

  9. 两个列表lst1和lst2,计算两个列表的公共元素和非公共元素

    方法1: 列表推导式 lst1 = [1, 3, 7] lst2 = [3, 5, 4] a = [x for x in lst1 if x in lst2] b = [y for y in (lst ...

  10. Centos7防火墙快速开放端口配置方法

    ▲这篇文章主要为大家详细介绍了Centos7防火墙开放端口的快速方法,感兴趣的小伙伴们可以参考一下! Firewalld服务是红帽RHEL7系统中默认的防火墙管理工具,特点是拥有运行时配置与永久配置选 ...