- 浏览: 48676 次
- 性别:
- 来自: 北京
最新评论
-
NEO_ONE:
awk '!x[$0]++' all_EN.txt > ...
Centos手动设置IP(不用dhcp) -
NEO_ONE:
Update Table1 set c = (select c ...
Oracle_Two
Java中的参数传递机制一直以来大家都争论不休,究竟是“传值”还是“传址(传引用)”,争论的双方各执一词,互不相让。不但“菜鸟”们一头雾水,一些“老鸟”也只知道结果却说不出所以然来。我相信看过下面的内容后,你就会明白一些。
先看基本类型作为参数传递的例子:
public class Test1 { public static void main(String[] args) { int n = 3; System.out.println("Before change, n = " + n); changeData(n); System.out.println("After changeData(n), n = " + n); } public static void changeData(int nn) { n = 10; } }
我想这个例子大家都明白,基本类型作为参数传递时,是传递值的拷贝,无论你怎么改变这个拷贝,原值是不会改变的,输出的结果证明了这一点:
Before change, n = 3
After changeData(n), n = 3
那么,我们现在来看看对象作为参数传递的例子,这也是大家争论的地方。
public class Test2 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb); changeData(sb); System.out.println("After changeData(n), sb = " + sb); } public static void changeData(StringBuffer strBuf) { strBuf.append("World!"); } }
先看输出结果:
Before change, sb = Hello
After changeData(n), sb = Hello World!
从结果来看,sb的值被改变了,那么是不是可以说:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。从上面例子的输出结果来看,这样解释是合理。
现在我们对上面的例子稍加改动一下:
public class Test3 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb); changeData(sb); System.out.println("After changeData(n), sb = " + sb); } public static void changeData(StringBuffer strBuf) { strBuf = new StringBuffer("Hi "); strBuf.append("World!"); } }
按照上面例子的经验:对象作为参数传递时,是把对象的引用传递过去,如果引用在方法内被改变了,那么原对象也跟着改变。你会认为应该输出:
Before change, sb = Hello
After changeData(n), sb = Hi World!
但运行一下这个程序,你会发现结果是这样的:
Before change, sb = Hello
After changeData(n), sb = Hello
这就是让人迷惑的地方,对象作为参数传递时,同样是在方法内改变了对象的值,为什么有的是改变了原对象的值,而有的并没有改变原对象的值呢?这时候究竟是“传值”还是“传引用”呢?
下面就让我们仔细分析一下,来揭开这中间的奥秘吧。
先看Test2这个程序:
StringBuffer sb = new StringBuffer("Hello ");
这一句执行完后,就会在内存 的堆里生成一个sb对象,请看图1:
如图1所示,sb是一个引用,里面存放的是一个地址“@3a”(这个“@3a”是我举的代表内存地址的例子,你只需知道是个内存地址就行了),而这个地址正是“Hello ”这个字符串在内存中的地址。
changeData(sb);
执行这一句后,就把sb传给了changeData方法中的StringBuffer strBuf,由于sb中存放的是地址,所以,strBuf中也将存放相同的地址,请看图2:
此时,sb和strBuf中由于存放的内存地址相同,因此都指向了“Hello”。
strBuf.append("World!");
执行changeData方法中的这一句后,改变了strBuf指向的内存中的值,如下图3所示:
所以,Test2 这个程序最后会输出:
After changeData(n), sb = Hello World!
再看看Test3这个程序。
在没有执行到changeData方法的strBuf = new StringBuffer(“Hi “);之前,对象在内存中的图和上例中“图2”是一样的,而执行了strBuf = new StringBuffer(“Hi “);之后,则变成了:
此时,strBuf中存放的不再是指向“Hello”的地址,而是指向“Hi ”的地址“@3b” (同样“@3b”是个例子)了,new操作符操作成功后总会在内存中新开辟一块存储区域。
strBuf.append("World!");
而执行完这句后,
通过上图可以看到,由于sb和strBuf中存放地址不一样了,所以虽然strBuf指向的内存中的值改变了,但sb指向的内存中值并不会变,因此也就输出了下面的结果:
After changeData(n), sb = Hello
String类是个特殊的类,对它的一些操作符是重载的,如:
String str = “Hello”; 等价于String str = new String(“Hello”);
String str = “Hello”;
str = str + “ world!”;等价于str = new String((new StringBuffer(str)).append(“ world!”));
因此,你只要按上面的方法去分析,就会发现String对象和基本类型一样,一般情况下作为参数传递,在方法内改变了值,而原对象是不会被改变的。
综上所述,我们就会明白,在Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数。
你可以试着按上面的画图法分析一下下面例子的结果,看看运行结果与你分析的结果是否一样:
public class Test4 { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("Before change, sb = " + sb); changeData(sb); System.out.println("After changeData(n), sb = " + sb); } public static void changeData(StringBuffer strBuf) { StringBuffer sb2 = new StringBuffer("Hi "); strBuf = sb2; sb2.append("World!"); } }
提示:
执行完strBuf = sb2;后:
发表评论
-
android sdk manager不能更新
2012-09-05 20:55 984Eclipse输出错误reason: Connection t ... -
进制转换
2012-06-12 15:10 6511. 十 -----> 二 给你一个十进制,比如: ... -
解决process.waitFor()阻塞
2012-05-22 10:50 2607private static void exeBat(){ ... -
lucene3.5例子
2012-04-09 17:38 921package com.lucene; import j ... -
win端口占用查看
2012-01-09 16:58 778C:\>netstat -ano | findstr & ... -
ABNF
2011-12-15 11:19 1063BNF 巴科斯范 ... -
全角半角转换
2011-11-09 17:39 876public class Convert { public ... -
System.getProperty()
2011-11-02 17:19 838java.version Java ... -
正则匹配标点
2011-10-27 15:39 695摘抄:str = str.replaceAll("[ ... -
暂时很强大的正则
2011-10-26 22:37 694最新手机号: (13[0-9]|15[0|3|6|7|8 ... -
JS post提交表单
2011-09-23 10:15 2208js post方式提交表单有两种办法,1:AJAX提交 2:在 ... -
轻量级synchronized
2011-09-19 10:59 934后台admin给用户加分,点的快了,会加两次分,在前台没限制的 ... -
MD5__java应用
2011-09-18 15:21 727public final static String enco ... -
会话跟踪
2011-09-11 10:32 684Cookie : 分为会话cookie,持久cookie ... -
MAP遍历
2011-09-08 23:07 652//最常规的一种遍历方法,最常规就是最常用的,虽然不复杂, ... -
JAVA date处理
2011-08-04 14:05 709Date now=new Date(); Lo ... -
java日期处理小例子
2011-07-22 11:47 598import java.text.SimpleDateForm ... -
action type redirect 参数传递
2011-06-16 15:10 991在使用Struts2开发时,有时需要用redirect 来跟多 ... -
js replace
2011-06-08 16:10 724去掉“” :req.responseText.replace ... -
java使用代理访问网络的几种方法
2011-06-02 14:23 923方法一使用系统属性来完成代理设置, 这种方法比较简单, 但是不 ...
相关推荐
参数传递 单个参数传递 多个参数传递 传入单个实体(JavaBean/Map) 传入多个实体 传入集合 使用场景 在实际开发过程中,我们往往需要编写复杂的SQL语句,拼接稍有不注意就会导致错误,Mybatis给开发者提供了动态SQL,...
本项目"Kettle实现多参数传递并且循环加载数据.zip"显然是一个利用Kettle解决复杂业务逻辑的示例,特别关注了参数传递和数据的循环处理。以下将详细解释相关知识点。 1. **Kettle参数传递**: 在Kettle中,参数...
C# 调用 C++ 编写的 DLL 函数各种参数传递问题 在 C# 调用 C++ 编写的 DLL 函数时,参数传递是一个非常重要的部分。这篇文章将详细介绍 C# 调用 C++ 编写的 DLL 函数各种参数传递问题,包括不返回值的参数、带...
### Matlab GUI参数传递方式详解 #### 一、全局变量 全局变量是一种常见的数据共享方法,尤其是在Matlab GUI设计中。这种方式简单直接,适用于GUI内部不同控件之间以及不同GUI之间的数据共享。 **特点:** - **...
在互联网应用中,参数传递是实现页面间数据交互的关键技术,尤其在动态网站和Web应用程序中更为重要。当用户在网站上浏览时,有时需要在不同的页面之间传递信息,如搜索查询、用户登录状态或者购物车的商品信息等。...
在互联网应用中,网页间的参数传递是至关重要的,它使得用户在浏览不同页面时能够保持信息的连贯性。这个例子将深入探讨几种常见的网页间参数传递方法,以帮助你理解这一关键概念。 首先,我们有URL查询字符串。当...
本主题聚焦于使用“一般参数传递方式”来创建一个能够处理加、减、乘、除运算的后端接口。这里我们将深入探讨如何实现这个功能,并通过具体的HTTP请求地址`Http://localhost:8080/simplecalculator`来演示其工作原理...
本篇文章将深入探讨JNI中参数传递的基本数据类型、自定义对象以及系统对象。 一、基本数据类型的参数传递 在JNI中,基本数据类型如int、float、char等的传递相对简单。Java中的基本类型在C/C++中都有对应的类型。...
VB参数传递方式是编程中一个基础但重要的概念,尤其是在Visual Basic中。VB中的参数分为实参(实际参数)和形参(形式参数),实参是在调用过程时提供的,而形参是在过程定义时声明的。当调用过程时,实参与形参通过...
通过学习这个教程,你将能够熟练地配置JSF环境,创建和管理Bean,使用Facelets创建动态视图,以及掌握各种参数传递技巧,从而开发出高效且易于维护的JSF应用程序。 总之,JSF是一个强大且灵活的Web开发框架,它简化...
本文档将详细讲解如何在Qt窗体之间进行参数传递,以实现更加灵活和功能丰富的应用。 首先,我们来看“Qt 窗体之间的参数传递(窗体B的参数传给窗体A).txt”这个主题。在Qt中,有多种方法可以将一个窗体的数据传递...
在C#编程语言中,参数传递和参数调用是核心概念,它们关乎着函数和方法如何接收和处理数据。理解这些概念对于编写高效且可维护的代码至关重要。本篇文章将深入探讨C#中的参数传递机制及其应用。 首先,我们要了解...
在C#编程中,跨窗体参数传递是应用程序设计中常见的需求,特别是在开发具有多个界面的桌面应用时。本主题将深入探讨如何在不同的窗体之间有效地传递数据,以实现功能如从一个窗体的文本框输入数据并在另一个窗体上...
### 关于C语言中函数调用和参数传递机制的探讨 在C语言中,函数是程序的基本构建单元之一,它们不仅能够实现代码的重用,还能通过参数传递机制实现数据的有效交互。本文将深入探讨C语言中的函数调用机制以及参数...
### Linux系统Kernel参数传递方式详细解析 #### 一、引言 在Linux系统中,内核启动时可以接收一系列参数,这些参数对于系统的初始化过程至关重要。例如,它们可以帮助内核了解如何配置硬件设备、确定系统运行模式...
本话题将详细探讨如何在 iReport 中使用 `subdataset`(子数据集)与主数据集配合,以实现参数传递,从而实现动态的数据过滤。 首先,我们需要理解主数据集和子数据集的概念。主数据集是报表的基础,它通常对应于一...
现在,我们来到参数传递的部分。在RDLC报表中,参数用于根据用户输入或代码动态筛选数据。在VS2010的报表设计器中,可以创建报表参数,并在数据源查询中使用它们。在WPF应用中,通过`ReportViewer`的`SetParameters`...
C和C++中的函数参数传递方式主要分为值传递、指针传递和引用传递。这些方式决定了参数在函数调用时的传值行为,以及它们在函数执行后是否能够影响原始数据。下面详细解释这些传递方式的知识点。 1. 值传递(Call by...