MyException - 我的异常网
当前位置:我的异常网» 编程 » Java圈套(一)

Java圈套(一)

www.myexceptions.net  网友分享于:2013-04-10  浏览:2次
Java陷阱(一)
前言:摘自《Java解惑》。这些问题都很经典,可以细细品味。今天先整理一些之后陆续上传,分享分享,大家共勉。

问题:奇数

代码:

public class Odd {
      /**
       * 奇数性
       * @authorLiangGzone
       */
	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){
  returni % 2 != 0;
}

方案二:

public static boolean isOdd2(inti){
  return(i & 1) != 0;
}

问题:长整除

代码:

/**
 *长整除
 * @authorLiangGzone
 */
public class LongDivision {
  publicstatic void main(String[] args) {
  finallong MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
  finallong MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
  System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
  }
}

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

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

解决:

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

public class LongDivision2 {
  publicstatic void main(String[] args) {
  finallong MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
  finallong MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
  System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
  }
}


问题:找零时刻

代码:

/**
 *找零时刻
 * @authorLiangGzone
 */
public class Change {
  publicstatic void main(String[] args) {
  System.out.println(2.0-1.1);
  }
}

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

建议:在需要精确答案的地方,要避免使用floatdouble。对于货币计算,要使用intlongBigDecimal。一定要用BigDecimalString)构造器,而千万不要用BigDecimaldouble)。后一个构造器将用它的参数的精确值来创建一个实例。

解决:

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

public class Change2 {
  publicstatic void main(String[] args) {
  System.out.printf("%.2f",2.0-1.1);
  }
}
方案二:使用BigDecimal

public class Change3 {
  publicstatic void main(String[] args) {
  BigDecimalbigNum1 = newBigDecimal("2.0");
  BigDecimalbigNum2 = newBigDecimal("1.1");
  System.out.println(bigNum1.subtract(bigNum2));
  }
}

问题:初级问题

代码:

/**
 * 初级问题
 * @authorLiangGzone
 */
public class Elementary {
  publicstatic void main(String[] args) {
  System.out.println(12345+5432l);
  }
}

分析:5432l”中的“l”是小写的“L”。

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

解决:

方案:

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

问题:多重转型

代码:

/**
 *多重转型
 * @authorLiangGzone
 */
public class Multicast {
  publicstatic void main(String[] args) {
  System.out.println((int)(char)(byte)-1);
  }
}
分析:如果最初的数值类型是有符号的,就执行符号扩展。如果是char,那么不管它将要被转换成什么类型,都执行零扩展。

问题:Dos Equis

代码:

/**
 * DosEquis
 * @authorLiangGzone
 */
public class DosEquis {
  publicstatic void main(String[] args) {
  charx = 'X';
  inti = 0;
  System.out.println(true?x:0);
  System.out.println(false?i:x);
  }
}

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

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


链接:

Java陷阱(二)











文章评论

软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有