String的按值传递,java传参都是传值

2023-05-16

看完绝对清晰~

java中对象作为参数传递给一个方法,到底是值传递,还是引用传递?

pdd:所谓java只有按值传递:基本类型  值传递;引用类型,地址值传递,所以叫值传递。

    当主函数的变量,对象(主本)传递到副函数时,传递的变量、对象(方法中的形参)其实都是副本,而副本的改变不会影响主  本。

基本类型:传递的是值的拷贝,也就是说传递后就互不相关了,也就是说,不过副函数的副本如何变化,主本永远不会被影响。

引用类型:传递的是引用地址值,有可能会被影响。

string:具有不可变。是特殊的引用类型,其作用跟基本类型一样,传递后不相关。


原作者:

String和int参数传递是按值传递还是引用传递?

一道面试题目,String的传递:

1
2
3
4
5
6
7
8
9
public  String change(String s){
      s =  "222" ;
      return  s; 
}
public  static  void  main(Stirng[] args){
     String s =  "111"
     change(s);
     sout(s);
}

我看到题目愣了一下,本来不假思考的结果是111,但仔细想,String是对象类型的,对象传递的是地址,那么地址传递到方法里面后,将指向修改成222,那么结果应该是222才对。实际恰恰相反。

Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本。指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的。 

java传递参数都是值,如果是对象的话,就是将引用的值复制一份给方法当参数。如果是根据引用把堆里的对象修改了,那么对象真被修改了,不过不是被创建赋值给的那个引用修改的,是方法里的一个复制的引用副本给修改的。换句话说,施瓦星格的媳被施瓦星格的克隆人亲了下。

用实例去理解,其实这个理解也就是根据jdk的结果告诉我自己记住规则是这样的,以后要记住。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   public  String change(String s,  int  i, StringBuffer sb, Person p){
         s= "123" ;
         i= 3 ;
         sb.append( "woshi" );
         p.setAge( 100 );
         sb =  new  StringBuffer( "sbsb" );
         p =  new  Person( "bb" , 44 );
         return  s;
     }
 
     @Test
     public  void  testChange(){
         StringBuffer sb =  new  StringBuffer( "buff" );
         String s =  "aaa" ;
         int  i =  1 ;
         Person p =  new  Person( "aa" , 12 );
         i= 2 ;
         change(s,i,sb,p);
//        s="222";
         System.out.println(s);
         System.out.println(i);
         System.out.println(sb.toString());
         System.out.println(p);
     }

这里一共测试了String,int,一个对象StringBuffer,一个对象people。让我们来仔细看看这些传递都发生了什么。我想有很大一部分人都猜不出打印结果。

1
2
3
4
aaa
2
buffwoshi
Person{id= 0 , name= 'aa' , age= 100 , Country= null , hashcode= 638783031 }

我们来一个个分析。

首先是String。

1
String s =  "aaa" ;

这里,jvm创建一个变量引用s,在堆中创建一个对象aaa,将aaa放进常量池。s指向aaa。

然后就到了change方法里。这里这样理解:将s引用的一个拷贝传给方法change。这样change有一个变量s,这个s也是指向aaa的。那么我们来通过debug来看后来发生了什么。

1.s指向aaa的时候:

2.s运行到change方法里的时候

然后看s再次赋值的时候:

然后我们运行结束change方法后到主方法里:

到这里s就结束了。那么如果我们按照传递的是s这个变量的引用,即String s="aaa"中这个s本身,那么,s这个本身是个变量,s指向aaa,在方法change里s又指向了123,回到主方法后s变量的指向被改变了?错!显然s仍旧是aaa,那么只能这样理解:s传递到方法里的时候,复制了s指向的地址给change,change里的s是另一个s,s指向aaa(@718),然后在change中s又指向了123(@731),由于String是不可变类(final and Immutable),这里只是把副本s的指向修改成731,原地址718里的对象没有发生改变因为String不可变。那么,回到主方法的时候,s变量本身没有任何改变,s仍旧指向地址718,718的内容是aaa。所以最终打印aaa。

然后是StringBuffer

int是基本类型,所以int只是将值复制一份给别的方法用,这个大家都知道,就不去测试了。现在看StringBuffer发生的改变。

1.初始化:

2.到change方法中:

3.发生append

4.指向新对象

这里就要说一下了,副本指向了新对象。就好比,施瓦星格的克隆人找了另一个女的当老婆,而真正的施瓦星格老婆没有变。

5.回到主方法:

 

到这里,StringBuffer就结束了。我们必须知道,虽然我们没有去研究源码是怎样实现的,change方法得到是一个sb的副本,只不过这个副本指向708,在change里对708的对象追加,708的对象就真的改变了。然后又把sb副本指向新地址737。这只是把副本指向的地址修改了,如果你在这里打印sb.toString(),打印的就是737里的内容。当跳出change,回到主方法的时候,原sb仍旧还是指向708的,最终就是打印708的结果。和String不同的是,StringBuffer的结果发生了变量,因为StringBuffer是可变的,可以append。而String是不可变的,在change中s=123就是发生两个行为,一个是查找常量池中是否有123,如果没有就在堆中创建123,一个是将s指向123.也就是说这时候是创建了一个新的String对象,而不是把原来的String对象s内容修改。这样,回到主方法的时候,s仍旧是aaa。

同理,看自己创建的对象people

 

1.初始化:

2.p传递到change里的时候

3.p副本设置age

4.p副本重新赋值

 这里仍旧要说一下,p副本修改了自己指向,并不影响主方法里的p的指向。主方法里的p的指向没有发生变化,依旧应该还是720.

5.回到主方法

总结:

通过上面对String,StringBuffer,People的研究,应该明白一个道理,重要的话说三遍,重要的规则我都演示了三遍。如果跟着步骤一步步走的,肯定牢记住了:

java所有的参数传递都是传递的副本,变量所代表的值的副本!java所有的参数传递都是传递的副本,变量所代表的值的副本!java所有的参数传递都是传递的副本,变量所代表的值的副本!

这里必须记住的就是副本概念。在方法里,运行的时候到这里的线程都会把传过来的参数拷贝副本带自己的工作区中,在工作区中对这个副本的值发生一些改变。最终改变的是副本,如果通过副本的指向修改了指向中的内容,那么那个指向的地址里的内容确实改变了。如果修改了副本的指向,即给副本重新赋值,那么关原来的变量何事?元变量仍旧指向最初的地址。

那么,String传递过去的是副本,修改了副本的指向,打印元string是不会改变的,因为副本没有能力修改final的String类。


出处:http://blog.csdn.net/zzp_403184692/article/details/8184751

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

String的按值传递,java传参都是传值 的相关文章

  • 位域,段域,联合体,结构体操作寄存器

    include lt stdio h gt typedef int Uint16 struct SCICCR BITS bit description Uint16 SCICHAR 3 2 0 Character length contro
  • C++ 网络编程之使用socket + epoll 模拟http 的请求与响应

    为了更好的理解http协议 xff0c 笔者使用了C 43 43 socket模拟了一个http服务器 xff0c 其中的服务器使用了epoll的方式 xff0c 并针对每一个新的连接开启新线程处理 大致分为三个部分 xff0c 具体代码可
  • 【Nova】nova-scheduler过滤称重

    在上一篇 nova scheduler调度过程分析 中 xff0c 对过滤称重的过程一笔带过了 xff0c 这篇着重介绍一下 首先 xff0c 我们声明一下host为主机 xff0c node为节点 xff0c 在OpenStack中一个h
  • 1.通过tcp从daytime服务器获取时间

    最近愈发觉得在学习源代码或者看书的时候 xff0c 做下读书笔记 xff0c 不仅能加深印象和理解 xff0c 同时也方便日后进行回顾 xff0c 所以就写下UNP UNIX网络编程 卷1的读书笔记 xff0c 涉及到的代码基本都是原作者提
  • 4.IPv4和IPv6地址长度

    IPv4地址的二进制形式长度为32 xff0c 使用我们常用的点分十进制形式进行表示那么最长长度为15 xff0c 例如 255 255 255 255 所以在posix的 lt netinet in h gt 中定义的IPv4地址字符串形
  • 29.Nginx HTTP之请求行解析函数ngx_http_parse_request_line

    Nginx的HTTP模块中使用ngx http parse request line函数来对读取的请求行进行解析 xff0c HTTP请求行的格式不是很复杂 xff0c 但是要注意HTTP 0 9与1 0 1 1之间的区别 xff1b 另外
  • 4. 事务隔离级别之Read Uncommitted

    前面我们说过 xff0c 要获得最高的事务隔离性 xff0c 可以采取序列化 串行的方式 xff0c 代价是严重影响系统处理事务的吞吐量 就好像数据库是个多核CPU xff0c 事务串行后 xff0c 那么意味着我们总是在使用单核 xff0
  • Vision Transformer学习笔记

    Vison Transformer学习笔记 1 前言2 网络结构 amp 设计原理2 1 Linear Projection of Flattened Patches2 2 Transformer Encoder2 2 1 Layer No
  • 5. 事务隔离级别之Read Committed

    这篇我们学习事务隔离级别Read Committed xff0c 顾名思义 xff0c 就是读已提交 xff0c 一个事务只能看到其他并发的已提交事务所作的修改 很显然 xff0c 该级别可以解决Read Uncommitted中出现的 脏
  • 6. 事务隔离级别之Repeatable Read

    接下来我们学习Mysql默认的事务隔离级别Repeatable Read xff0c 顾名思义 xff0c 可重复读 xff0c 也即在一个事务范围内相同的查询会返回相同的数据 延续上面的栗子 xff1a 1 小明很开心自己考了69分 xf
  • 7.事务隔离级别之Serializable

    最后我们学习一下最高的事务隔离级别Serializable xff0c 顾名思义 xff0c 可串行化的 xff0c 也即并发事务串行执行 很显然 xff0c 该级别可以避免前面讲到的所有问题 xff1a 脏读 不可重复读 和 幻读 代价是
  • 6. 消息发送重试

    当连接失败 xff0c Celery会自动重试发送消息 xff0c 我们可以对重试行为进行设置 xff0c 譬如说多久重试一次 最大重试次数或者干脆不重试 xff01 当然这只是官方文档说的 xff0c 我在Windows上进行测试 xff
  • 1. RabbitMQ安装

    RabbitMQ作为消息队列 xff0c 在分布式系统中具有举足轻重的作用 xff0c 能够方便地解耦各个组件 xff1b OpenStack之所以具有高扩展性 xff0c RabbitMQ功不可没 虽然一直都在用 xff0c 但没有进行过
  • 1. Tornado实现聊天室

    Tornado的异步I O机制使其很适合处理长连接的场景 xff0c 在官方提供的Demo中就有一个简单的聊天室实现 xff0c 大致做法如下 xff1a 1 提供一个全局的消息缓存 2 每次获取新消息时 xff0c 如果缓存中没有新消息出
  • D435i运行VINS-mono以及Kalib标定

    D435i运行VINS mono以及Kalib标定 系统说明 xff1a Ubuntu 18 04 内核版本 xff1a 5 4 0 1 运行VINS mono 参考博客VINS xff08 D435i xff09 测试 问题 xff1a
  • ESP8266/ESP01 Server模式中TCP Client无法接收到数据

    硬件环境 xff1a ESP01 ESP8266 Windows7 xff0c 网络调试助手 xff0c 串口调试助手 先设置ESP8266的服务器模式 AT 43 CIPMUX 61 1 AT 43 CIPSERVER 61 1 8080
  • ROS报错:TF_OLD_DATA ignoring data from the past for frame leftwheel_link

    现象 xff1a rviz 中提示no transform from XX to odom 原因 xff1a lt param name 61 34 use sim time 34 value 61 34 true 34 gt 中use s
  • STM32-寄存器编程-使用寄存器点亮LED

    一 工程文件的建立 1 我们建立一个 工程模板 文件夹 xff0c 在它下面在新建4个文件夹 Listing存放编译器编译适合产生的C 汇编 链接的列表信息Project存放工程Output存放编译产生的调用信息 hex文件 预览信息 封装
  • VC 与VS的区别以及各个版本之间的对应关系

    各个版本之间的对应关系 使用windows平台搞开发时 xff0c 下载第三方库时经常会遇到文件名以VCxx版本号命令 xff0c VC版本如何转换成对应的VS的版本呢 xff0c 这里总结一下vc和vs的关系 Microsoft Visu
  • C/C++永不过时,不服来辩!

    序言 当你需要为你的项目放弃不同部分的时候 xff0c C 43 43 能帮你做到 当你需要不同抽象层次不同的性能要求时 xff0c C 43 43 能帮你做到 如果用别的语言 xff0c 你会发现那个语言只能做某几类的 而C 43 43

随机推荐

  • 标准c++库和stl库,boost库,qt库的总结(一)

    用了很长时间是stdio iostream 等头文件 xff0c 一直有个疑惑 xff0c 也用了很长一段是键的stl标准库中个别的类 xff0c 间接性的知道了boost库 xff0c qt库等一系列的库 昨天在有用到 include l
  • 激光雷达的结构和分类

    在蔚来ET7的发布会上 xff0c 李斌特别指出 xff0c ET7搭载了1550nm的激光雷达 小鹏P5搭载的两颗大疆览沃车规级激光雷达在ROI区域积分时间0 1秒下 xff0c 能等效144线 极狐阿尔法S HI版搭载的华为的车规版激光
  • STM32之串口通信之printf重定向

    当我们在学习一款CPU时 xff0c 最经典的实验莫过于流水灯了 xff0c 掌握流水灯的话就基本等于学会操作I O口了 xff0c 那么在学会I O之后 xff0c 相对于我们来说会把学习串口的操作放在第二位 在程序运行的时候我们可以点亮
  • 网络RTK——主辅站误差改正法(MAC)

    主辅站误差改正法的基本思想是 xff0c 首先 xff0c 将基准网内所有基准站的相位距离转换到公共整周未知数水平 xff0c 即整周模糊度被消除 其次 xff0c 计算各个误差改正项 xff0c 充分考虑误差的色散和非色散特性 xff0c
  • Centos7 thinkphp6 安装 swoole 小皮面板环境

    环境准备 xff1a centos 7 thinkphp6 nginx 小皮面板 本想着根据官方指引https www kancloud cn manual thinkphp6 0 1359700 完成安装 xff0c 结果中间波折挺多 x
  • 关于qt中加载gif图片,cpu占用过高的解决发办法

    1 将gif图拆分成若干张静态png图 xff1b 2 程序启动 xff0c QImage对象list中 xff1b 3 使用定时器或者多线程来控制label setPixmap加载的QImage对象 xff1b 关于gif显示快慢的问题
  • linux下命令行方式的音量控制

    输入命令 xff1a alsamixer xff1b 设置系统音量 xff0c 这个百分比会有一定的误差存在 amixer set Speaker 100 设置系统麦克风 amixer set Mic 100 c 43 43 代码可以执行运
  • Ubuntu检测ip有效性 且 修改系统ip

    正则表达式实现检测IP地址是否有效 bool UntilTool CheckIPAddrIsVaild string str regex check ip 34 25 0 5 2 0 4 0 9 1 0 9 0 9 1 9 0 9 1 9
  • clion同一个项目创建多个可执行文件

    简述需求 xff1a 需要写多个可执行文件 xff0c 但是文件一些工具类等都是通用的 xff0c 比较麻烦的就是创建多个项目 xff0c 下来让你一个项目中生成多个可执行文件 xff0c 用到那个编译那个就可以了 默认创建好项目后 xff
  • Visual Studio Code (vscode) 配置C、C++环境/编写运行C、C++(Windows)【真正的小白版】

    写在前面的前面 xff1a 这篇文章vscode和cpp插件版本有点老了 xff0c 仅供大家参考 xff0c 最新的和最详细的更新见我的另一篇文章 xff1a https blog csdn net bat67 article detai
  • linux服务端下的c++ udp socket demo

    linux服务端 udp socket demo 如下 xff1a 创建接受数据的socket int iSock 61 socket PF INET SOCK DGRAM 0 printf 34 socket ss d n 34 iSoc
  • ROS个别命令的使用 ros ros2

    ros1 录包 rosbag record a O filename bag 解释 xff1a a是把所有的包都进行录制 xff0c O表示后面需要跟输出的文件名字 xff0c o的话系统会自己添加录制日期为文件名上 xff1b rosba
  • 浅析 自动驾驶、遥控驾驶、平行驾驶区别

    以下内容仅为个人粗浅理解 xff0c 欢迎大家留言指正 图片内容来源于互联网 xff0c 图片权利归图片作者所有 xff0c 本文仅引用 自动驾驶 xff1a 重点在车端 xff0c 自动驾驶相关资源部署在车端 xff0c 或大部分算力等都
  • CNN图像分割简史:从R-CNN到Mask R-CNN(译)

    一直想总结一下CNN在图像分割中的发展脉络 xff08 主要是R CNN及其改进方法 xff09 xff0c 看到一篇不错的英文博文 A Brief History of CNNs in Image Segmentation From R
  • c: __FILE__, __LINE__

    这是编译器内置宏 xff0c 这些宏定义不仅可以帮助我们完成跨平台的源码编写 xff0c 灵活使用也可以巧妙地帮我们输出非常有用的调试信息 注意 xff0c 是双下划线 xff0c 而不是单下划线 FILE 包含当前程序文件名的字符串 LI
  • 当数组遇到mybatis in 的时候

    我想实现 多个id 传入sql 语句 的操作 1 我试着将数组 stringUtils join 数组 34 34 数组转string 并以逗号分隔 没成功 因为传到sql 里是 123 234 435 xff0c 而我们需要的是 123
  • jeesite中的ztree应用

    话不多说 xff0c 直接开始一二三 jeesite页面上通过以自定义jstl lt sys treeselect gt 方式引入树形选择 1 lt sys treeselect id 61 34 company 34 name 61 34
  • getByte()用法小结

    在Java中 xff0c String的getBytes 方法是得到一个操作系统默认的编码格式的字节数组 这个表示在不同情况下 xff0c 返回的东西不一样 xff01 String getBytes String decode 方法会根据
  • plsql 导出表和表数据

    导出数据表结构 打开pl sql客户端 Tools Export User Objects xff08 工具 导出用户对象 xff09 按图选择自己需要导出的表 xff0c 在选择导出文件位置 导出表数据 Tools Exports Tab
  • String的按值传递,java传参都是传值

    看完绝对清晰 java中对象作为参数传递给一个方法 xff0c 到底是值传递 xff0c 还是引用传递 xff1f pdd xff1a 所谓java只有按值传递 xff1a 基本类型 值传递 xff1b 引用类型 xff0c 地址值传递 x