Java中容易忽略的问题(表达式篇,根据java解惑归纳)

来源:互联网 发布:华为交换机端口绑定 编辑:程序博客网 时间:2024/05/17 06:28

1.在需要精确答案的地方,要避免使用float和double;对于货币计算,要使用int,long或BigDecimal。这是因为并不是所有的小数都可以用二进制浮点数精确表示。

 

2.长整除问题,参看以下代码:

public class LongDivision {public static void main(String[] args) {final long MICRO_PER_DAY =24*60*60*1000*1000;final long MILLIS_PER_DAY=24*60*60*1000;System.out.println(MICRO_PER_DAY/MILLIS_PER_DAY);}}


你可能会毫不犹豫的回答是1000。但是结果确是5.这是为什么呢?

虽然计算的结果适合放入long中,但是却不适合放入int中。在java中,它是以int运算来执行的,这是因为所有乘在一起的因子都是int数值。当两个int数值相乘时得到的还是int值。这是java的一种语言特性,其含义是指存储结果的变量类型会影响计算所使用的类型。

对于修改此程序,则只需要将其中的因子变为long类型。

通过这个程序我们可以看到:当你在操作很大的数字时,千万要提防溢出!

 

3.多重转换问题

参照以下代码:

public class Multicast {public static void main(String[] args){System.out.println((int)(char)(byte)-1);}}


无论你怎样分析这个程序,都会感到迷茫。它以数值-1开始,然后从int转型为byte,之后转型为char,最后转换回int。第一个转型数值从32位窄化为8位,第二个转型将数值从8位拓宽为16,最后一个转型又将数值从16位拓宽为32位。这个数值将回到起点吗?运行后发现答案不是,而是65535。这是为什么呢?

该程序的行为紧密依赖于转型的符号扩展行为。但是只有遵循一定的规则就可以解决这个问题:

如果最初的数值类型是有符号的,那么就执行符号扩展;如果它是char,那么不管它将要转换成什么类型,都执行零扩展。

因为byte是有符号的类型,所以将byte转换成char时,发生符号扩展,等于2的16次方减1,即65535。从char到int为零扩展,也就是65535.

4.条件操作符

请看一下代码:

public class DosEquis {public static void main(String[] args) {char x='X';int i=0;System.out.print(true ? x:0);System.out.print(false? i:x);}}

这个程序由2个变量声明和两个print语句构成。第一个print语句计算条件表达式(true?x:0)并打印结果,这个结果是char类型变量x的值‘x’而第二个print语句计算表达式(false?i:x)并打印结果,这个结果依旧是x的‘x’。然而运行后为x88。

首先,必须明白一点:混合类型的计算会引起混乱,而这一点在条件表达式中比在其他任何地方都表现得更明显!确定条件表达式结果类型的规则过于冗长和复杂,很难完全记住它们,但是其核心为一下三点:

(1)如果第二个和第三个操作数具有相同的类型,那么它就是条件表达式的类型。换句话说,可以通过混合类型的计算来避免大麻烦。

(2)如果一个操作数的类型是T,T表示byte,short或char,而另一个操作数是一个int类型的常量表达式,它的值可以用类型T表示,那么条件表达式的类型就是T。

(3)否则,将对操作数类型进行二进制数字提升,而条件表达式的类型就是第二个和第三个操作数被提升之后的类型。

在程序的两个条件表达式中,一个操作数的类型是char,另一个的类型是int。在两个表达式中,int操作数都是0,它可以表示成一个char。然而,只有第一个表达式中的int操作数是常量,而第二个表达式中的int操作数是变量。因此第二点被应用到第一个表达式上,他返回的类型为char,而第三点被应用到第二个表达式上,其返回的类型是对int和char进行二进制数字提升之后的类型,即int。

总之,通常最好是在条件表达式中使用类型相同的第二和第三操作数!

5.请不要将复合赋值操作符用于byte,short或char类型的变量。