JDK 作为我们每天必备的调用类库,里面大量提供了基础类供我们使用。可以说离开 JDK ,我们的 Java代码寸步难行。
JDK 带给我们的便利可谓是不胜枚举,但同时这些方法在使用起来也存在一些坑,如果不注意就很容易掉入到陷阱里面,导致程序抛出错误。
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
注意:这里返回了一个 "null" 的字符串,而不是 null。这两个是有很大区别的。当进行非空判断的时候,返回的是 true。也就是这个 "null" 字符串是符合判空条件的!
正确的姿势是在 String.valueOf 方法前必须判空:
Object obj= null;
// 判空
if(obj != null) {
String str= String.valueOf(obj);
}
Integer.parseInt() 方法用于将字符串转化为 Integer 类型的方法。此方法的适用性就显得比较窄,因为是 String 类型的参数没有任何限定,当在传入一些比如 20.0、20L、30d、40f 这类数据的情况下会抛出异常。
String input = "20.0";
int out = Integer.parseInt(input);
会抛出异常 NumberFormatException:
Exception in thread "main" java.lang.NumberFormatException: For input string: "20.0"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
所以对于数字,最好可以用 BigDecimal 进行转换!
众所周知,BigDecimal 是处理金额最有效的数据类型。一般进行财务报表计算的时候为了防止金额出现错误,一般情况下都会采用 BigDecimal。而 double、float 都会存在些许的误差。
常见的除法用起来没有任何丝毫的问题,妥妥的没毛病。
你开开心心地用 BigDecimal 进行了计算,而最终的结果返回却有问题。
public static void main(String[] args) throws Exception {
BigDecimal ten = new BigDecimal(10);
BigDecimal three= new BigDecimal(3);
BigDecimal result = ten.divide(three);
System.out.println(result.toString());
}
执行结果报错:
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1693)
这就是 BigDecimal 除法的坑:一旦返回的结果是无限循环小数,就会抛出 ArithmeticException。因此在进行 BigDecimal 除法的时候,需要进行保留小数的处理。
public static void main(String[] args) throws Exception {
BigDecimal ten = new BigDecimal(10);
BigDecimal three= new BigDecimal(3);
BigDecimal result = ten.divide(three, 2, BigDecimal.ROUND_HALF_UP);
System.out.println(result.toString());
}
执行结果:
3.33
在接口服务层处理时候,我们可能会对没有数据是返回一个空的List:Collections.emptyList()。
public List<String> get(String param) {
// 逻辑处理
// ......
// 没有数据返回空集合
return Collections.emptyList();
}
表面上看起来没有问题,但是一旦接受者对结果进行操作,就会出现异常:
List<String> resultList = service.get("param");
resultList.add("test");
运行结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
主要问题在于 Collections.emptyList() 并非我们平时看到的 List,此List 不支持 add、remove 方法。原因是 Collections.emptyList 返回的并不是我们平时认识的那个 List,它是一个内部常量类,是一种只读的 List ,并不提供数据的写入能力。因此它仅可作为一种空值返回,无法进行删除、添加操作。
public static final List EMPTY_LIST = new EmptyList<>();
虽然 BigDecimal 重写了 equals 方法,但是使用会存在问题:
public static void main(String[] args) {
boolean b = new BigDecimal("1").equals(new BigDecimal("1.0"));
System.out.println(b);
}
运行结果:
false
1 和 1.0 在比较的时候返回了 false。这是因为在 equals 的源码中进行了数据的 scale(也就是精度)的比较。如果不一致就会返回 false。如果使用 compareTo() 方法就不存在这个问题。
public static void main(String[] args) throws Exception {
BigDecimal bd1 = new BigDecimal("1");
BigDecimal bd2 = new BigDecimal("1.0");
int i = bd1.compareTo(bd2);
// i = 0 : bd1 == bd2
// i = -1 : bd1 < bd2
// i = 1 : bd1 > bd2
}
String 的 split 方法在进行 || 分割的时候需要进行转义,否则结果会有问题!
public static void main(String[] args) throws Exception {
String str = "77|88";
String[] s1 = str.split("|");
String[] s2 = str.split("\\|");
System.out.print("错误:");
for (String s : s1) {
System.out.print(s + "\t");
}
System.out.print("\n");
System.out.print("正确:");
for (String s : s2) {
System.out.print(s + "\t");
}
}
运行结果:
错误:7 7 | 8 8
正确:77 88
JDK 的设计者有两个很大的特点:
在实际开发中,面对 JDK 一定要谨慎使用。JDK 提供了便利的同时,也有一些我们使用上的盲区。应该养成多看源码,多注意错误性处理,防止在小问题上栽大跟头。