异常处理的基本使用 -- 《JAVA编程思想》35

本文介绍了JAVA异常处理机制,包括终止和恢复模型,try-catch语句的使用,自定义异常的创建及使用,以及如何通过日志记录异常信息。通过实例演示了如何捕获和处理不同类型的异常,强调了代码健壮性和异常管理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JAVA 的基本理念是 “结构不佳的代码不能运行”。

发现错误的理想时机是在编译阶段,即在程序运行之前。然而,在编译期间并不能找出所有错误,余下的问题必须在运行期间解决。

这就需要错误源通过某种方式将适当的信息传递给接收者,再由接收者正确处理这个问题。

错误恢复机制是保障代码健壮性的强有力标志。早期编程语言通常会在方法内设置特殊返回值或者标记,来判定程序是否发生了错误。

每次在调用程序之前都进行错误检查,会使得代码变得难以阅读,特使是在构建大型程序时,会造成很大的阻碍。

JAVA 提供异常处理机制来解决这个问题,异常处理程序不必在方法调用处进行检查,异常机制将保证能捕获这个错误,并在一个地方集中处理错误。

异常会阻止当前方法或作用域继续执行,之后允许我们强制停止程序运行或者强制程序处理问题,并返回稳定状态。

故异常处理理论上拥有2种基本模型:

1.终止模型
假设此错误非常关键,一旦此异常被抛出,表示错误已无法挽回,也不允许程序回来继续执行。

2.恢复模型
这类模型用来修正错误,然后重新尝试调用出问题的方法,通常认为第二次能成功。使用这类模型不能将异常向外抛出,而是调用方法修正错误。通常不建议使用此类模型,因修复错误依赖抛出异常位置的非通用性代码,不仅增加了代码的耦合性,也增加了代码编写和维护的困难。

接下来,我们来看个异常处理的例子:

public class ExceptionFeature {

    public static void main(String[] args) {
        try {
            ArrayList<Object> arrayList = new ArrayList<>();
            arrayList = null;
            System.out.println(arrayList.toString());
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        System.out.println("method finish");
    }
    
}

java.lang.NullPointerException
	at mtn.baymax.charpter12.ExceptionFeature.main(ExceptionFeature.java:16)
method finish

对可能产生异常的代码块使用 try - catch 关键字包裹起来,try { } 包含预计产生异常的代码,然后在 catch(Exception e ) 方法中指定参数,即需要捕获的异常类型,所有的异常类都继承于 Exception 类。

异常在处理完成后,程序会继续执行。若有抛出的异常未处理或者异常处理中再次出现异常且未处理,程序会立即终止。

此外,我们还可以定义多个 catch 块来处理异常,异常只会进入第一个匹配的异常,后续的 catch 不会继续执行,在这里第二个 catch 使用的是 Exception 类,它可以捕获所有类型的异常,但因所有子类都会进行向上转型,不利于根据指定类型异常进行处理的情形。

public class ExceptionFeature {

    public static void main(String[] args) {
        try {
            ArrayList<Object> arrayList = new ArrayList<>();
            arrayList = null;
            System.out.println(arrayList.toString());
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("method finish");
    }

}

其次,我们还可以创建自定义异常,只需继承 Exception 类即可,同时还可定义多个构造器来生成自定义异常类,满足不同场景的需求。

下述例子 SimpleException(String message) 重写了父类构造器中的方法,throw 表示主动抛出异常,throws 表示该方法可能会抛出某种类型的异常,通过 throws抛出异常后,若其他程序调用此方法,编译器会强制要求处理此异常。

public class SimpleException extends Exception {

    public SimpleException() {
        
    }

    public SimpleException(String message) {
        super(message);
    }
    
}
public class InheritingExceptions {

    public void f() throws SimpleException {
        System.out.println("throw simpleException from f()");
        throw new SimpleException();
    }

    public void g() throws SimpleException {
        System.out.println("throw simpleException from g()");
        throw new SimpleException("message");
    }

    public static void main(String[] args) {
        InheritingExceptions inheritingExceptions = new InheritingExceptions();
        try {
            inheritingExceptions.f();
        } catch (SimpleException e) {
            e.printStackTrace();
        }
        try {
            inheritingExceptions.g();
        } catch (SimpleException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
    
}

throw simpleException from f()
throw simpleException from g()
message
mtn.baymax.charpter12.SimpleException
	at mtn.baymax.charpter12.InheritingExceptions.f(InheritingExceptions.java:12)
	at mtn.baymax.charpter12.InheritingExceptions.main(InheritingExceptions.java:23)
mtn.baymax.charpter12.SimpleException: message
	at mtn.baymax.charpter12.InheritingExceptions.g(InheritingExceptions.java:17)
	at mtn.baymax.charpter12.InheritingExceptions.main(InheritingExceptions.java:28)

此外,我们通常会将异常信息记录在日志中,一般是在调用类中进行记录,而非在异常类中直接进行记录。

Exception 类中的 printStackTrace() 不会产生字符串,需调用另一个接收 java.io.StringWriter 对象的重载方法来产生字符串。

public class LoggingException extends Exception {

    public LoggingException() {
        
    }
}
public class LoggingExceptions {

    private static Logger logger = Logger.getLogger("LoggingExceptions");

    public static void main(String[] args) {
        try {
            throw new LoggingException();
        } catch (LoggingException e) {
            StringWriter trace = new StringWriter();
            e.printStackTrace(new PrintWriter(trace));
            logger.severe(trace.toString());
        }
    }

}

七月 10, 2021 9:06:29 下午 mtn.baymax.charpter12.LoggingExceptions main
严重: mtn.baymax.charpter12.LoggingException
	at mtn.baymax.charpter12.LoggingExceptions.main(LoggingExceptions.java:18)

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BaymaxCS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值