题目1.指出下列程序运行的结果 ()
public class Example { String str = new String("good"); char[] ch = { 'a', 'b', 'c' }; public static void main(String args[]) { Example ex = new Example(); ex.change(ex.str, ex.ch); System.out.print(ex.str + " and "); System.out.print(ex.ch); } public void change(String str, char ch[]) { str = "test ok"; ch[0] = 'g'; } }
A、 good and abc
B、 good and gbc
C、 test ok and abc
D、 test ok and gbc
答案:B
解析:我也像很多人一样,上了就像选D。但敲到eclipse中试了下,的确输出B。很神奇!百度了一下,这就是所谓的java只有值传递,没有引用传递。
就是说传入的实参是对象str的值,同时为复制这个值并分配一个新的引用地址,而并不是原本的str的引用。所以修改新的值与原始的并没有关系。
这里有个哥们讲的比较精髓:
http://guhanjie.iteye.com/blog/1683637
但为什么char数组的首位元素的值却被修改了呢?这个让我不仅想到Python的内存处理:
对于简单的Python对象,例如数值、字符串,元组(tuple不允许被更改)采用的是复制的方式(深拷贝),也就是说当将另一个变量B赋值给变量A时,虽然A和B的内存空间仍然相同,但当A的值发生变化时,会重新给A分配空间,A和B的地址变得不再相同
而对于像字典(dict),列表(List)等,改变一个就会引起另一个的改变,也称之为浅拷贝
Java中的数组,也是可以改变元素数量的,就像Python中的字典和列表。new char[]时,编译器要做的,只是分配一块内存给它,保存指向数组实体的地址。
所以当数组作为实参传入函数的时候,肯定传入的是数组的引用地址,引用地址指向数组对象真实的值,所以该数组元素被修改了。
同时,联想到今天面试遇到的一个问题,做下记录说明:
题目2.Java中字符串连接有哪些方法,其中+连接时内存是怎么分配的?
首先,常用的字符串连接就是+和append,网上还有提到:strFormat2(s1, s2);
其实+是重载了StringBuilder的append()方法,append()是StringBuilder对象中的一个方法。
strFormat源代码也是通过StringBuilder实现的。
所以StringBuilder是其他两种方式的基础实现,所以还是StringBuilder比较占优势。
而且Java中String对象是不可变的,String类中每一个修改String的方法,其实都是创建了一个全新的String对象,当然append()也不例外。
网上有一个帖子详细比较了这三个方法的内存消耗:
http://www.2cto.com/kf/201409/333054.html
只有append()的确是最直接也是速度最快的!