文章目录

  1. 1. 奇数性
    1. 1.1. 分析
    2. 1.2. 建议
    3. 1.3. 解决
  2. 2. 长整除
    1. 2.1. 分析
    2. 2.2. 建议
    3. 2.3. 解决
  3. 3. 找零时刻
    1. 3.1. 分析
    2. 3.2. 建议
    3. 3.3. 解决
  4. 4. 初级问题
    1. 4.1. 分析
    2. 4.2. 建议
    3. 4.3. 解决
  5. 5. 多重转型
    1. 5.1. 分析
  6. 6. Dos Equis
    1. 6.1. 分析
    2. 6.2. 建议


微信公众号

摘自《Java解惑》。这些问题都很经典,可以细细品味。
今天讲解的问题如下,奇数性问题、长整除问题、找零时刻、多重转型、Dos Equis。

奇数性

public class Odd {  
    public static void main(String[] args) {  
        System.out.println("1是奇数吗?"+isOdd(1));  
        System.out.println("2是奇数吗?"+isOdd(2));  
        System.out.println("-1是奇数吗?"+isOdd(-1));  
    }  
    public static boolean isOdd(int i){  
        return i % 2 == 1;  
    }  
}

分析

这是Java对取余操作符(%)的定义所产生的。isOdd方法对于对所有负奇数的判断都会失败。在任何负整数上调用该方法都回返回false,不管该整数是偶数还是奇数。

建议

无论你何时使用到了取余操作符,都要考虑到操作数和结果的符号。

解决

方案一:

public static boolean isOdd(int i){  
  return i % 2 != 0;  
} 
方案二:
public static boolean isOdd2(int i){  
  return (i & 1) != 0;  
}  

长整除

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

分析

当两个int数值相乘时,将得到另一个int数值。因此最后的结果是int数值,从而导致溢出。

建议

当在操作很大的数字时,千万要提防溢出。

解决

方案:强制表达式中的所有后续计算都用long运算来完成

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

找零时刻

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

分析

并不是所有的小数都可以用二进制浮点数精确表示。

建议

在需要精确答案的地方,要避免使用float和double。对于货币计算,要使用int、long、BigDecimal。一定要用BigDecimal(String)构造器,而千万不要用BigDecimal(double)。后一个构造器将用它的参数的精确值来创建一个实例。

解决

方案一:JDK5.0或更新版本,可以使用printf方法

public class Change2 {  
  public static void main(String[] args) {  
      System.out.printf("%.2f",2.0-1.1);  
  }  
} 
方案二:使用BigDecimal类
public class Change3 {  
  public static void main(String[] args) {  
      BigDecimal bigNum1 = newBigDecimal("2.0");  
      BigDecimal bigNum2 = newBigDecimal("1.1");  
      System.out.println(bigNum1.subtract(bigNum2));  
  }  
}  

初级问题

public class Elementary {  
  public static void main(String[] args) {  
      System.out.println(12345+5432l);  
  }  
}

分析

“5432l”中的“l”是小写的“L”。

建议

在long类型常量中,一定要用大写的L,千万不要使用小写的l。类似地,要避免使用单个l字母作为变量名。

解决

方案:

public class Elementary {  
  public static void main(String[] args) {  
      System.out.println(12345+5432L);  
  }  
}  

多重转型

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

分析

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

Dos Equis

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

分析

如果第2个和第3个操作数具有相同的类型,那么它就是条件表达式的类型。如果一个操作数的类型是T,T表示byte、short、char,而另一个操作数是一个int类型的常量表达式,它的值可以用类型T表示。否则,将对操作数类型进行二进制数字提升,而条件表达式的类型就是第2个和第3个操作数被提升之后的类型。

建议

最好在表达式中使用类型相同的第2个和第3个操作数。

文章目录

  1. 1. 奇数性
    1. 1.1. 分析
    2. 1.2. 建议
    3. 1.3. 解决
  2. 2. 长整除
    1. 2.1. 分析
    2. 2.2. 建议
    3. 2.3. 解决
  3. 3. 找零时刻
    1. 3.1. 分析
    2. 3.2. 建议
    3. 3.3. 解决
  4. 4. 初级问题
    1. 4.1. 分析
    2. 4.2. 建议
    3. 4.3. 解决
  5. 5. 多重转型
    1. 5.1. 分析
  6. 6. Dos Equis
    1. 6.1. 分析
    2. 6.2. 建议