做为一门面向对象的编程语言,Java凭借其简单易用、功能强大的特色受到了广大编程爱好者的青睐,伴随着开源社区的推波助澜,Java语言更是席卷全球,势不可挡,在世界各地都有Java技术的从业者,它也常年高居编程语言排行榜的首位,足以代表Java的强悍与王者之风。
然而,即使是如此强大的编程语言,也有不少“坑爹”的功能,稍不注意,咱们就会掉入坑里,轻则遭到同事的嘲笑和鄙视,重则形成悲惨后果而不得不跑路。
固然,坑爹这个词加上了双引号,由于大部分时候,都是因为咱们不够熟练、违反咱们的常识才形成了使人不愉快的后果。
今天咱们就来梳理一下Java中最“坑爹”、最违反常识的功能点,以排行榜的方式发布,以飨读者。说明一下,本文中的代码基于JDK8来编译实现。程序员
switch必须加上break才结束面试
对于多重分支选择,一系列的if-else-if语句会让代码的可读性变差,建议使用switch语句来代替,然而switch case中的分支判断,必须加上break语句才会停止其它case的执行,好比:编程
int count = 1;
switch(count){
case 1:
System.out.println("one");
case 2:
System.out.println("two");
case 3:
System.out.println("three");
}数组
上面的代码会输出:
one
two
three
然而,这并非咱们想要的,或者说违反了咱们的常识。知足了某种条件,固然就只须要执行这种条件下的逻辑便可,其余的case应该不予理会、直接跳过,象上面这段代码,只须要输出one就好了。固然,在每一个case结尾处加上break就能够达到咱们指望的效果。缓存
这个功能点稍显“坑爹”,也是初学者常犯的错误,因此它也光荣上榜,排名第10位。
逻辑运算符的“短路”现象编程语言
使用逻辑运算符时,咱们会遇到“短路”的现象:一旦可以肯定整个表达式的值,就不会计算余下的部分了,固然,这个功能点实际上是很是有用的,但对于初学者来讲,可能会感受比较惊讶,使用不当就会产生“坑爹”后果。好比下面的代码:ide
int num = 1;
System.out.println(false && ((num++)==1));
System.out.println(num);设计
就会输出false和1,由于逻辑与&&的前半部分为false,无论后半部分为true仍是false,整个表达式都会返回false,因此就不会再计算后面的部分了,若是把false改为true,那么后半部分就会获得执行,num也就变成2了。
它在“坑爹”榜单中位列第9位。
数组下标从零开始code
Java程序员都清楚,数组的下标是从零开始的,好比,咱们要遍历一个数组,能够采用以下的方式:对象
int[] arr = new int[]{1,3,5,7,9};
for(int i=0;i<arr.length;i++){
System.out.println("the element is:"+arr[i]);
}
这跟咱们平常生活中的经验是相违背的,正常状况都是从第1个元素开始计数的,特别是对于初学者来讲有点难以接受,会以为很惊讶。即便对于经验丰富的程序员来讲,有些地方也须要格外注意,好比:
String str = "hello world";
System.out.println(str.charAt(1));
咱们知道,charAt的做用是获取字符串中某个位置的字符,然而,上面的代码并非输出第一个字符h,而是e,由于数组是从零开始计数的,这个也是比较“坑爹”啊。固然,设计者这么作的缘由是考虑到了内存偏移量的因素。
每次在编写这样的代码时,都须要作这样的1到0的映射和转换(熟练了就是下意识的转换),确实也有点“坑爹”,因此它也不能幸免,排在第8位。
ArrayList遍历删除时报错
Talk is cheap,先上代码:
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("bc");
list.add("bc");
list.add("abcd");
list.add("abcdef");
//报错
int length = list.size();
for(int i = 0;i < length;i++){
if(list.get(i).equals("bc")){
list.remove(i);
}
}
}
想从ArrayList中删除某个元素,因而,咱们就写了上面的代码,可是它却抛出了IndexOutOfBoundsException异常,缘由是ArrayList在删除元素后会从新计算数量,把list.size放在for循环中便可:
for(int i=0;i<list.size();i++){
if(list.get(i).equals("bc")){
list.remove(i);
}
}
固然,这种方法也存在问题,建议使用迭代器的方式来删除元素。
对于不太熟练的程序员来讲,有时候就会掉入这样的陷阱之中。这是排名第7的状况。
字符转成数字的坑
有时候,咱们想把字符直接经过类型转换变成整数,好比像下面这样:
char symbol = '8';
System.out.println((int) symbol);
咱们想要的结果是8,然而,上面的代码却输出了56,略显“坑爹”,具体缘由参考ASCII的知识。
while循环体的“障眼法”
对于while循环语句,若是你没有加上大括号,即便后面的语句挨在一块儿,也只会执行第一条statement,好比:
int i = 0;
while(i++<3)
System.out.print("A");
System.out.print("B");
上面的代码会输出:
AAAB
而不是3个A、3个B,更“坑爹”的是,若是两条语句放在一行上,迷惑性会更大:
int i = 0;
while(i++<3)
System.out.print("A");System.out.print("B");
上面这种写法一样是输出AAAB。因此,象这样的状况,哪怕只有一条语句,也建议加上大括号,完美避坑。
Integer类有缓存
这个功能点也是面试的高频热点之一,稍不注意,也有可能被带入沟里,咱们看看下面这段代码:
public static void main(String[] args){
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a==b);
System.out.println(c==d);
}
上面的代码居然输出:
true
false
这确实太出乎意料了,一样的代码,只是数值不一样(并且差异不太大的样子),就产生了不同的输出,这也太离谱了。原来,Integer中有一个静态内部类IntegerCache,在类加载的时候,它会把[-128, 127]之间的值缓存起来,而Integer a = 100这样的赋值方式,会首先调用Integer类中的静态valueOf方法,这个方法会尝试从缓存里取值,若是在这个范围以内就不用从新new一个对象了:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}此功能入选“坑爹”排行榜的第4名。
空方法体致使死循环
若是循环的方法体为空,则会致使死循环,好比,下面的代码打印出数字1,2,3:
int i = 1;
while(i<4){
System.out.println(i++);
}
若是你在敲键盘的时候,不当心在while结尾处加了一个分号(若是方法体没有加大括号,更容易产生这种状况):
int i = 1;
while(i<4);{
System.out.println(i++);
}
你猜怎么着,上面的代码能够正常编译并运行,然而,它却陷入了死循环......是否是很是“坑爹”?for循环也存在相似的状况。
它高居排行榜的第3位。
神奇的=+
咱们知道,对于相似a=a+b这样的赋值语句,有一种简写方式:a +=b,然而,若是你不当心写成了a =+ b,结果又会是什么呢?咱们看看下面的代码:
int i = 100;
i =+ 2; //注意,加号在后面
System.out.println(i);
上面的代码既不会输出102,也不会报错,而是输出2,这的确出乎意料,彻底不是咱们指望的结果,太神奇了,很是的“坑爹”。
因此,它排名第2,稳居榜眼的位置。
Java注释可以识别Unicode
先看看代码:
public static void main(String[] args){
// \u000d System.out.println("Hello World!");
}
乍一看,代码都被注释掉了,固然不会输出任何东西,然而,它仍是输出每一个程序员都倍感亲切的Hello World,这是由于,unicode解码发生在代码编译以前,编译器将\u样式的代码进行文本转义,即便是注释也是这样,而后\u000a被转换成\n换行符,因此println代码得以正常执行。
这样的功能着实“坑爹”,极其违反常识,它必需要上榜,必需要荣登状元的位置。
以上就是编者总结的Java语言中十大“坑爹”的功能点,你是否定同这样的排名?你以为有哪些功能更应该入选此榜单?欢迎后台留言讨论!