字符串是通过“引用”传递的

简介:

一段有趣且让人困惑的代码

复制代码
package simplejava;

public class Q14 {

    public static void change(String x) {
        x = "cd";
    }

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

}
复制代码

结果打印:

ab

C++版本如下:

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

打印结果:

cd

常见有误的理解

x变量存储了堆中“ab”对象的引用,当x作为一个参数传入到change()方法内部时,仍然指向堆中的“ab”对象,如下所示:

因为Java是按值传递的,x的值是“ab”对象的引用,当方法change()被调用时,创建了一个新的对象“cd”,然后x指向“cd”对象,如下图所示:

这看起来像是一个完美的解释,他们很清楚Java总是按值传递的。但是,问题到底出在哪里呢?

这段代码到底究竟在做什么

上面的解释有若干处错误,为了更加容易的理解该问题,我们还是先理清下整个过程。

当字符串对象“ab”被创建的时候,Java分配了对应大小的内存空间,然后对象被赋值给变量x,事实上是x变量存储的是对象的引用,这个引用是“ab”对象在内存中的地址;

x变量包含了对象的引用,x并不是“ab”对象,而是一个存储了“ab”对象引用(内存地址)的变量。

Java是按值传递的,当x被传入change()方法的时候,事实上传入的是一个x变量的拷贝。然后在方法change()内部创建了另一个对象“cd”,它有一个不同的引用。真正改变的是这个x变量的拷贝,其值变成了“cd”对象的引用,而不是原始的x变量被改变;

注:感觉说得有点混乱,我的理解,先说这个参数x,其相当于一个局部变量,当使用该参数的时候,将会分配一个新的存储位置,将实参拷贝到该位置,并将该拷贝值传递给该方法;

在change()方法内部,执行x = "cd"的时候,这里的x实际上是main方法的x变量的一个拷贝,一开始其存放的是“ab对象”的引用,执行完这段代码后,其值变成“cd”对象的引用,而main方法的x变量并没有改变,存放的仍然是“ab”对象的引用。

另一错误解释

这个问题的原因跟字符串的不变形没任何关系,即使将String替换成StringBuilder对象,结果仍然不变,关键点是变量存储的是对象的引用,而不是对象本身;

解决这个问题的方法

如果真的想改变这个对象的值,

首先这个对象是要可改变的,例如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");
}

 本文转自风一样的码农博客园博客,原文链接:http://www.cnblogs.com/chenpi/p/5494980.html,如需转载请自行联系原作者

相关文章
|
C++
C++ 用引用的方式向函数传递数组
C++ 用引用的方式向函数传递数组
160 0
C++ 用引用的方式向函数传递数组
|
9月前
|
JavaScript 前端开发 Java
字符串的引用方式
字符串的引用方式
185 0
|
9月前
|
C语言
字符串的引用
字符串的引用
99 0
|
C++
浅析C++的引用与const指针与各种传递方式
转自:https://www.jb51.net/article/120561.htm   首先我们知道 const int *p 与 int const *p 是一样的,即 *p 是常量; 而 int * const p 跟上面是不一样的,即 p 是常量; 我们知道引用只是一个别名,与变量共享存储空间,并且必须在定义的时候初始化,而且不能再成为别的变量的别名,这让我们想到什么呢,貌似跟  int * const p   的性质很像。
1227 0
|
安全 C++
向函数中传递指针和传递指针的引用的区别
如果是传递指针,那么会先复制该指针,在函数内部使用的是复制后的指针,这个指针与原来的指针指向相同的地址,如果在函数内部将复制后的指针指向了另外的新的对象,那么不会影响原有的指针;但 是对于传递指针应用,如果将传递进来的指针指向了新的对象,那么原始的指针也就指向了新的对象,这样就会造成内存泄漏,因为原...
2087 0
|
存储
集合作为函数参数传参时创建新集合对象的作用
易错点——List集合集合作为函数参数传参时创建新集合对象的作用
189 0
|
C语言 Android开发 C++
【C++】函数 指针类型参数 与 引用类型参数 对比 ( 修改外部变量需要传入的参数要求 | 参数作返回值 )
【C++】函数 指针类型参数 与 引用类型参数 对比 ( 修改外部变量需要传入的参数要求 | 参数作返回值 )
204 0
返回数组引用的4种函数写法
#include #include using namespace std; //传入的参数是数组的引用,返回值也是数组的引用 string (&fun(string (&s)[10]))[10] { return s; } //using str_arr...
878 0

热门文章

最新文章