【Java入门提高篇】Day16 Java异常处理(上)

简介:   当当当当当当,各位看官,好久不见,甚是想念。  今天我们来聊聊Java里的一个小妖精,那就是异常。什么是异常?什么是异常处理?  异常嘛,顾名思义就是不正常,(逃),是Java程序运行时,发生的预料之外的事情,它阻止了程序按照程序员的预期正常执行。

  当当当当当当,各位看官,好久不见,甚是想念。

  今天我们来聊聊Java里的一个小妖精,那就是异常。

什么是异常?什么是异常处理?

  异常嘛,顾名思义就是不正常,(逃),是Java程序运行时,发生的预料之外的事情,它阻止了程序按照程序员的预期正常执行。

  异常处理,应该说异常处理机制,就是专门用来制服这个小妖精的法宝。Java中的异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。

  简而言之,Java异常处理就是能让我们主动迎击可能到来的异常,并将它们以圆润的方式处理掉。

  还是先来看个小栗子,看看java里的异常长什么样。

public class Test {
    public static void main(String args[]){
        int i = 0 / 0;
        System.out.println("i = " + i);
    }
}

  

  别慌别慌,不要看到红色提示就内心崩溃只想关掉IDE,来,抓紧我的手,带你看清“异常”这个磨人的小妖精的真面目(滑稽)。

  代码里将0作为了分母,因此程序会发生算术异常,抛出一个异常后,如果没有任何处理,默认会终止程序,所以后面的打印内容并没有输出。在异常内容里,有说明异常类型为:java.lang.ArithmeticException,也就是算术异常,后面跟着的是异常原因: / by zero,也就是说异常出现的原因是将0作为了分母,而且后面还有堆栈信息,指出了异常抛出的位置是在com.frank.chapter16.main.Test.main这个包下,Test类的第11行(这个行数如果跟你想的不一样,不要在意,因为我的代码开始之前还有一些不可描述的说明信息),因为只有一次方法调用,所以没有很长的堆栈信息,看起来也很简洁明了。

  所以你看,其实异常也没那么可怕吧,不仅给了异常原因,还告诉了你这个bug是出在第几行,所以好好利用它,可以帮助你写出更难以发现的bug,呸,说错了,可以帮助你更容易找到bug(手动滑稽)。

  如果不希望抛出异常后程序就结束,而是希望它继续运行呢?那么就捕获它。

如何使用异常处理

  我们来把上面那个栗子改改:

public class Test {
    public static void main(String args[]){
        try{
            int i = 0 / 0;
        }catch (Exception e){
            System.out.println("好像发生异常了,但是我不管,我还要继续运行");
        }
        System.out.println("运行完毕!");
    }
}

  输出如下:

好像发生异常了,但是我不管,我还要继续运行
运行完毕!

  好的,很强势,现在即使抛出了异常,程序也继续运行了。异常就像是一头野兽,但你一旦捕获它,驯服它,就可以为你所用,为所欲为了。

  try...catch...是常用的异常处理搭配,如果在try语句块中发生了异常,如果刚好这个异常被捕获到了,那么会直接跳到catch语句块中,执行catch语句中的代码,像上面的栗子里,因为对Exception类进行了捕获处理,所以当它的子类异常java.lang.ArithmeticException被抛出来的时候,也能捕获它。关于Exception类的结构层次关系,后面再做详细介绍。

  还有另外一种搭配方式,那就是try...catch...finally,finally语句块比catch要强势的多,前面说了catch语句块必须要捕获到了特定的Exception才会执行里面的代码,如果catch的是ArithmeticException但是抛出的却是空指针异常,那就不会被捕获了,异常也就逃之夭夭了。这个时候,finally的优势就展示出来了,不管抛出什么样的异常,也不管是否抛出了异常,finally中的代码都会被执行。所以一般的用法是在finally语句块里释放掉那些需要被释放的资源,如socket连接,关闭io流,关闭数据库连接等等。也就是说一般在finally中收拾try中抛出的烂摊子,心疼一秒finally,果然能者多劳啊。

  当然,try...finally这样的搭配也是ok的,需要注意的是,当try语句中发生了异常之后,在发生异常处之后的代码将不会再执行,而是跳到相应的catchu或者finally中去。

public class Test {
    public static void main(String args[]){
        try{
            int i = 0 / 0;
        }catch (NullPointerException e) {
            System.out.println("这里捕获空指针异常");
        }catch (ArithmeticException e){
            System.out.println("这里捕获算术异常");
        }finally {
            System.out.println("这里是finally");
        }
        System.out.println("运行完毕!");
    }
}

  输出如下:

这里捕获算术异常
这里是finally
运行完毕!

  在上面的代码中,catch语句块是可以同时使用多个的,第一个catch语句块捕获的是空指针异常,但由于抛出的是算术异常,所以没有捕获住,但被第二个catch捕获到了,所以第二个catch语句块中的代码执行了。异常匹配是按照从上到下的顺序进行匹配的,最后才执行finally中的代码块。关于try...catch...finally,还有一个很有趣的return问题,如果三个语句块里都有return,最终返回结果会是怎样呢?这里做了详细的说明,http://www.cnblogs.com/mfrank/p/7895660.html 有兴趣的话可以看一看。

  绝大多数情况下,finally中的代码都是会被执行的,只有一种情况下,finally中的代码不会被执行,那就是在try语句块中结束掉了虚拟机(如:使用 System.exit(0); )。

  关于异常,还有一个关键字需要介绍,那就是throw,使用throw可以主动抛出一个异常。看到这你也许会一脸懵逼,主动抛出???嫌异常不够多,凑热闹不嫌事大??别急别急,中间一定有什么误会,把刀放下,有话好好说。

  throw关键字确实是用来抛出异常的,你可以这样使用:

public class Test {
    public static void main(String args[]){
        try{
            throw new NullPointerException("听说你很闲,给你抛个异常。");
        }catch (NullPointerException e) {
            System.out.println("这里捕获空指针异常,提示内容:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

  输出如下:

这里捕获空指针异常,提示内容:听说你很闲,给你抛个异常。
java.lang.NullPointerException: 听说你很闲,给你抛个异常。
    at com.frank.chapter16.main.Test.main(Test.java:11)

  用throw关键字可以抛出任意类型的异常,当然,你想的话,还有抛Error,至于什么是Error,已经跟Exception的关系,将在下一篇里进行讲解。暂时不用深究。

  在throw异常的时候,可以加上抛出异常的原因,这样可以更方便定位问题所在,当然,一般来说不会像栗子中这样使用的,这里只是为了简单起见。

  到此为止,异常的上半篇已经讲解完毕,在这一篇里,说明了什么是异常,什么是异常处理,以及如何使用异常处理机制。相信大家对这个小妖精有了初步的认识,下一篇中,将会讲解Exception家族都有哪些成员,如何使用自定义异常,已经异常处理的实际使用中的正确姿势。欢迎大家继续关注,之后计划每周两篇以上的更新,如果有讲解遗漏或者不好的地方,欢迎大家及时指出,共同进步!

 

真正重要的东西,用眼睛是看不见的。
相关文章
|
12天前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
|
12天前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
|
15天前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
3天前
|
安全 Java 程序员
Java中的异常处理:从新手到专家
在Java编程的世界里,异常处理是每个开发者必须面对的挑战。本文将带你从基础的异常概念出发,逐步深入到高级处理技巧,让你在遇到代码中的“意外”时,能够从容应对,甚至化险为夷。
|
8天前
|
Java 数据库连接 开发者
Java中的异常处理:从基础到高级
【10月更文挑战第42天】在Java的世界中,异常处理是维护程序稳定性和健壮性的关键。本文将带你深入了解Java的异常处理机制,从基本的try-catch语句出发,逐步探索更复杂的异常处理策略。我们将通过实际代码示例来演示如何捕获和处理异常,以及如何自定义异常类型来满足特定需求。无论你是Java新手还是有经验的开发者,这篇文章都将帮助你更好地理解和应用Java的异常处理。
|
13天前
|
IDE 前端开发 Java
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
|
14天前
|
Java 编译器
如何避免在 Java 中出现 NoSuchElementException 异常
在Java中,`NoSuchElementException`通常发生在使用迭代器、枚举或流等遍历集合时,尝试访问不存在的元素。为了避免该异常,可以在访问前检查是否有下一个元素(如使用`hasNext()`方法),或者使用`Optional`类处理可能为空的情况。正确管理集合边界和条件判断是关键。
|
15天前
|
Java 开发者
Java中的异常处理:从基础到高级
【10月更文挑战第35天】在Java的世界里,异常处理是维护程序健壮性的关键。本文将深入浅出地探讨Java的异常处理机制,从基本的try-catch语句到自定义异常类的实现,带领读者理解并掌握如何在Java中优雅地处理错误和异常。我们将通过实际代码示例,展示如何捕获、处理以及预防潜在的运行时错误,确保程序即使在面临意外情况时也能保持稳定运行。
33 7
|
12天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
14天前
|
Java 数据库连接 开发者
Java中的异常处理机制及其最佳实践####
在本文中,我们将探讨Java编程语言中的异常处理机制。通过深入分析try-catch语句、throws关键字以及自定义异常的创建与使用,我们旨在揭示如何有效地管理和响应程序运行中的错误和异常情况。此外,本文还将讨论一些最佳实践,以帮助开发者编写更加健壮和易于维护的代码。 ####
下一篇
无影云桌面