整理好了!2024年最常见 100 道 Java基础面试题(十八)

上一篇地址:整理好了!2024年最常见 100 道 Java基础面试题(十七)-CSDN博客

三十五、运行时异常与受检查异常有什么区别?

在Java中,异常分为两大类:运行时异常和受检查异常,它们之间的主要区别体现在异常处理的强制性、使用场景以及它们继承的类上。

运行时异常(RuntimeException)

  1. 继承关系:运行时异常继承自java.lang.RuntimeException
  2. 编译时检查:Java编译器不会强制方法或代码块捕获运行时异常或声明抛出它们。也就是说,运行时异常是可选捕获的。
  3. 编程错误:运行时异常通常反映了程序中的编程错误,如数组越界、空指针引用等。
  4. 恢复可能性:运行时异常通常被认为是不可恢复的错误,尽管在某些情况下,通过适当的错误处理逻辑,程序可能能够从这些异常中恢复。
  5. 示例
    • NullPointerException
    • IllegalArgumentException
    • IndexOutOfBoundsException

受检查异常(Checked Exceptions)

  1. 继承关系:受检查异常继承自java.lang.Exception但不是RuntimeException的子类。
  2. 编译时检查:Java编译器要求必须处理所有受检查异常。方法可以捕获这些异常或在方法签名中使用throws关键字声明它们,以便调用者处理。
  3. 外部错误:受检查异常通常表示可以从外部条件或用户操作中恢复的异常情况,如文件未找到、数据库连接失败等。
  4. 恢复可能性:受检查异常通常被认为是可以被程序捕获并适当处理的,以恢复程序的正常执行。
  5. 示例
    • IOException
    • SQLException
    • GeneralSecurityException

主要区别

  • 处理强制性:受检查异常必须被捕获或声明抛出,而运行时异常则没有这个要求。
  • 继承类:受检查异常继承自Exception,运行时异常继承自RuntimeException
  • 错误类型:受检查异常通常用于可预见的、可以恢复的错误,而运行时异常通常用于不可预见的编程错误。
  • 使用场景:受检查异常适用于那些调用者可能需要知道并处理的情况,而运行时异常则适用于那些调用者通常不需要处理的情况。

示例

public class ExceptionExample {
    public static void main(String[] args) {
        try {
            readFile(); // 可能抛出IOException
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            processArray(); // 可能抛出IndexOutOfBoundsException
        } catch (IndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }

    public static void readFile() throws IOException {
        // 模拟抛出受检查异常
        throw new IOException("File not found");
    }

    public static void processArray() {
        int[] array = new int[1];
        // 模拟抛出运行时异常
        array[2] = 5; // 这将抛出IndexOutOfBoundsException
    }
}

在这个示例中,readFile 方法抛出了一个受检查异常IOException,调用者必须捕获它或同样声明抛出。而processArray 方法抛出了一个运行时异常IndexOutOfBoundsException,调用者可以选择捕获它,也可以不捕获。

总结

了解运行时异常和受检查异常的区别对于编写健壮且易于维护的Java程序非常重要。合理地使用异常处理可以提高程序的稳定性和可维护性。同时,应该避免滥用异常,例如,不应该使用异常来控制正常的程序流程。

三十六、什么时候会发生空指针异常?

在Java中,空指针异常是一个常见的运行时异常,属于不受检查异常(Unchecked Exceptions),它在尝试使用null引用进行操作时抛出。

以下是一些会导致NullPointerException的常见情况:

  1. 访问对象的成员变量或方法: 当尝试通过一个null引用访问对象的成员变量或调用其方法时,会抛出空指针异常。

    Object obj = null;
    System.out.println(obj.toString()); // 抛出NullPointerException
  2. 数组索引访问: 如果尝试访问一个数组的元素,而该数组为null,则会抛出空指针异常。

    String[] array = null;
    System.out.println(array[0]); // 抛出NullPointerException
  3. 调用超类的方法: 如果子类的实例的超类引用为null,调用超类的方法时会抛出空指针异常。

    class Base {
        void show() {}
    }
    
    class Derived extends Base {
        void test() {
            super.show(); // 如果super引用为null,将抛出NullPointerException
        }
    }
  4. 使用反射调用方法: 通过反射调用对象的方法时,如果该对象为null,也会抛出空指针异常。

    Method method = ...;
    Object obj = null;
    method.invoke(obj); // 抛出NullPointerException
  5. 访问类变量或静态方法: 如果尝试通过一个null类的实例引用访问类变量或静态方法,同样会抛出空指针异常。

    ClassWithStaticField cls = null;
    System.out.println(cls.SOME_STATIC_FIELD); // 抛出NullPointerException
  6. 使用字符串连接: 当使用null字符串与非null字符串进行连接操作时,会抛出空指针异常。

    String str = null;
    String result = str + "some string"; // 抛出NullPointerException
  7. 使用==!=比较对象: 使用==!=比较一个null对象引用和非null对象引用时,不会产生空指针异常,但如果比较涉及null数组,则会。

    String str = null;
    boolean isEqual = str == "some string"; // 不抛出NullPointerException
  8. 方法返回null: 如果一个方法设计为返回对象,但实际返回了null,并且调用者尝试在返回的对象上调用方法或访问变量,那么调用者处会抛出空指针异常。

    Object getObject() {
        return null; // 方法返回null
    }
    
    void useObject() {
        Object obj = getObject();
        obj.toString(); // 抛出NullPointerException
    }

如何避免空指针异常

  • 代码审查:在编写和审查代码时,注意检查可能的null引用使用。
  • 输入验证:对所有可能为null的输入进行验证。
  • 使用Java 8的Optional:使用Optional类来封装可能为null的引用,以避免直接使用裸的null引用。
  • 断言和检查:在方法内部使用断言或显式检查来确保引用不为null
  • 日志记录:记录空指针异常的发生,以便于调试和分析原因。
  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值