- 浏览: 243485 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
di1984HIT:
学习了。
CMS项目中用到的技术(全) -
di1984HIT:
就是用xml麻烦~
RESTEasy入门 -
di1984HIT:
学习了~~
RESTEasy入门 -
真三武侯:
写得很好,感谢分享经验心得!
RESTEasy入门 -
fangcensi:
是不是还有一个application文件,没写出来
RESTEasy入门
publicclass StringAsParamOfMethodDemo { publicstaticvoidmain(String[] args) { StringAsParamOfMethodDemo StringAsParamOfMethodDemo = newStringAsParamOfMethodDemo(); StringAsParamOfMethodDemo.testA(); } privatevoidtestA() { String originalStr = "original"; System.out.println("Test A Begin:"); System.out.println("The outer String: " + originalStr); simpleChangeString(originalStr); System.out.println("The outer String after inner change: " + originalStr); System.out.println("Test A End."); System.out.println(); } publicvoidsimpleChangeString(String original) { original = original + " is changed!"; System.out.println("The changed inner String: " + original); } }
一、 最开始的示例
写代码最重要的就是实践,不经过反复试验而得出的说辞只能说是凭空遐想罢了。所以,在本文中首先以一个简单示例来抛出核心话题:
这段代码的逻辑是这样的:先赋值一个String类型的局部变量,然后把这个变量作为参数送进一个方法中,在这个方法中改变该变量的值。编译运行之后,发现输出结果是这样的:
Test A Begin:
The outer String: original
The changed inner String: original is changed!
The outer String after inner change: original
Test A End.
这个结果表明在方法内部对String类型的变量的重新赋值操作并没有对这个变量的原型产生任何影响。好了,这个示例的逻辑和运行结果都展示清楚了,接下来我们来对这个小程序进行分析。在这之前我们先来回顾下Java中所谓的“传值”和“传引用”问题。
二、 Java中的“传值”和“传引用”问题
许多初学Java的程序员都在这个问题上有所思索,那是因为这是所谓的“C语言的传值和传指针问题”在Java语言上同类表现。
最后得出的结论是:
在Java中,当基本类型作为参数传入方法时,无论该参数在方法内怎样被改变,外部的变量原型总是不变的,代码类似上面的示例:
int number = 0;
changeNumber(number) {number++}; //改变送进的int变量
System.out.println(number); //这时number依然为0
这就叫做“值传递”,即方法操作的是参数变量(也就是原型变量的一个值的拷贝)改变的也只是原型变量的一个拷贝而已,而非变量本身。所以变量原型并不会随之改变。
但当方法传入的参数为非基本类型时(也就是说是一个对象类型的变量),方法改变参数变量的同时变量原型也会随之改变,代码同样类似上面的示例:
StringBuffer strBuf = new StringBuffer(“original”);
changeStringBuffer(strBuf) {strbuf.apend(“ is changed!”)} //改变送进的StringBuffer变量
System.out.println(strBuf); //这时strBuf的值就变为了original is changed!
这种特性就叫做“引用传递”,也叫做传址,即方法操作参数变量时是拷贝了变量的引用,而后通过引用找到变量(在这里是对象)的真正地址,并对其进行操作。当该方法结束后,方法内部的那个参数变量随之消失。但是要知道这个变量只是对象的一个引用而已,它只是指向了对象所在的真实地址,而非对象本身,所以它的消失并不会带来什么负面影响。回头来看原型变量,原型变量本质上也是那个对象的一个引用(和参数变量是一样一样的),当初对参数变量所指对象的改变就根本就是对原型变量所指对象的改变。所以原型变量所代表的对象就这样被改变了,而且这种改变被保存了下来。
了解了这个经典问题,很多细心的读者肯定会立刻提出新的疑问:“可是String类型在Java语言中属于非基本类型啊!它在方法中的改变为什么没有被保存下来呢!”的确,这是个问题,而且这个新疑问几乎推翻了那个经典问题的全部结论。真是这样么?好,现在我们就来继续分析。
三、 关于String参数传递问题的曲解之一??直接赋值与对象赋值
String类型的变量作为参数时怎么会像基本类型变量那样以传值方式传递呢?关于这个问题,有些朋友给出过解释,但可惜并不正确。
一种解释就是,对String类型的变量赋值时并没有new出对象,而是直接用字符串赋值,所以Java就把这个String类型的变量当作基本类型看待了。即,应该String str = new String(“original”);,而不是String str = “original”;。这是问题所在么?我们来为先前的示例稍微改造下,运行之后看看结果就知道了。改造后的代码如下:
privatevoidtestB() { String originalStr = newString("original"); System.out.println("Test B Begin:"); System.out.println("The outer String: " + originalStr); changeNewString(originalStr); System.out.println("The outer String after inner change: " + originalStr); System.out.println("Test B End:"); System.out.println(); } publicvoidchangeNewString(String original) { original = newString(original + " is changed!"); System.out.println("The changed inner String: " + original); }
我们来看看这次运行结果是怎么样的:
Test B Begin:
The outer String: original
The changed inner String: original is changed!
The outer String after inner change: original
Test B End.
实践证明,这种说法是错的。
实际上,字符串直接赋值和用new出的对象赋值的区别仅仅在于存储方式不同。
简单说明下:
字符串直接赋值时,String类型的变量所引用的值是存储在类的常量池中的。因为”original”本身是个字符串常量,另一方面String是个不可变类型,所以这个String类型的变量相当于是滴对一个常量的引用。这种情况下,变量的内存空间大小是在编译期就已经确定的。
而new对象的方式是将”original”存储到String对象的内存空间中,而这个存储动作是在运行期进行的。在这种情况下,Java并不是把”original”这个字符串当作常量对待的,因为这时它是作为创建String对象的参数出现的。
所以对String的赋值方式和其参数传值问题并没有直接联系。总之,这种解释并不是正解。
四、 关于String参数传递问题的曲解之二??“=”变值与方法变值
又有些朋友认为,变值不同步的问题是处在改变值的方式上。
这种说法认为:“在Java 中,改变参数的值有两种情况,第一种,使用赋值号“=”直接进行赋值使其改变;第二种,对于某些对象的引用,通过一定途径对其成员数据进行改变,如通过对象的本身的方法。对于第一种情况,其改变不会影响到被传入该参数变量的方法以外的数据,或者直接说源数据。而第二种方法,则相反,会影响到源数据??因为引用指示的对象没有变,对其成员数据进行改变则实质上是改变的该对象。”
这种方式听起来似乎有些…,我们还是用老办法,编写demo,做个小试验,代码如下:
privatevoidtestC() { String originalStr = newString("original"); System.out.println("Test C Begin:"); System.out.println("The outer String: " + originalStr); changeStrWithMethod(originalStr); System.out.println("The outer String after inner change: " + originalStr); System.out.println("Test C End."); System.out.println(); } privatestaticvoidchangeStrWithMethod(String original) { original = original.concat(" is changed!"); System.out.println("The changed inner String: " + original); }
结果如下:
Test C Begin:
The outer String: original
The changed inner String: original is changed!
The outer String after inner change: original
Test C End.
怎么样,这证明了问题并不是出在这,又一个解释在实践论据下夭折了。
那到底是什么原因导致了这种状况呢?
好了,不卖关子了,下面说下我的解释。
五、 String参数传递问题的症结所在
其实,要想真正理解一个类或者一个API/框架的最直接的方法就是看源码。
下面我们来看看new出String对象的那小段代码(String类中),也就是String类的构造函数:
publicString(String original) { int size = original.count; char[] originalValue = original.value; char[] v; if (originalValue.length > size) { // The array representing the String is bigger than the new // String itself. Perhaps this constructor is being called // in order to trim the baggage, so make a copy of the array. int off = original.offset; v = Arrays.copyOfRange(originalValue, off, off+size); } else { // The array representing the String is the same // size as the String, so no point in making a copy. v = originalValue; } this.offset = 0; this.count = size; this.value = v; }
也许你注意到了里面的char[],这说明对String的存储实际上通过char[]来实现的。怎么样?其实就是一层窗户纸。不知道大家还记不记得在Java API中定义的那些基本类型的包装类。比如Integer是int包装类、Float是float的包装类等等。对这些包装类的值操作实际上都是通过对其对应的基本类型操作而实现的。是不是有所感悟了?对,String就相当于是char[]的包装类。包装类的特质之一就是在对其值进行操作时会体现出其对应的基本类型的性质。在参数传递时,包装类就是如此体现的。所以,对于String在这种情况下的展现结果的解释就自然而然得出了。同样的,Integer、Float等这些包装类和String在这种情况下的表现是相同的,具体的分析在这里就省略了,有兴趣的朋友可以自己做做试验。
这也就是为什么若组串操作是通过不同方法来实现的时候,推荐大家使用StringBuffer的真正原因了。至于StringBuffer为什么不会表现出String这种现象,大家再看看的StringBuffer的实现就会明白了,在此也不再赘述了
发表评论
-
Java基本功——Reference
2011-10-08 17:52 1132版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声 ... -
Caused by: org.codehaus.jackson.map.JsonMappingException
2011-08-29 16:09 12376写道 No serializer found for cla ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat(2)
2011-08-10 13:44 3872如果能熟练运用这些命令,尤其是在linux下,那么完全可以代替 ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat (1)
2011-08-10 13:44 1191jstack -- 如果java程序崩溃生成core文 ... -
IT公司中最流行的10种编程语言
2011-08-05 13:12 10011. C语言 C语言是一种 ... -
JDK自带线程池总类介绍介绍
2011-07-28 20:38 7551、newFixedThreadPool创建一个指定工作线程数 ... -
深入浅出多线程(4)对CachedThreadPool OutOfMemoryError问题的一些想法
2011-07-28 20:37 1559线程池是Conncurrent包提供给我们的一个重要的礼物。 ... -
Java多线程--让主线程等待所有子线程执行完毕
2011-07-28 19:25 3364数据量很大百万条记录,因此考虑到要用多线程并发执行,在写 ... -
Quartz管理类
2011-07-18 17:11 1224package com.sihuatech.project.t ... -
JAVA写文件到FTP的几种方法
2011-07-18 11:32 26581.使用URL: URL url = n ... -
为什么会出现 java.util.ConcurrentModificationException 异常?
2011-07-15 14:47 1503工作中碰到个ConcurrentModificationExc ... -
装饰模式
2011-07-12 11:41 12561) 装饰模式 装饰模式 (Decor ... -
全面解析Java中的String对象的数据类型
2011-07-11 12:56 10291. 首先String不属于8种基本数据类型,String是一 ... -
oscache配置详解
2011-07-08 14:36 2142#一、内存缓存或硬盘、数据库缓存 cache.memory= ... -
oscache使用指南
2011-07-07 15:19 2484一、简介 Cache是一种用于提高系统响应速度、改善 ... -
java文件操作
2011-07-05 12:10 752package Test; import ja ... -
map的三种遍历方法!
2011-07-04 13:27 993集合的一个很重要的操作---遍历,学习了三种遍历方法,三种 ... -
not in 优化
2011-06-20 14:35 151401.select * from emp where emp_ ... -
简单工厂模式与策略模式的区别
2011-06-14 16:10 3325工厂(Factory)模式我们可以做如下理解,假设有一个A ... -
UML中的关系
2011-05-30 17:14 931uml定义的关系主要有六种:依赖、类属、关联、实现、聚合和组合 ...
相关推荐
本文将深入探讨Java中的引用类型及其如何影响方法参数的传递机制。通过具体实例,我们将揭示值类型与引用类型之间的差异,并解释在实际编程过程中可能遇到的一些常见困惑。 #### 二、Java的数据类型 Java语言支持两...
本文旨在深入解析Java语言中的参数传递机制。作为一门广泛使用的编程语言,Java提供了多种处理数据的方法,其中参数传递是函数(方法)间数据交互的基础。本文将重点讨论Java中方法调用时的基本类型和引用类型参数...
在 Axis1.4 中传递复杂类型数组参数,涉及到的是 Web 服务中的数据绑定和消息处理。Axis 是一个开源的 SOAP 库,它允许开发者创建、部署和使用 Web 服务。在处理复杂类型数组时,ArrayMapping 是 Axis 中的一个关键...
通过对Java中参数传递方式的学习,我们可以更加熟练地掌握如何在方法间传递数据,这对于编写高效且易于维护的代码至关重要。此外,理解不同类型的参数传递方式也有助于避免一些常见的错误和陷阱,提高代码的质量和...
在方法调用中,`String`类型的参数是按值传递(实际传递的是对象的引用),而数组也是按引用传递,但数组本身是可以修改的,只要不改变数组的引用,就可以改变数组的内容。理解这些特性对于编写高效的Java代码至关...
在Java编程中,String对象和Byte类型的转换是常见的操作,特别是在网络编程中,因为网络通信通常涉及字节流的处理。下面将详细讲解Java中如何进行这两种类型之间的转换,并探讨其在网络编程中的应用。 首先,让我们...
Java中,当涉及到基本类型(如`int`, `double`等)的参数传递时,采用的是传值的方式。这意味着当一个基本类型的变量作为参数传递给方法时,实际上是传递了一个副本,而不是原始值本身。因此,即使在方法内部改变了...
综上所述,在Java中,对于基本数据类型的参数传递实际上是按值传递,而对于对象类型的参数传递则是按引用传递的一种特殊形式——传递的是对象引用的副本,但由于这些副本指向同一个对象,因此对对象的修改会影响到...
Java 参数传递机制是编程中的重要概念,尤其是在Java中,它涉及到“值传递”和“引用传递”的理解。这里我们将深入探讨这两个概念,并结合给定的示例代码进行解析。 首先,我们看“值传递”。在Java中,基本类型...
1. **直接传递数组:** 在Java中,当我们想要将一个数组作为参数传递给某个方法时,只需要在方法的参数列表中指定数组类型即可。 ```java public void someMethod(int[] array) { // 方法体 } ``` 上述代码...
当前端使用 jQuery 向后台传递数组类型的参数时,Java 后台尝试直接通过 `List` 类型来接收这些参数,却发现无法取到任何数据。例如: **前端代码示例**: ```javascript $.ajax({ url: "xxxx", data: { areaList...
Java 参数传递机制详解 Java 中的参数传递机制是一个经久不息的讨论...Java 参数传递机制详解,揭开了 Java 中的参数传递机制的奥秘,详细分析了基本类型和对象作为参数传递的机制,并揭开了对象作为参数传递的迷惑。
### JNI中C和Java参数传递详解 #### 一、引言 Java Native Interface (JNI) 是Java平台标准的一部分,用于让Java代码与其他语言写的代码进行交互。本文将深入探讨在JNI环境中,C/C++和Java之间如何进行参数传递,...
根据题目要求,我们将详细解析如何使用Java Applet来接收HTML文件中的参数,并计算矩形的面积与周长,最后将结果展示在Applet窗口中。 ### 一、Java Applet简介 Java Applet是一种可以嵌入到网页中的小型Java应用...
在Java编程语言中,函数参数的传递方式有两种:值传递和引用传递。理解这两种机制对于编写高效、无误的代码至关重要。以下是对这两种传递方式的详细解析。 首先,值传递是指函数调用时,实际参数的值被复制一份传给...
今天,我们将讨论如何在 Lotus Domino Java 代理中获取传递值 JSON。 代理程序的作用 在 Lotus Domino 服务器上,代理程序可以用来处理用户请求,并返回相应的数据。代理程序可以用 Java 语言编写,具有很高的灵活...
3. **类型不匹配**:Web服务的接口定义与实际传递的参数类型不一致可能导致问题。检查服务接口定义(WSDL文件)与客户端调用的参数类型是否匹配。 4. **配置问题**:Xfire的配置文件(如xfire-config.xml)可能没有...
### Java参数的传递与返回值 #### 一、Java参数传递的基本概念 在Java中,方法(或称为函数)可以通过参数来接收外部的数据,并且能够返回处理后的结果。参数的传递方式主要有两种:值传递(Pass-by-value)和引用...
总之,Java调用shell脚本向DataX传递参数,尤其是在where条件中包含特殊字符时,需要关注字符串转义、shell命令构建以及安全问题。同时,合理设计和使用配置文件能有效提高代码的灵活性和可维护性。
在Java中,这通常是通过将字符串参数直接传递给服务端方法来实现。然后,服务端代码将接收到的JSON字符串转换为JSON对象,以便从中提取所需的数据。 2. 使用诸如net.sf.json JSONObject类(一个流行的Java库,用于...