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