解惑是一本关于java基础的书籍,内jdk版本较低,但仍值得一读,有很多基础但非常重要的思想。
下面进行一些举例和解惑:
1:
package com.gcc.javaRiddle;
import java.math.BigDecimal;
public class Accuracy {
public static void main(String[] args) {
System.out.println(2.00-1.4+"元");
System.out.println(200-140+"分");
System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.4")));
}
}
最常见的数字迷惑,精度计算, java小数默认是double类型,计算小数会有精度缺失,这时如果你从事的是金融相关的项目要非常注意这一点,在金融上面精度缺失是致命的!有面试金融或者电商一类单位的同志们也注意下此类数据的处理。
* 解决方案1,改变单位,将小数改为整数用int或long来计算 * 解决方案2,用BigDecimal,注意new对象用string类型
运行结果:
0.6000000000000001元
60分
0.60
2:
package com.gcc.javaRiddle;
public class BiggestValue {
public static void main(String[] args) {
int count=0;
for (int i = Integer.MAX_VALUE-100; i <=Integer.MAX_VALUE; i++) {
count++;
}
System.out.println(count);
}
}
不太会遇到,但又可能遇到的问题,这里提个醒。
运行结果:
结果是死循环,因为i++根本做不到比自己类型上线还大的数值
教训:在用数值时要时刻注意上溢和下溢
3:
package com.gcc.javaRiddle;
import java.math.BigInteger;
public class BigProblem {
public static void main(String[] args) {
BigInteger bigInteger1 = new BigInteger("500");
BigInteger bigInteger2 = new BigInteger("5000");
BigInteger bigInteger3 = new BigInteger("50000");
BigInteger total = BigInteger.ZERO;
total.add(bigInteger1);
total.add(bigInteger2);
total.add(bigInteger3);
// total=total.add(bigInteger1);
// total=total.add(bigInteger2);
// total=total.add(bigInteger3);
System.out.println(total);
}
}
不太会遇到的迷惑,这里用来清晰一个概念。
BigInteger是不可变的,同理还有String,BigDecimal,Integer,Long,Short,Byte,Character,Boolean,Float,Double这类包装类型,不能改变这些的值,对这些类型的操作返回的是新的实例。不要被误导不可变类型是可变的。
运行结果:
0
4:
package com.gcc.javaRiddle;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 在关闭流的时候不能直接连续写:in.close()和out.close();因为在第一个流关闭时报错会导致第二个流没有正常关闭;
* 使用try catch来防止这种错误。
* try catch:捕获错误,并让程序往下走完
*
*/
public class CloseProblem {
public static void main(String[] args) throws IOException {
String src="";//源数据
String dest="";//目的路径
CloseProblem.copy(src, dest);
}
@SuppressWarnings("null")
static void copy(String src, String dest) {
InputStream in = null;
OutputStream out = null;
byte[] buf = new byte[1024];
int n;
try {
while((n=in.read(buf))>=0){
out.write(buf,0,n);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
一个规范的要求,要多关注异常处理,注意内容见代码内注释
5:
package com.gcc.javaRiddle;
public class ConString {
public static void main(String[] args) {
System.out.println("a"+"b");
System.out.println('a'+'b');
}
}
一个很容易被忽视的类型char,一旦使用易发的错误。这里进行解释。
* 第一行输出是字符串,所有结果是拼接结果
* 第二行输出是字符型字面常量,所有结果是加法运算,会拓宽原生类型,char自动转为int
运行结果:
ab
195
6:
package com.gcc.javaRiddle;
public class GetValue {
public static void main(String[] args) {
int j=0;
for (int i = 0; i < 100; i++) {
j=j++;
}
System.out.println(j);
int k=0;
for (int i = 0; i < 100; i++) {
k++;
}
System.out.println(k);
}
}
一个一时手贱,看半天又会自觉觉得没问题的写法,这里给出解释。
* j=j++的执行顺序是,j赋值给j得0,j加1但并没有赋值,j仍为0
运行结果:
0
100
7:
package com.gcc.javaRiddle;
public class Indecision {
public static void main(String[] args) {
System.out.println(decision());
}
@SuppressWarnings("finally")
private static boolean decision() {
try {
return true;
} catch (Exception e) {
} finally{
return false;
}
}
}
一个可以向新手程序员秀一秀的技巧,也是偶尔可能遇到的错误。
* finally的返回值重于try
* 不论try是否出错,若finally有返回值,都将丢掉try的返回值
运行结果:
false
8:
package com.gcc.javaRiddle;
import java.util.Calendar;
public class InitOrder {
// static int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR);
static InitOrder initOrder=new InitOrder();
int size;
static int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR);
private InitOrder() {
size=CURRENT_YEAR-1990;
}
private int getSize(){
return size;
}
public static void main(String[] args) {
System.out.println("InitOrder size is:"+initOrder.getSize());
}
}
静态常量也是一些java新手比较陌生的对象,因为使用的不是特别的频繁,这举一个错误例子。
* 目的是在InitOrder初始化过程中给size赋值。而CURRENT_YEAR也是静态的,赋值操作只会在上一个静态域完成后再执行
* 所以CURRENT_YEAR还是缺省值0
* 修改静态变量赋值循序即可。
教训:使用到静态变量时要多注意声明的位置。
运行结果:
InitOrder size is:-1990