在Java中字符串是通过引用传递的?

这是一个经典的java问题。在stackoverflow上,许多类似的问题已经被问过了,但是许多回答是错误的或不完整的。

如果你不想深入思考的话,这个问题很简单。如果你想明白的更彻底,那么问题可能容易让人迷惑不清。

1. 一段有趣但令人困惑的代码

public static void main(String[] args) {
  String x = new String("ab");
  change(x);
  System.out.println(x);
}
public static void change(String x) {
    x = "cd";
}

输出 "ab"

C++ 代码如下:

void change(string &x) {
    x = "cd";
}
int main(){    
    string x = "ab";
    change(x);    
    cout << x << endl;
}

输出 "cd"

2.经常让人捉摸不透的问题

x 存储了堆中"ab"字符串的引用。因此,当x作为参数传递到change()方法的时候,它仍然堆中的"ab",如下所示:

因为java是按值传递的,x的值是"ab"的引用。当方法change()被调用的时候,它创建了一个新的字符串对象"cd" ,然后x就指向了"cd" ,如图所示:

这似乎是一个非常合理的解释。他们很清楚,java是按值传递的,但是这里出了什么问题?

3.这段代码到底做了什么?

上面的解释有几处错误。为了更容易理解,我们最好简单的过一下整个流程。

当字符串"cd" 被创建时,java会分配储存字符串所需要的内存量。然后,对象被分配给了变量x,实际上是将对象的引用分配给了变量x。这个引用是对象储存的内存地址。

变量x包含了一个指向字符串对象的引用,x并不是字符串对象本身。它是一个储存了字符串对象'ab'引用的变量。

java是按值传递的。当x被传递给change()方法时,实际上是x的值(一个引用)的一个副本。方法change被调用后,会创建另一个对象"cd",它有着一个不同的引用。方法内的局部变量x的值变成了"cd"的引用。这里改变的是方法内的局部变量的引用值,而不是改不了原先引用的字符串"ab"。

看图:

4.错误的解释:

从第一个代码片段引发的问题与字符串不可变性没有任何关系。即使String被StringBuilder替换,结果仍然是一样的。关键点是变量存储的是对象引用,而不是对象本身!

5.解决这个问题

如果我们真的需要去改变对象的值,首先,对象应该是可变的,比如StringBuilder。其次,我们需要确保没有创建新对象并将其分配给参数变量,因为Java只是按值传递。

public static void main(String[] args) {
  StringBuilder x = new StringBuilder("ab");
  change(x);
  System.out.println(x);
}
public static void change(StringBuilder x) {
  x.delete(0, 2).append("cd");
}

作者:在下贼溜 链接:https://www.jianshu.com/p/df903886b5a9 來源:简书

原文发布于微信公众号 - java工会(javagonghui)

原文发表时间:2018-05-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏土豆专栏

Java面试之数据类型(一)

封装类是引用类型,基本类型在传递参数的时候都是按值传递,而封装类型是按引用传递的(其实引用也是按值传递的,但是传递的是对象的地址)

20420
来自专栏IMWeb前端团队

JSON Schema 参考书

本文作者:IMWeb 孙世吉 原文出处:IMWeb社区 未经同意,禁止转载 1 简介 JSON 模式(JSON Schema)是一种基于 JSON 格...

412100
来自专栏章鱼的慢慢技术路

LeetCode_1. Two Sum_Solution

这道题目的意思是给定一个数组和一个值,要求出这个数组中两个值的和等于这个给定值target。

13130
来自专栏刘晓杰

正则表达式

27890
来自专栏前端迷

数据结构与前端(一)——栈

每种数据结构都可以用很多种方式来实现,其实可以把栈看成是数组的一个子集,所以这里使用数组来实现

11320
来自专栏Python小屋

常用正则表达式锦集与Python中正则表达式的用法

1、常用正则表达式 最简单的正则表达式是普通字符串,只能匹配自身 '[pjc]ython'可以匹配'python'、'jython'、'cython' '[a-...

33050
来自专栏java初学

final关键字

402120
来自专栏JavaEE

String类相关面试题很难?不要方,问题不大前言:一、字符串的创建:二、字符串的拼接:三、intern方法:总结:

Java中有一个String类,特别让人伤脑筋。因为它可以直接赋值,也可以new一下用构造器生成对象,还可以用加号拼接……这些不同的方式到底有什么区别?本文是个...

28050
来自专栏码云1024

JAVA 第二天 关键字

30370
来自专栏Script Boy (CN-SIMO)

Java之继承、抽象类、接口篇

一、继承(extends) 什么是继承? 继承是对现实生活中的"分类"概念的一种模拟。 狮子拥有动物的一切基本特性,但同时又拥有自己的独特的特性,这就是"...

26400

扫码关注云+社区

领取腾讯云代金券