您的位置:首页 > 职场人生

String方法调用面试题引发的思考

2016-12-23 16:00 197 查看
public class TestString {
public void fun(String str) {
str = " 张三 ";
}
public static void main(String args[]) {
TestString t = new TestString();
String str = " 李四 ";
t.fun(str);
System.out.println(str);
}
}


以上代码的最终结果是‘李四’那么原因是什么呢?

这个一个很经典的java面试题,很多人面试的时候都会遇到。

本文将基于这道面试题展开思考,请随之作者的思路一起展开思想风暴吧

第一个思考方向

1、刚看到这道题的是想到的是形参和实参的问题,很直白的来说函数fun(String str)中的str是一个形参,它规定了这个函数调用时传入的实参必须是String。而main函数中定义的变量str是传入函数时的实参。

2、接下来想到了作用域,形参的作用域就是在那个函数内,函数执行完毕,当前变量也就会随之销毁。而main函数中的参数的作用域是整个main函数,所以没有变。

第二个思考方向

1、 String是一个特殊的对象,在传递参数之前,给str赋值的操作会在jvm常量池PSPermGen中分配一个地址存储‘李四’,并在java的栈中创建出来一块地方对应存储该str的地址空间,然后在传递函数调用的过程中复制了一份栈中的地址空间,并把复制的这一份地址空间赋给函数中的参数str。这个时候两个str存储了相同的值。都是‘李四’这个字符串的地址空间。



2、问题继续往下思考,在java函数中的参数值传递到底是值传递函数引用传递。

这部分我也在努力的寻找有关文档来证实此事。以下是我了解到的观点

1、java只有值传递

该观点阐述的是每次传递的时候都会在栈中复制一份地址并传递到方法中。

2、值传递和引用传递并存

该观点阐述的是,当是基本类型以及其包装类如int,Integer的时候是值传递,当是对象的时候是引用传递。

3、以下是我的观点

其实按值还是按引用的区别在于“是否在传递的时候进行对象的内存拷贝”,java中基本类型是由于在JVM中存储区域不同于普通对象所以传递前会拷贝,传递的是拷贝后的值,但是对象在传递的时候不拷贝,直接传“引用值”,指向同一片对象堆内存区域

综述来讲

String 因为是特殊的对象,它的传递应该是地址的传递应该是当前这个str的栈中的地址空间中的内容,因为对象存在,所以对象不会重新创建,但是传入的str和接受的str在栈中应该是不同的地址,并且都指向‘李四’。在函数中重新赋值的本质是该变了函数中的str在栈中的值,也就是所谓的断开之前的引用,将新的引用赋值给当前str,这和c的指针的切换是一样的。但是这一切的操作并没有影响到main中的那个str在栈中的信息,所以该str没有发生任何的变更。

注: 本文的解释只属于个人观点,欢迎各位读者交流指教
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  面试题 string java