◆传参的问题

  引用类型(在函数调用中)的传参问题,是一个相当扯的问题。有些书上说是传值,有些书上说是传引用。搞得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. deepin使用笔记-解决安装并解决gvim没有启动器的问题

    我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 1.安装gvim #apt-get install vim-gtk3 2.创建桌面启动器 创建/usr/share/applic ...

  2. C语言字符串读入函数笔记

    gets(str)函数和scanf("%s",str)区别: 转自:https://zhidao.baidu.com/question/290403568.html 二者都是从终端 ...

  3. Error running tomcatUnable to open debugger port (127.0.0.1 50181) java.net.B

    1.把tomcat删除,重新建一个,tomcat就会重新自动使用一个端口了 2.自己手动调一下端口 我用的是第二种,手动调了下,最开始的端口是:50181,该成了50182,就可以了.

  4. jQuery js 中return false,e.preventDefault(),e.stopPropagation()的区别(事件冒泡)

    有时候遇到冒泡事件很烦人,真的..... 1.e.stopPropagation()阻止事件冒泡 <head> <title></title> <script ...

  5. 正则与python的re模块

    一.正则表达式的语法 正则表达式使用反斜杠字符('\')来表示特殊的形式或者来允许使用特殊的字符而不要启用它们特殊的含义.这与字符串字面值中相同目的的相同字符的用法冲突:例如,要匹配一个反斜线字面值, ...

  6. 洛谷P3987 我永远喜欢珂朵莉~(set 树状数组)

    题意 题目链接 Sol 不会卡常,自愧不如.下面的代码只有66分.我实在懒得手写平衡树了.. 思路比较直观:拿个set维护每个数出现的位置,再写个线段树维护区间和 #include<bits/s ...

  7. 【代码笔记】Web-JavaScript-JavaScript语句

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  8. 【读书笔记】iOS-使用蓝牙

    蓝牙是由Sony Ericsso公司研发出来的,它是一种无线通讯协议,主要用于短程和低耗电设备,其有效通讯范围约30ft,传输速度为1MB/s.与Wifi设计初衷不同,蓝牙适用于无线的外围设备,进行小 ...

  9. 安全测试 WEB安全测试手册

    WEB安全测试手册 By:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436 概述 Ø          目的 Ø          适用读者 Ø          适用 ...

  10. 自己写bitmap

    备注:1.原创文章,转载请标明出处: 2.欢迎建议和意见 3.我的实现是C语言,为了保护公司隐私,下述数据类型被我改了.实际上int应改是无符号4个字节的类型,byte是有符号1个字节,才能保证移植性 ...