尽信书,则不如无书。—–孟子
《Java程序员面试宝典》是我接触的第一本讲解面试相关的书籍在看到这本书之前我就经常逛csdn的bbs,已经接触面试之类的知识。不过这本书还是带给我好运,在去年的校招中学会一些技巧,乃至获得几家offer的机会。
老早就听别人说这本书有很多诟病,比如:错漏百出,概念不清,代码混乱,排版错误,不遵循Java编码风格等 ,还有,作为一本《Java面试书籍》,里面有很多c/c++方面的东西,这可能与作者写《程序员面试宝典》有关,因为这本书是另一本的姊妹篇。去年的这个时候我在学校图书馆借阅到了这本书,感觉真的是一本宝典。当时在网上的大神它的批评,我内心觉得太过苛刻,是无法接受大神对这本书批判的。今年的这个时间点又到我求职面试的季节,听说这本书出到了第4版本了,想必应该修改了不少地方了,将书中不足之处做了修改。于是在京东买了最新一版的第4版回来,心里满满的期待感。看到前言提到“更新了部分程序面试题目,内容主要取材于2013年至2015年多家大公司的面试题”,心想肯定是捡到了干货。
下面是我的读书笔记,不是一味的批判本书,而是在我现有的技术基础上读到的感悟,取其精华,去其糟粕。
前四章的主要内容是交代求职过程,比如如何写简历,如何参加校招等,遵循它的原则,我写了自认为比较满意的简历。我觉得如果作者加上社招的经验就更好了,如今互联网这么火,加上Java是互联网的第1开发语言,作者应该谈一谈社招与互联网的关系。谈一谈智联,51job,拉钩,内推等网站,哪些适合什么人投简历等等。正如像博主这种只有半年的工作经验,参加过校招,但是没有社招经验的人,很是需要这方面的指导。当然了,不能一味的书上写有的才去做,不写就不知道怎么做,这不变成一书呆子了么?
1.i++问题:
下面程序输出结果是多少?
public class Test1 {
static {
int x= 5;
}
static int x, y;
public static void main(String[] args) {
x--;
myMethod();
System.out.println(x + y++ + x);
}
public static void myMethod() {
y = x++ + ++x;
}
}
答案:2
这里需要注意的是第3行的int x = 5;因为它是局部变量,x=5不影响后面的值。
下列程序的输出结果是:
public class Test1 {
public static void main(String[] args) {
int j = 0;
for(int i = 0; i < 100; i++) {
j = j++;
}
System.out.println(j);
}
}
答案:0
因为Java用了中间缓存变量的机制,所以,循环体里面的j=j++可换成如下写法:
temp = j;
j = j + 1;
j = temp;
2.类型转换
下列的语法正确的是?
A. Short myshort = 99S;
C. float z = 1.0;
B. int t = "abc".length();
D. char c = 17c;
参考答案是:D.
但是一切都是编译器说了算了。编译器告诉我:B才是正确答案。A和D这种后缀几乎不存在,1.0默认是double类型,如果非要说1.0是float型的话,一般都是这样写的:1.0f。还有length()和length的区别是:length用于数组的长度,length()用于字符串长度。
作者在讲解自动了类型转换的时候,举例子有范了错误。原文:
低级变量可以直接转换为高级变量,这叫做自动类型转换。例如,下面的语句可以在Java中直接通过:
byte b;int i=b;long l=b;float f=b;double d=b;
作者的讲解时没有错的,错就错在这个例子上面,这里的变量b未初始化就直接使用了,在Java会报错:The local variable b may not have been initialized.所以说上面的语句在Java中直接通不过。
包装类过度类型转换
原文说:Java的包装类就是可以直接将简单类型的变量表示为一个类。Java共有六个包装类,分别是Boolean、Character、Integer、Long、Float和Double.
Java的数据类型不是有8中么?还是byte和short呢?他们对应的包装类是Byte,Short。
作者的例1:
当希望吧float转换为double型时:
float f1 = 100.00f;
Float F1 = new float(f1);
Double d1 = F1.doubleValue();
代码第二行的Float应该大写,这可能是印刷有问题,不过这还真的应正了其他网友的那句话:排版不严谨。还有变量的命名也不严谨吧,变量名都是小写字母开头,这都是一种习惯而已。
3.main方法的写法问题:
下面那个main函数的声明是不合法的?
A. public static void main()
B. public static void main(String[] String)
C. public static void main(String[] exp) throws FileNotFoundException
D. static void main(String[] args)
参考答案:D。但是,A也是不合法的,对于每一个java Coder来说,hello world应该都是第一个Java程序,开始写了这么久的程序,可能没有关注过main函数到底是怎么写的,更不关注这个返回值的意义,是不是像c/c++那样返回给系统的。我的理解main方法的写法有点类似于方法的重载,返回值和参数个数类型必须一致。
原书讲解错误之处:
A,B选项是合法的。C选项抛出一个文件异常,但也是合法的,并可以通过,至于选项D,因为main方法必须是public,默认的代表是protect,所以是不合法的。
这个解释导致读者会误认为:一个方法默认的属性是protect范围的,然而Java有四个属性范围,他们分别如图:
这张图一目了然,如果你在方法或者变量前面没有加属性的范围,那么默认是default级别的,不是protected。作者以为不写就是protected,而default的范围和protected范围是不一样的。还有,作者把protected写成:protect,我相信这可能是粗心大意造成的,不过书中有太多类似的地方。如果说作者的对Java的属性范围不清楚是功夫不到家,那么把关键词写错,那就是在忽悠读者了。
4.运算符
以下代码输出结果是:
public class Test {
public static void main(String[] args) {
char x = 'x';
int i = 10;
Sysout.out.println(false?i:x);
Sysout.out.println(false?10:x);
}
答案:120 x。很怪异的结果,编译器确实结果也是这样的,反正解析还是不能让我信服。
5.&运算符
&运算符以前我只知道是按位与,后来才知道,这哥们除了能够按位与之外,还有逻辑与的功能,不过这哥们与&&的区别是,&&是短路与,如果前面的条件为假,后面不再执行。而&不是短路与,无论前面的条件是真是假,照样执行后面的语句。如以下代码:
int m = 5;
int n = 5;
if( (m != 5) && ( (n++ == 5) ) {
Sysout.out.println("进来过");
}
Sysout.out.println(n);
(m != 5)是false,后面的那个n++不再执行,因此输出的n是5。
int m = 5;
int n = 5;
if( (m != 5) && ( (n++ == 6) ) {
Sysout.out.println("进来过");
}
Sysout.out.println(n);
比较一下有什么区别吧。
5.final,finally,finalize的区别。
这道题貌似去年做准备的看过,不过去年的面试中,从来没有遇见过有面试官问到这道题。
不要迷信书,尽信书不如无书。眼看千遍不如手过一遍,编译器是最终的解释权。但是目前我的技术水平,还是需要静下心读书。那么问题又来了,到底要不要看书,答案是肯定的。那就要多看书,看好书。