五、String在Java中是传“引用”
2016-03-12 11:41
344 查看
这个是Java的经典问题。许多类似的问题在stackoverflow被提问,有很多不正确或不完备的答案。如果不想太多你会认为这个问题比较简单。( The question is simple if you don't think too much.)如果你想的多的话,它会非常让你困扰。
1、 下面的代码片段是有有趣和让人困惑的
将会打印“ab”。
在C++里面,代码如下:
它会打印“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是只能值传递的。
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"); }
相关文章推荐
- 四、用“”或构造函数创建Java的String区别
- 三、为什么String在Java中是不可更改的
- java SE基础(多线程)
- 二 、在 JDK 6 and JDK 7中 substring() 方法
- Java 按位与(&)和短路与(&&)按位或(|)和短路或(||)的区别总结
- 一、图解Java中String不可变性
- 【JAVA】37、关于private的补充说明
- Java设计模式之适配器模式
- Java基础知识(一)
- Hadoop-Windows下的Eclipse开发环境搭建,远程虚拟机Hadoop服务器
- Eclipse的Android工具解析
- 覆盖override和重载overload的区别
- SpringMVC
- java.io.NotSerializableException
- 服务器部署JAVA程序及其调试
- MyBatis+Spring+Spring MVC整合开发
- Spring 4.2.5 - 序
- Java工程项目开发中异常处理的方法及系统
- Spring中的ContextLoaderListener作用
- Java单例模式如何理解