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

关于JAVA的一道面试题

2012-01-10 07:34 429 查看
身边有些做java开发的朋友,找工作时常常被考到一道关于字符串的题目。题目倒是很基础,然而根据朋友们事后的描述,有理由认为有的面试官自己都没有完全搞清楚这个问题。此外,在csdn论坛中我也多次看到一些朋友在这个问题上的迷惑。索性把自己的理解写下来吧。
题目是一道简单的小程序,像下面这样:
view plain
public class test1 {
public static void main(string args[]) {
string s = new string("hello");
system.out.println(s);
foo(s);
system.out.println(s);
}
public static void foo(string s) {
s = new string("world");
}
}
问程序先后两次分别会输出什么。
第一个肯定输出“hello”。关键是第二个,个别基础不牢的朋友可能被考倒,但基础稍微扎实一点的就不会。第二个输出的也是“hello”。
到这里,万事大吉。面试官两眼放出喜悦的光芒,赞叹道:“嗯,不错不错。不会变的,对吧。因为string是immutable类型,immutable类型改不了的。”他说的“immutable”是指string类没有任何一个方法会改变对象的状态。
这可就有问题了。确实程序两次输出的都是“hello”,但原因却不是string的immutable特性。不信换一个“mutable”的试试,比如stringbuilder或stringbuffer。
view plain
public class test2 {
public static void main(string args[]) {
stringbuilder s = new stringbuilder("hello");
system.out.println(s);
foo(s);
system.out.println(s);
}
public static void foo(stringbuilder s) {
s = new stringbuilder("world");
}
}
这次呢?会先输出“hello”,然后输出“world”吗?不会,仍然是两次“hello”。
足以说明这个问题跟string的immutable特性没有一毛钱的关系。不管是immutable类型,还是一般的类型,用这种方式写出来的程序main方法中前后两个对象肯定是一样的。
真正的原因是:java语言的参数传递机制是“按值传递”(pass by value)。虽然java中除基本数值类型外,其它变量都是引用,但那是另一回事。变量的语义(“引用”还是“值”)跟函数传参的机制是两个正交的概念。
各种编程语言中,最常见的参数传递方式不外乎按值传递和按引用传递(pass by reference)两种。比如,c和java中函数参数都是按值传递的,c++和c#则同时支持按值传递和按引用传递。c和java的不同在于,c是值类型的按值传递,而java是引用类型的按值传递(基本的数值类型除外)。
按值传参最大的特点就是函数内部对“形参变量”本身的所做的修改外面的“实参变量”感知不到。
不过,对于stringbuilder来说我们至少有办法让它改变,比如像下面这样:
view plain
public class test3 {
public static void main(string args[]) {
stringbuilder s = new stringbuilder("hello");
system.out.println(s);
foo(s);
system.out.println(s);
}
public static void foo(stringbuilder s) {
s.replace(0, s.length(), "world");
}
}
体会到不同了吗?虽然参数变量本身是按值传递的,但这次我们对变量本身不感兴趣,我们不改变变量本身,而是通过它直接修改它所引用的那个对象。这一次,java语言“几乎一切皆引用”的特点起作用了,程序第一次输出“hello”,第二次输出“world”。熟悉c的朋友可能马上联想到:这很像c语言中通过指针来修改它指向的内容。
而先前那个string版本的程序,我们无法写出一个相应的可变版本。为什么呢?……“嗯,不错不错。因为string是immutable类型……”,这次真对了。——可见先前说“没有一毛钱的关系”也不尽然。因为immutable,导致我们无法针对string写出一个像test3那样的“可变”程序,如此说来,“二分钱的关系”应该是有的。
“pass reference by value”就像c++ 11中的“an lvalue with rvalue reference type”一样,乍一看挺绕的,但只要仔细想清楚,让正交的东西“尘归尘 土归土”,就可以加深对语言的理解。
顺便问一句,您知道java.lang.stringbuilder和java.lang.stringbuffer的区别吗?好多面试官都喜欢“顺便”问问这个,而且答对了不会加分,答不上来却会扣分,至少扣印象分。:(

======================================================

在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定
这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: