JAVA编程一些必须注意小心的陷阱

来源:互联网 发布:扮猪吃老虎 网文 知乎 编辑:程序博客网 时间:2024/04/28 17:46

《Java Puzzlers》(中文译名《Java解惑》),一句话,好书,有趣,短小精悍的行文,主要是介绍JAVA编程一些必须注意小心的陷阱(trap)。第一章:表达式之谜,俺只记下一些有趣的例子,很多关于16进制的趣事不多说,反正尽量不要使用16进制。

1。对于精确答案的地方,要尽量避免使用float和double;对于货币计算,要使用int,long和BigDecimal,并且使用 BigDecimal时千万不要使用BigDecimal(double)构造函数。,因为此构造函数将用它的参数的精确值来构建一个实例。

如:

public class Change {
    public static void main(String args[]) {
        System.out.println(2.00 - 1.10);
    }
}

我们希望打印0.9,可是打印的却是0.899999999999999,货币计算最好还是采用BigDecimal:

public class Change {
    public static void main(String args[]) {
        System.out.println(new BigDecimal("2.00").subtract(new BigDecimal(" 1.10")));
    }
}

2。长整除:当你操作很大的数字时,千万要提防溢出:

public class LongDivision {
    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);
    }
}

你猜测打印什么?1000?不,打印的是5。因为第一个MICRO_PER_DAY的计算完全是以int类型来进行,虽然计算结果是可以放进long的,但在放进之前已经溢出了。改为如此,显示地转为long:

  final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;

3。基本类型的转型操作:

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

输出可能让你很吃惊:65535。其实问题的关键是JAVA不显式区分有符号数与无符号数。在执行char的转换时,一条规则必须记住,如果最初的 数值类型是有符号的,那么就执行符号扩展;如果它是char,那么不管它转化成什么类型,都执行零扩展。因为byte是有符号的类型,所以在-1转化为 char时,发生符号扩展,作为结果的char的16位都被置位了,所以结果为2的16次方再加上-1。

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);
    }
}
你可能以为应该打印XX,可并非如此,结果是X88,why?这与条件操作符的规则有关:

A。如果第2和第三操作数的类型相同,那么它也是条件操作符结果的类型

B。如果一个操作数的类型是T(T包括byte,short,char)时,另一个操作数的类型是int的常量(注意是常量)表达式,并且可以用T类型表示,那么条件表达式的结果为T

C。否则,将对表达式的操作数进行二进制提升,结果即为提升后的类型。

因此第2个输出语句把X转为int型即88。很复杂对不?呵呵,所以还是最好使用相同类型吧!!

5。另一个需要注意的是复合操作符,如+=,*=,/+等,复合赋值表达式将自动把所执行计算的结果转化为其左侧变量的类型。所以要防止窄化转型。

原创粉丝点击