你真的了解Java吗?
1.表达式谜题
三目运算符规则:
• 如果第二个和第三个操作数具有相同的类型,那么它就是条件表达式的类
型。换句话说,你可以通过绕过混合类型的计算来避免大麻烦。
• 如果一个操作数的类型是 T,T 表示 byte、short 或 char,而另一个操作数是一个 int 类型的常量表达式,它的值是可以用类型 T 表示的,那么条件表达式的类型就是 T。
• 否则,将对操作数类型运用二进制数字提升,而条件表达式的类型就是第
二个和第三个操作数被提升之后的类型。
public static void main(String[] args){
char x = 'X';
int i = 0;
System.out.println(true ? x : 0);
结果:X 第二条原则,返回一个char类型
System.out.println(false ? i : x);
结果:88 第三条原则,char和int被提升为int,返回一个int类型
}
下面的方法意图确定它那唯一的参数是否是一个奇数。这个方法能够正确运转吗?
public static boolean isOdd(int i){
return i % 2 == 1;
//它在四分之一的时间里返回的都是错误的答案。 对于对所有负奇数的判断都会失败,因为当 i 是一个负奇数时,i % 2 等于-1 而不是 1。
}
正确的写法:
public static boolean isOdd(int i){
return (i & 1) != 0;
}
并不是所有的小数都能够用二进制精确表示的,例如下面的代码就会出现问题, 在需要精确答案的地方,要避免使用 float 和 double;对于货币计算,要使用 int、long 或 BigDecimal。
public static void main(String args[]){
System.out.println(2.00 - 1.10);
}
计算时1.10默认会转成double来计算,但1.10这个数字不能被精确表示成为一个double,所以最终结果为一个近似值:0.8999999999999999
下面程序的结果并不是1000,问题在于常数 MICROS_PER_DAY 的计算“确实”溢出了。尽管计算的结果适合放入 long 中,并且其空间还有富余,但是这个结果并不适合放入 int 中。这个计算完全是以 int 运算来执行的,并且只有在运算完成之后,其结果才被提升到long,而此时已经太迟了:计算已经溢出了,它返回的是一个小了 200 倍的数值。
public static void main(String args[]){
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
//5
}
public static void main(String args[]){
final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
//1000
}
复合赋值操作符会悄悄地产生一个转型。如果计算结果的类型宽于变量的类型,那么所产生的转型就是一个危险的窄化转型。这样的转型可能会悄悄地丢弃掉精度或数量值。多重转型也会产生精度的损失
2.表达式谜题
操作符重载:
+ 操作符当且仅当它的操作数中至少有一个是 String 类型时,才会执行字符串连接操作;否则,它执行的就是加法。
public static void main(String[] args){
System.out.print("H"+"a");
结果为:Ha,此处的+ 表示字符串拼接。
System.out.print('H'+'a');
结果为:169,是通过我们熟知的拓宽原始类型转换将两个具有字符型数值的操作数('H'和'a')提升为 int 数值而实现的。从 char 到int 的拓宽原始类型转换是将 16 位的 char 数值零扩展到 32 位的 int。对于'H',char 数值是 72,而对于'a',char 数值是 97,因此表式'H'+'a'等价于 int
常量 72 + 97,或 169。
}
操作符优先级和比较问题:
任何两个 String类型的常量表达式,如果标明的是相同的字符序列,那么它们就用相同的对象引用来表示。如果用常量表达式来初始化 pig 和 dog,那么它们确实会指向相同的对象,但是 dog 并不是用常量表达式初始化的。
public static void main(String[] args){
String a = "abc";
String b = "abc";
System.out. println(a == b);//true
final String pig = "ABC:5";
final String dog = "abc:" + pig.length();
System.out. println(pig == dog);//false
System.out. println(pig.equals(dog));//false
System.out. println("Animals are equal: " + pig == dog);
结果是:false,因为 + 操作符,不论是用作加法还是字符串连接操作,它都比 == 操作符的优先级高
}
上一篇: 你真的了解Java继承吗?
下一篇: javase基础