下面的坑有些来自别人的技术博客,有些事以前自己遇到的坑,持续补充。。。
坑1:三目运算符
首先我们看一下这道题:char x = 'x';System.out.println(true?120:x);
我们的第一反应结果不就是120吗,但是我们实际运行一下,结果是x。是不是有种诧异的感觉,是不是觉得被带沟里去了?不知道大家感觉如何,反正我看到这个结果都惊呆了。对于三目运算符中的两个结果,如果一个是常量,一个是类型T的变量,则常量会被转型为类型T,这个据说是java编程规范中规定的,反正我是没看过,就此记住一条。所以常量120被转型为char,对应于x(小写)。
扩展1:
- int a=5;
- System.out.println("a="+((a<5)?10.9:9));
输出:9.0。因为三目运算符中有一个10.9,java会根据运算符的精度类型进行自动类型转换。因此9会变为9.0
扩展2:
- char x='x';
- int i=10;
- System.out.println(false?i:x);
- System.out.println(false?100:x);
而这段代码的输出是
120
x
对于第一行输出,与上个例子相同,x被提升了类型,变为int
而对于第二行,由于100是一个常量。若三目运算符中的两个表达式有一个是常量表达式,另一个是类型T的表达式,且常量表达式可以被T表示,则输出结果是T类型。因此输出是字符x
坑2:{}真是可有可无吗?
先看题目:
for(int i=0;i<10;i++)
Integer k=new Integer(i);
System.out.println("hello world");
请问结果如何?
我第一反应没有认真看,然后觉得直接输出hello world.但是实际上呢,根本编译不过去。
平时我的感觉就是,如果for中只有一行语句,那就不加{}了,免得看得那么多,所以印象中,对于一行的循环体,觉得{}是可有可无的。然而,事实是,java中的局部变量应该是在一个代码块中,也可以理解为是在{}中。for可以不加{},但是只限于执行语句,不包括局部变量声明的语句,而在本例中,就出现了局部变量重复定义的错误,改正的办法是加上{}。可见,{}还真不是可有可无的,怪不得刚开始学编程时候老是说用不用带带着呢,还是有道理的呀
坑3:除0
- System.out.println(1.0d / 0);
- System.out.println(0.0d / 0);
- System.out.println(1 / 0);
- System.out.println(0 / 0);
输出:
Infinity
NaN
java.lang.ArithmeticException: / by zero
at test.ww.Test.main(Test.java:27)
java.lang.ArithmeticException: / by zero
at test.ww.Test.main(Test.java:32)
原因:
因为 IEEE 754 有规定无穷大是怎么表示的,因此被除数不为 0,除数是 0 的话计算结果是正无穷或者是负无穷,如果被除数和除数都是 0 的话,那么计算结果是 NaN
整数不在是 IEEE 754 规定的,也没有无穷大的表示,因此只能抛出异常了
-
int[] arr = new int[]{1,2,3}; - System.out.println(Arrays.asList(arr).contains(1));
输出什么?
大多数人的回答肯定是true,显而易见么。。但它输出的却是false,为什么,哪里出错了么?
分解一下表达式,先调用Arrays.asList(arr),通过遍历或者debug你会发现里面的元素个数为1,这又是什么原因呢,查看一下API或者源代码,发现它声明为List<T> Arrays.asList(T... args),难道是可变长参数有问题?
做一个测试:
- public static void main(String[] args) {
- int[] arr = new int[]{1, 2, 3 };
- test1(arr);
- }
- private static void test1(Object... values) {
- System.out.println(values.length);
- }
输出
1
把int数组改为Integer数组后,输出
3
看来是基本类型的数组被当作了一个对象,而对象类型的数组的每个元素才能分别作为可变长参数方法的参数。