📜  5 个最常见的Java陷阱(1)

📅  最后修改于: 2023-12-03 15:29:12.082000             🧑  作者: Mango

5 个最常见的Java陷阱

作为一门广泛应用的编程语言,Java拥有许多容易被开发者忽视的坑。本文将介绍5个常见的Java陷阱及如何避免它们。

1. 混淆在泛型中的类型与原始类型

Java中的泛型机制使得开发者可以在编写通用代码时避免类型转换及其可能导致的类型异常。然而,如果开发者对泛型理解不够透彻,则容易陷入混淆类型的陷阱。

例如,以下代码中的list1和list2都是ArrayList,但是它们存储的元素类型是不同的:

ArrayList list1 = new ArrayList();
ArrayList<String> list2 = new ArrayList();

为了避免混淆泛型和原始类型,建议始终在声明集合类型时使用泛型。

2. 理解浮点数计算的误差

由于浮点数在计算机中的存储方式与人类对浮点数的概念不同,因此在进行浮点数计算时很容易出现预期之外的结果。

例如,计算0.1+0.2的结果不是0.3,而是一个接近0.3但是不精确的浮点数,因为这两个数在二进制中是无限循环小数,而计算机只能进行有限位数的存储和计算。

为了避免浮点数计算误差,建议使用BigDecimal类进行高精度计算。

3. static变量的初始化

当我们定义一个static变量时,我们需要确保它已经初始化。如果未初始化,它将采用默认值(0,null,false等)。这可能在代码中产生严重的错误,并且很难排查问题。

例如,以下代码中getStaticValue()方法将返回null,因为静态变量str未进行初始化。

public class TestClass {
    private static String str;
 
    public static String getStaticValue() {
        return str;
    }
}

为了避免静态变量的未初始化,我们应该在声明静态变量时立即将其赋初值。

4. 判断对象相等时需要重写equals方法

如果我们将一个对象用==运算符与另一个对象作比较,它会比较对象的引用。也就是说,只有当两个对象的引用是相同的时,==运算符才会返回true。如果我们想要比较两个对象的内容是否相同,则需要重写equals方法。

以下是一个不重写equals方法的例子:

public class Person {
    private String name;
    private Integer age;
 
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
 
    public static void main(String[] args) {
        Person p1 = new Person("John", 30);
        Person p2 = new Person("John", 30);
 
        System.out.println(p1 == p2);
        System.out.println(p1.equals(p2));
    }
}

输出结果为false和false,因为p1和p2虽然属性相同,但是引用不同。如果我们想要比较p1和p2的内容是否相同,需要重写equals方法。

5. 在finally语句中覆盖异常

在Java中,try-catch语句可以用于处理异常。如果在try块中发生了异常,系统会跳转到catch块中以执行相关的异常处理。无论try块中是否发生异常,finally块中的语句都会执行。通常我们在finally块中释放资源或进行清理工作。

然而,如果finally块中发生了异常,则当前异常将被finally块中的异常所覆盖,并且外部的catch块将无法捕捉到该异常。这会导致很难查明问题,并使代码难以调试。

为了避免在finally语句中覆盖异常,我们需要确保finally中的代码不会抛出异常,或者至少记录下finally块中的异常。如果finally中需要进行异常处理,则应该在finally块中使用try-catch语句。