这个是Java的经典问题。许多类似的问题在stackoverflow被提问,有很多不正确或不完备的答案。如果不想太多你会认为这个问题比较简单。( The question is simple if you don't think too much.)如果你想的多的话,它会非常让你困扰。

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”如下图:

因为Jva是传值的,x的是“ab”的引用。当方法change()被调用时,
它创建个新的“cd”对象,x现在指向“cd”如下:

这看起来像是非常很里的解释,它们清晰的描述了Java中按值传递。
但是这里有什么错吗?

3、 代码实际上怎么做的?
上面解释有几个错误。为了方便理解,简单跟踪整个过程是个好主意。
当字符串“ab“被创建时,Java分配了大量的内存去存在这个字符串对象。因此,这个对象被赋值给变量x,这个变量实际被赋值给这个对象的引用。引用是一个存在这个对象的内存地址。

变量x存储一个字符串对象的引用。但是x不是自己不是引用。它是一个存储引用的变量(内存地址)。
Java只有传值。当x被传递给change()方法时,一份x值(一个引用)的拷贝被传递。当change()方法创建另外一个“cd“对象时候,它有个不同的引用。变量x改变了它的引用(指向”cd“),而不是引用自己。
下图显示了实际发生的。

4、 错误的解释
第一个代码片段的问题与字符串的不可变性无关。即使用StringBuilder替代String,结果仍然相同。关键是变量存储了引用,但是不是引用本身。
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");
}

五、String在Java中是传“引用”的更多相关文章

  1. Java中对象和引用的理解

    偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两方面去更形象的认识理解,再去记忆. 一.对象和引用的概念: 在Java中万 ...

  2. Java中四种引用:强、软、弱、虚引用

    这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173 Java中四种引用:强.软.弱.虚引用 1.1.强引用当我们使用new 这个关键字创建对象时 ...

  3. Java中构造函数传参数在基本数据类型和引用类型之间的区别

    Java中构造函数传参数在基本数据类型和引用类型的区别 如果构造函数中穿的参数为基本数据类型,如果在函数中没有返回值,在调用的时候不会发生改变:而如果是引用类型,改变的是存储的位置,所有不管有没有返回 ...

  4. 三、为什么String在Java中是不可更改的

    String在Java中是个不可更改的类.一个不可更改的类简单来说就是这个类的所有实例是不可以更改的.所有的实例信息在创建的时候被初始化而且信息是不可以更改的.不可更改的类有很多好处.这篇文章总结了为 ...

  5. 为什么 String 在 Java 中是不可变的?

    我最喜欢的 Java 面试问题,很棘手,但同时也非常有用.一些面试者也常问这个问题,为什么 String 在 Java 中是 final 的.字符串在 Java 中是不可变的,因为 String 对象 ...

  6. 理解Java中的弱引用(Weak Reference)

    本篇文章尝试从What.Why.How这三个角度来探索Java中的弱引用,理解Java中弱引用的定义.基本使用场景和使用方法.由于个人水平有限,叙述中难免存在不准确或是不清晰的地方,希望大家可以指出, ...

  7. 为什么 String 在 Java 中是不可变的(终极答案)

    为什么 String 在 Java 中是不可变的(终极答案) 我们可以从2个角度去看待这个问题: 1.为什么要设计成不可变2.如何保证不可变? 1.为什么设计不可变? 1.String对象缓存在Str ...

  8. java传值和传引用区别

    1. 在java中所有的参数都是传值的,引用符号&的传递是C++中才有的:2. 在java传参中,基本类型(byte--short--int--long--float--double--boo ...

  9. 在Java中动态传参调用Python脚本

    最近,又接触到一个奇葩的接口,基于老板不断催促赶时间的情况下,在重写java接口和复用已有的python脚本的两条路中选择了后者,但是其实后者并没有好很多,因为我是一个对python的认识仅限于其名称 ...

随机推荐

  1. ubuntu开机自动启动xampp/lampp的两种方法

    方法一: sudo ln -s /opt/lampp/lampp  /etc/init.d/lampp sudo update-rc.d -f lampp defaults 方法二: 1. 在/etc ...

  2. sp_trace_setfilter sqlserver筛选跟踪或跟踪过滤

    sp_trace_setfilter sp_trace_setfilter [ @traceid = ] trace_id , [ @columnid = ] column_id , [ @logic ...

  3. maven 找不到或无法加载主类

      maven 找不到或无法加载主类 CreateTime--2018年4月19日22:58:14 Author:Marydon 1.情景还原: 在maven管理的web项目中,单独运行Java类报错 ...

  4. 转:【HTTP】常见错误码说明

    一些常见的状态码为: 200 - 服务器成功返回网页404 - 请求的网页不存在503 - 服务不可用详细分解: 1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 代码 说明100 ...

  5. 搭建Hexo博客并部署到Github

    参考: http://www.jianshu.com/p/a67792d93682 http://jingyan.baidu.com/article/d8072ac47aca0fec95cefd2d. ...

  6. word使用宏定义来统一设置图片大小

    1. 首先手动拖拽将图片调到需要的格式,点击图片在格式选项中查看图片的宽高 2. 视图中点击宏新建 3. 编辑框中输入以下代码并保存,由于我只需要统一宽度,所以将统一高度的代码注释 Sub 图片格式统 ...

  7. Swift3.0生成二维码、扫描二维码、相册读取二维码,兼容iOS7(结合ZXingObjC)

    二维码生成 //MARK: 传进去字符串,生成二维码图片(>=iOS7) text:要生成的二维码内容 WH:二维码高宽 private func creatQRCodeImage(text: ...

  8. web服务器一些概念

    一.Web服务器 Web服务基于HTTP协议,HTTP协议基于TCP/IP协议. HTTP请求底层必然是套接字,也就是TCP协议,HTTP服务器就是监听端口的一个守护进程. 它负责HTTP连接的建立. ...

  9. iOS - App 间的通信方式

    1.前言 iOS 系统是相对封闭的系统,App 各自在各自的沙盒(sandbox)中运行,每个 App 都只能读取 iPhone 上 iOS 系统为该应用程序程序创建的文件夹 AppData 下的内容 ...

  10. Android应用如何适配不同分辨率的手机

    主要分三块考虑   1 )界面配置   根据不同的分辨率,创建手机界面文件   例子: 在res下创建 layout-800x480            layout-480x320   并在各自不 ...