Java中String类型的参数传递问题的解析收藏--转载

【EPS精品教程】EPS2016三维测图版安装教程(附EPS2016安装包下载地址) EPS地理信息工作站是北京清华山维新技术开发有限公司历经十五年精心研发和打造,为满足“以地理信息服务为中心”的信息化测绘生产需求而推出的测绘生产活动多种业务模块集成化软件系统。主要功能有:(1)测绘与地理信息多业务模块集成管理;(2)多元多尺度多种类数据集成管理;(3)跨平台异构数据转换;(4)数据监理;(5)自动缩编与综合;(6)坐标转换与动态投影;(7)地理信息模板定制;(8)GIS地理信息描述与CAD图形表达一体化支持;(9)GIS数据库更新维护;(10)图形打印与地图出版。 一、安装过程 EP.. 阅读详情

 

 

<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:1; mso-generic-font-family:roman; mso-font-format:other; mso-font-pitch:variable; mso-font-signature:0 0 0 0 0 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} -->

 

一、          最开始的示例

写代码最重要的就是实践,不经过反复试验而得出的说辞只能说是凭空遐想罢了。所以,在本文中首先以一个简单示例来抛出核心话题:

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的实现就会明白了,在此也不再赘述了。

【NVIDIA】Jetson Orin Nano系列:烧写Ubuntu22.04 Jeson Orin Nano系列:烧写Ubuntu22.04 电脑主机可以是Ubuntu20.04 阅读详情

相关推荐

从零到一:Quartus II连接开发板实战,打通绘图、管脚分配、编译与下载全链路

本文详细介绍了使用Quartus II软件连接FPGA开发板并完成首个项目的全流程。从硬件连接到驱动安装,到绘制电路框图、精准分配管脚,再到编译设置与最终下载,手把手指导您打通从设计到硬件实现的完整链路,是FPGA初学者的实战入门指南。

mqtt6iot的博客 717

Java方法中参数String...你需要知道的事

String…的含义 String… args 为类型后面三个点(eg:String …),是从Java 5开始,Java语言对方法参数支持的一种新写法,叫可变长度参数列表;表示此处接受的参数为0到多个Object类型的对象,或者是接受一个String[] 类型的参数。 String…的使用 在使用的时候,对于test(String…strings),你可以直接用test()去调用,表示无参调用,也可以用去test(“abc”),也可以用test(new String[]{“abc”,”abd”}),但你不

CowboyStyle的博客 7358

Kafka 系列 —(17)Kafka 流式处理:Kafka Streams架构、使用场景、框架选择

本文介绍了KafkaStreams的架构特点、应用场景及与其他流处理框架的比较。KafkaStreams作为嵌入式分布式流处理库,其核心架构包含流处理器、任务、拓扑和本地状态存储,具备自动容错和伸缩能力。适用于实时监控、ETL、聚合、Join、物化视图等低延迟场景。与Flink、Spark相比,KafkaStreams适合简单架构和微服务,而Flink适合大规模处理,Spark更适合批处理。选择框架需根据具体场景需求,如微服务推荐KafkaStreams,大规模处理推荐Flink。

moton2017的博客 1631

Java方法参数类型String...与String[]的使用方式比较

String[]需要一个数组作为参数,而String…可以接受任意数量的字符串作为参数,并将它们作为一个数组传递给方法。,也被称为参数的不定数量。而在Java中,使用。

专注于优雅与性能的未来架构师 2767

sap2000 api matlab,SAP2000_API入门指南.pdf

SAP2000_API入门指南北 京 金 土 木 软 件 技 术 有 限 公 司Beijing Civil King Software TechnologyCo., Ltd.SAP2000 API 入门指南余承飞 韦群跃 汤娣概述SAP2000 API 是从 SAP2000 V11 开始引进的,即应用软件编程接口。用户可以编写程序,通过API 随心所欲地调用 SAP2000...

weixin_42118423的博客 1942

自动驾驶中的多传感器融合实战:用卡尔曼滤波搞定毫米波雷达与摄像头航迹对齐

本文深入探讨了自动驾驶中多传感器融合的实战技术,重点介绍了如何使用卡尔曼滤波实现毫米波雷达与摄像头的航迹对齐。通过分析传感器特性差异、时空同步挑战及工程化实现步骤,提供了包括状态向量定义、观测矩阵设计和故障检测机制在内的完整解决方案,最终实现0.15米以内的高精度航迹对齐。

weixin_28728495的博客 411

参数String... 类型后加三个点的用法

参数String… 类型后加三个点的用法 这是一种定义多个形参的方式 使用String… 表示该参数可以是0个或者多个。 场景: 通常在写工具类的时候会这么用, 用法示例如下 public class TestManyParam { /** * @param stringValues 可以是没有参数,也可以是好几个参数,可变参数列表 * @return 所有参数的拼接 ...

星游LK的笔记 1602

Gamit10.71添加新的天线类型

添加新的天线类型需要涉及到四个文件:antmod.dat,rcvant.dat,guess_rcvant.dat,hi.dat。 注意:格式要一致!!! 举例说明,我要添加一个JCA229的天线(带JCAD天线罩),对应接收机使用的是南方的South Net-S9。

Penny的博客 2713

Java的可变参数,参数后面三个点

private void removeTempFiles(String... fileNames) { for (String fileName : fileNames) { try { new File(fileName).delete(); } catch (Exception e) { }

沸沸腾的专栏 3131

[USACO2023-JAN-Bronze] T2 Air Cownditioning II 题解

[USACO2023-JAN-Bronze] T2 Air Cownditioning II题解

1652

通信算法之334:无人机侦测-DJI 大疆云哨接收机系列

【代码】通信算法之334:DJI 大疆 云哨接收机算法流程。

leegang12的专栏 844

Java String...的使用-》扩展到【数据类型】...

[数据类型]... 将会允许你传入一个[数据类型]和[数据类型][] 两种传参方法

blastospore的博客 317

软考「系统规划与管理师(第2版)」通关全攻略(2026年下半年)

它考的是一个IT管理者能不能用体系化的语言,把"我们为什么要建这个系统→怎么规划→怎么管好服务→怎么合规"讲圆。所以备考的核心策略也很明确——教材建框架 → 真题磨考点 → 案例练结构 → 论文备好真实项目素材 → 机考练打字。按计划走,不贪全、不盲刷、不死背,稳稳把三科都推过45分那条线。祝你通关 🎯。

软件行业技术文化交流。 3048

JAVA方法参数传递

JAVA方法参数传递 package demo.methodparamDemo; public class MethodParamsDemo { public static void main(String[] args) { int num = 10; ...

184

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

关于Java中形参与实参的理解

关于Java中形参与实参的理解 今天阅读了一个写的非常棒的博文,通过此博文再次复习了Java中参数传递的知识(即值传递与引用传递的区别)。参考网站http://www.cnblogs.com/binyue/p/3862276.html。下面我将通过次博文记录自己的理解,还望能够帮助再学Java或者复习Java的朋友们。 一、基本类型与引...

weixin_30528371的博客 599

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深入解析Java堆内存溢出与栈溢出:原理、诊断与实战预防

在Java开发中,内存管理是性能优化的核心,而理解JVM内存模型是基础。JVM内存主要分为堆(Heap)和栈(Stack)等区域,它们共同协作支撑程序运行。堆是线程共享的运行时数据区,用于存储对象实例和数组,其生命周期由垃圾回收器(GC)管理;栈则是线程私有的,用于存储局部变量、操作数栈和方法调用信息,遵循后进先出原则。从原理上看,堆内存的动态分配和GC机制直接关系到程序稳定性,不当的对象引用管理易导致内存泄漏,进而引发OutOfMemoryError;而栈的有限空间则对方法调用深度敏感,递归过深或局部变量

weixin_34185320的博客 425

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

String ... String 三个点 jdk1.5的特性.才知道

String ... String 三个点 jdk1.5的特性.才知道 String... excludeProperty表示不定参数,也就是调用这个方法的时候这里可以传入多个String对象。public static void main(String[] args) { //测试,传入多个参数 ...

weixin_30794499的博客 108

(转)string和stringbuffer区别

(转)string和stringbuffer区别 关于string和stringbuffer的区别,一直是面试的重点哦,这里转自刑红瑞的一篇BLOG,简单而清晰讲了其区别,收藏之,原文来自http://blogger.org.cn/blog/more.asp?name=hongrui&id=11880 string和stringbuf...

weixin_30600503的博客 69

Android修行手册 - 可变参数中星号什么作用(冷知识)

这是因为 Java 中的 vararg 参数在被传递给 **String.format()** 方法时,会自动被转换为一个数组。这表示我们将 args 数组作为参数传递给 String.format() 方法。这样做是为了确保 **args** 数组能够以参数的形式传递给 String.format() 方法,以便正确地进行格式化字符串。

空名先生 437

形参的一种特殊写法

形参的一种特殊写法 import java.lang.*; import javax.swing.*; import javax.swing.text.IconView; public class Xample_3 { pu...

weixin_30445169的博客 107

java 可变参数String...用法

public class test { //调用方法 public static void main(String[] args) { printArr("1","2"); } //含可变参数的方法(注,可变参数只能放在末位) public static void printArr (String... s){ for (String str:s) {

sl475900947的博客 1908

String字符串以及数组参数

String类 System.String是一个专门存放字符串的类,允许字符串进行许多操作。 由于这种数据类型非常重要,C#提供了它自己的关键字和相关的语法,以便于使用这个类来轻松地处理字符串。 这个类可以完成很多的常见的任务,如替换字符串、删除空白字符串和把字母变成大写形式等。 String类是个功能非常强大的类,它实现许多有用的方法。但是,String类存在一个问题:重复修改给定的字符串,...

qq_42024185的博客 1049

String类型参数传递和扩展

String类型的参数传递&equals()方法 JAVA的数据类型和引用类型的参数传递是java初学者们经久不衰的话题 利用空余的时间,我给大家大概的总结了下,随便扩展下String类型的参数传递 相信之前大家都对数据类型和引用类型的参数传递有所了解,废话不多说,直接看码 static void change(int methodVar) { System.out.println("change before,x=" + methodVar); //10

weixin_48254340的博客 1339

java.lang.String--String类型传参

Java只有一种参数传递方式:值传递 基本数据类型: 传参传递的就是数值的副本,也就说把实参的数据复制给形参一份,不管形参怎么改变,实参是不受影响的。 引用类型: 引用数据类型,参数传递的是引用的副本。即把实参的引用(指向对象的地址)复制一份,然后赋给形参,此时形参与实参都指向同一个对象,因为他们的值相同(都是引用对象的地址)。 1、把形参引用指向一个新对象------------将实参的引用地址赋给形参,此时形参中保留的是对象在堆中的引用地址。 1、把形参引用指向一个新对象-------.

qaws9403的博客 1285

java pattern详解_Java Pattern pattern()用法及代码示例

Java中Pattern类的pattern()方法用于获取正则表达式,将其编译以创建此模式。我们使用正则表达式创建模式,并且使用此方法来获取相同的源表达式。用法:public String pattern()参数:此方法不接受任何内容作为参数。返回值:此方法返回模式的源正则表​​达式。以下示例程序旨在说明pattern()方法:示例1:// Java program to demonstrate/...

weixin_42102933的博客 2664

String(bytes, offset, length)参数的含义

String(bytes, offset, length) bytes为要翻译的 字符串/数组。 offset为要解译的第一个索引,比如从0开始就是第一个字符开始。 length为要翻译的字符串bytes的长度。

junmoxiao_的博客 1150
上一篇: AWT、SWT 和 Swing
下一篇: JavaBean的属性
sofful
博客等级 码龄18年 0粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值