String类型函数传递问题

问题

  • 以前没有注意过的一个问题, 最近在使用String类型作为函数入参的时候, 发现函数内对于String类型的改变并不会影响到外层调用对象本身;

结论 (先说结论)

  • 这个问题根本不存在 (属于是自己把自己绕进去了);
  • String类型与普通的java对象一样, 只不过是用final修饰的不可变对象 (具体看String类型的源码与相关介绍);

测试数据(为什么会有这个问题, 来源于以下操作)

  • 发现String (其实Integer, Long... 等等这些类型也会这样)函数传递修改后, 对象的值并没有被改变;
  • 主要是因为String类型与Integer...等等这些类型的赋值方式迷惑了我们, 不需要通过"new"关键字和反射也可以构建对象;
  • 比如: Integer a = 123; 这种操作, 让我们误当作基本类型赋值(实际上这个问题比较基础, 但有时候也会迷糊);
  • 以下是对上述的操作案例;
package timer;

/**
* @author liwangcai E-mail:1252376504@qq.com
*/
public class StringDemo {
public static void changeString(String tmp) {
//此处操作具有一定的迷惑行为, 通常情况下只有基本数据类型才会这么操作;
//但是对与String类型, 相当于新建了一个对象或者是拿到了常量池中的对象;
tmp = "new";
//打印通过函数传递进来的tmp参数的地址
System.out.println(System.identityHashCode(tmp));
} public static void changeInteger(Integer tmp) {
//此处操作和String类型一样
tmp = 199;
//打印通过函数传递进来的tmp参数的地址
System.out.println(System.identityHashCode(tmp));
} public static void changeOther(StringDemo stringDemo) {
System.out.println(System.identityHashCode(stringDemo));
} public static void main(String[] args) {
String tmp = "old";
//打印原始的tmp
System.out.println(tmp);
//打印原始的tmp对象地址
System.out.println(System.identityHashCode(tmp));
changeString(tmp);
//打印函数调用后的tmp值
System.out.println(tmp); //出于好奇也测试了一下Integer类型
Integer iTmp = 1;
//打印原始的iTmp的值
System.out.println(iTmp);
//打印原始的iTmp对象地址
System.out.println(System.identityHashCode(iTmp));
changeInteger(iTmp);
//打印函数调用后iTmp的值
System.out.println(iTmp); //对于普通的java对象
StringDemo stringDemo = new StringDemo();
//打印当前对象的地址
System.out.println(System.identityHashCode(stringDemo));
changeOther(stringDemo);
}
} //执行结果
old
685325104
685325104
460141958
old
1
1163157884
1163157884
1956725890
1
356573597
356573597

以上测试结果得到的结果分析

  • 上面的这个操作实际上就是迷惑所在,在这里单独把它列出来看一下
Integer a;
//此处实际上是java的自动装箱, 相当于调用了valueOf函数
// 实际上是new了一个Integer对象出来,或者将另一个Integer对象直接赋值(可以去看一下Integer的源码)
a = 123;
//基础类型的直接赋值
int b;
b = 123;
//与Integer类似,String类型也有常量池, 相当于缓存, 此处不是重点;
// 相当于new了一个对象出来, 或将另一个String对象直接赋值;
String c;
c = "abc"

普通对象操作对比

/**
* @author liwangcai E-mail:1252376504@qq.com
*/
public class StringTest {
public static void changeUser(User user) {
user = new User("zhang san", 24);
} public static void main(String[] args) {
User user = new User("li si", 25);
System.out.println(user);
changeUser(user);
System.out.println(user);
} @Data
@AllArgsConstructor
@ToString
static class User {
private String name; private Integer age; }
} //执行结果, 可以发现对象的值并没有改变
StringTest.User(name=li si, age=25)
StringTest.User(name=li si, age=25)
Process finished with exit code 0

为什么new一个对象并不会改对象值?

  • 主要是因为在Java中函数传递只有值传递 (不是本博客重点, 不展开描述)

如果想要改变String的值正确的操作姿势?

  • String对象是普通的Java对象, 不过是被final修饰了;
  • 实际上String对象的值存在其内部的char value[]数组中,如果想要改变String的值应该区修改这个数组的数据;
  • 不过上述数组是使用final修饰的, 所以如果使用jdk中的String类, 那么String的值是无法被修改的;

如果要改变String的值应该怎么做?

  • 实现自己的String类型, 内部存储char[]数组不设置为final类型就可以了;
/**
* @author liwangcai E-mail:1252376504@qq.com
*/
public class MyStringTest {
public static void main(String[] args) {
MyString myString = new MyString(new char[]{'a', 'b'});
System.out.println(myString);
changeMyString(myString);
System.out.println(myString);
} private static void changeMyString(MyString myString) {
myString.setValue(new char[]{'c', 'd'});
} @ToString
@AllArgsConstructor
@Data
static class MyString {
char[] value;
}
} //测试结果
//可以发现值改变了
MyStringTest.MyString(value=[a, b])
MyStringTest.MyString(value=[c, d]) Process finished with exit code 0

总结

  • 对于String,Integer类型 "=" 操作符号迷惑了我们, 实际上一开始提出的问题并不存在;
  • 如果要修改同一个对象, 需要修改其内的成员;

String类型函数传递问题的更多相关文章

  1. string的函数的学习

    1.string类型的构造函数和对象的定义 string s3 : 把string s2 拷贝的 s3 string s4 : 把数组首地址或者字符串首地址strArr 从0开始截取到第n个字母 st ...

  2. String类型和包装类型作为参数传递时,是属于值传递还是引用传递呢?

    原理知识: 如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的.如果在函数中改变了副本的 值不会改变原始的值. 如果参数类型是引用类型,那 ...

  3. 对String值不可变的理解以及String类型的引用传递问题

    今天复习java时,突然注意到了一句以前没有注意过的一句话,String 是final修饰的,其值是不可变的.当时看的一脸懵逼,String str = "abc"; str = ...

  4. Delphi中返回类型为string的函数的一个陷阱(不是很懂)

    如果类的一个成员函数的返回值是string类型,需要注意一个问题 其返回值可能是错误的 例如函数的实现如下 function GetString( s: string ): string;begin  ...

  5. php中函数 isset(), empty(), is_null() 的区别,boolean类型和string类型的false判断

    php中函数 isset(), empty(), is_null() 的区别,boolean类型和string类型的false判断 实际需求:把sphinx返回的结果放到ssdb缓存里,要考虑到sph ...

  6. String类型_static成员_动态内存分配_拷贝构造函数_const关键字_友元函数与友元类

    1:String类型 #include <iostream> using namespace std; int main() { //初始化方法 string s1 = "hel ...

  7. printf()函数不能直接输出string类型

    因为string不是c语言的内置数据,所以直接printf输出string类型的是办不到的. 要这样输出: printf("%s\n",a.c_str()); 举例: #inclu ...

  8. string类型常用函数

    一个字符串就是一个string类型数据,此类型变量我们可以把它看作一个只读数组,其元素是char变量,在这里我们来说下string类型的常用命令. 1.TocharArray():将此实例中的字符复制 ...

  9. [STL]string类型的getline函数

    3.cin.getline() 实际是cin.getline(接收字符串到m,接收个数n,结束字符).接收一个字符串,可以接收空格等,最后一个字符为‘\0’.结束符可以通过设置第三个参数自己设置,默认 ...

随机推荐

  1. 架构师必备:Redis的几种集群方案

    结论 有以下几种Redis集群方案,先说结论: Redis cluster:应当优先考虑使用Redis cluster. codis:旧项目如果仍在使用codis,可继续使用,但也推荐迁移到Redis ...

  2. 【Java分享客栈】SpringBoot线程池参数搜一堆资料还是不会配,我花一天测试换你此生明白。

    一.前言   首先说一句,如果比较忙顺路点进来的,可以先收藏,有时间或用到了再看也行:   我相信很多人会有一个困惑,这个困惑和我之前一样,就是线程池这个玩意儿,感觉很高大上,用起来很fashion, ...

  3. iNeuOS工业互联网操作系统,数据点、设备和业务的计算与预警

    目       录 1.      概述... 2 2.      概念解释... 2 3.      数据点的计算与预警... 2 4.      设备的计算与预警... 3 5.      业务的 ...

  4. 最新管家婆财贸ERP C9 V22.0的应用网页版的财务软件1000用户补丁免狗授权注册机网络版软件下载

    管家婆财贸ERPC9应用价值: 1.多组织独立核算 多种组织形态核算,出具独立的三大财务报表及业务报表,发挥经营管理的积极性,便于专业化运营. 2.兼顾统筹与分权 满足多种集团统管与分权管控模式需求, ...

  5. 【深入理解计算机系统CSAPP】第六章 存储器层次结构

    6 存储器层次结构 存储器系统(memory system)是一个具有不同容量.成本和访问时间的存储设备的层次结构.CPU 寄存器保存着最常用的数据.靠近 CPU 的小的.快速的高速缓存存储器(cac ...

  6. UML类图六种关系的总结

    在UML类图中,常见的有以下几种关系: 泛化(Generalization):继承的关系,实线带三角形箭头,指向父类. 实现(Realization):实现的关系,虚线带三角形箭头,指向接口. 关联( ...

  7. 在Windows2003 server 64位系统上使用ArcEngine开发的WCF服务

    之前大篇文章提到,ESRI说AE10.0以后已经不支持WebService的发布,经过一段时间的测试,发现目前10.2.2版本开始的WCF服务都可以正常发布,且运行正常. 先说一下之前遇到的问题,本机 ...

  8. MongoDB 分片集群

    每日一句 Medalist don't grow on trees, you have to nurture them with love, with hard work, with dedicati ...

  9. .Net分表分库动态化处理

    介绍 本期主角:ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖.零学习成本.零业务代码入侵 背景 最近有个小伙伴来问我,分表下他有一批数据,这个 ...

  10. 爬取豆瓣TOP250电影

    自己跟着视频学习的第一个爬虫小程序,里面有许多不太清楚的地方,不如怎么找到具体的电影名字的,那么多级关系,怎么以下就找到的是那个div呢? 诸如此类的,有许多,不过先做起来再说吧,后续再取去弄懂. i ...