如题,在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”.

2. 通常让人迷惑的解释如下

在java堆中x存储指向“ab”的引用。所以当x作为参数传递给change()方法时,它在内存中仍然指向“ab”,如下:

由于java是值传递,所以此时x仍然指向“ab”。当chang()方法执行时,它在内存中创建了一个新的String对象“cd”,并且现在x指向“cd”,如下:

上面的解释看起来非常合理。他们也很清楚java是值传递。但是哪里出错了?

3. 上面的代码到底如何执行的呢?

上面的解释有几处错误。跟踪代码执行全过程是一个很好的方法,并且理解起来很容易。

当“ab”创建后,java分配对象所需内存空间。然后,变量x指向了“ab”,变量实际上是指向对象的引用。这个引用指向对象存储的地址。

x保存了一个指向String对象的地址。x不是引用本身!它是保存一个内存地址。

在Java中只有值传递。当x通过参数传递给change()方法后,x被拷贝了一份。change()创建了另一个对象“cd”,并且x指向了不同的地址空间。实际上是x改变它的引用(指向“cd”),不是x本身。

下图展示了x在内存的变化

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");
}

  

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

  1. Java中String的 "引用" 传递

    1.来看一段有趣但又让人困惑的代码片段 public static void main(String[] args){ String x = new String("ab"); c ...

  2. Java中参数的引用传递和值传递

    1.一些定义 值传递:把实际传入参数的值,在内存中赋值一份 引用传递:传入的是实际参数的地址 2.传递基本类型的参数 因为Java是值传递,那就不难理解下面的代码不交换任何值 swap(Type ar ...

  3. Java中到底是值传递还是引用传递?

    Java中到底是值传递还是引用传递? 我们先回顾一下基本概念 实参和形参 参数在编程语言中是执行程序需要的数据,这个数据一般保存在变量中.在Java中定义一个方法时,可以定义一些参数, 举个例子: p ...

  4. java中String类型变量的赋值问题

    第一节 String类型的方法参数 运行下面这段代码,其结果是什么? package com.test; public class Example { String str = new String( ...

  5. 2013年6月19日星期三java中函数地址值传递

    今天代码审核时确认了一个问题,理解了java中string和stringbuffer赋值问题,看到一个帖子很好,摘录如下: 理解这两个例子需要分清实参和形参的区别,引用和对象的区别 第一个例子的内部执 ...

  6. java成神之——java中string的用法

    java中String的用法 String基本用法 String分割 String拼接 String截取 String换行符和format格式化 String反转字符串和去除空白字符 String获取 ...

  7. Java中真的只有值传递么?

    Java中真的只有值传递么? (本文非引战或diss,只是说出自己的理解,欢迎摆正心态观看或探讨) 回顾值传递和引用传递 关于Java是值传递还是引用传递,网上有不一样的说法. 1.基本类型或基本类型 ...

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

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

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

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

随机推荐

  1. PHP提取身份证号码中的生日并验证是否成年的函数

    php 提取身份证号码中的生日日期以及确定是否成年的一个函数.可以同时确定15位和18位的身份证,经本人亲测,非常好用,分享函数代码如下: <?php //用php从身份证中提取生日,包括15位 ...

  2. 如何配置SSH Keys登录

    SSH Keys简介: 使用SSH Keys的登录远程虚拟云主机的方式比单独使用密码登录更加安全,简单的密码很可能被暴力破解.而目前来看采用长度大于1024位的RSA加密算法,几乎是不可能被破解的.S ...

  3. ubuntu系统软件

    1.办公软件:wps 2.浏览器:firefox,opera 3.思维导图:xmind 如果您有好的软件,请推荐给我,谢谢!

  4. 图片生成操作属性导致WP内存溢出解决办法

    在开发的项目中,发现经常会出现异常 “内存溢出,不能再继续执行程序”,通过搜索一些国外的文章,发现原来是由于项目中的图片比较多,而生存操作设为了“内容”.通过设置图片的生成操作为“无”,复制操作为“如 ...

  5. hadoop 存储空间满了

    -- ::, WARN mapred.LocalJobRunner - job_local_0001 org.apache.hadoop.util.DiskChecker$DiskErrorExcep ...

  6. WEB黑客工具箱之FireBug介绍

    Firefox扩展Firebug是一个全功能的Web 应用程序调试器,可以协助Web黑客洞悉复杂的Web 应用程序的内部工作机制.它有两种版本:一种可以跨浏览器使用的组件Firebug Lite,另一 ...

  7. Cloud Test 单页面即时监测功能上线!

    什么是即时监测? 即时监测,顾名思义是指输入 URL 后能够立即进行监测并展示结果,无需注册. 如下图,在输入框内输入需要监测的 URL,点击免费监测,即可展示网页监测结果: 图中我们可以看到页面各个 ...

  8. PIL(Python Image Library)生成验证码

    # -*- coding: utf-8 -*-#导入三个模块import Image,ImageDraw,ImageFontimport randomimport math'''基本功能'''#图片宽 ...

  9. Jmeter 日志设置---如何设置java协议中被测jar的日志?

    先转载一下Jmeter的日志设置: Jmeter运行出现问题可以通过调整jmeter的日志级别定位问题,但运行测试时建议关闭jmeter日志,jmeter打印日志耗费系统性能. Jmeter日志默认存 ...

  10. Cassandra命令行CLI的基本使用

    启动cassandra-cli服务之后,可以进行CQL的使用. 1. 创建keyspace 可以理解成关系数据库的database [default@testkeyspace] create keys ...