Java基础异常

简介: Java基础异常

1、什么是异常,java提供异常处理机制有什么用?


以下程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常

java语言是很完善的语言,提供了异常的处理方式,以下程序执行过程中出现了不正常情况,

java把该异常信息打印输出到控制台,供程序员参考。程序员看到异常信息之后,可以对

程序进行修改,让程序更加的健壮。


什么是异常:程序执行过程中的不正常情况。

异常的作用:增强程序的健壮性。


以下程序执行控制台出现了:


Exception in thread "main" java.lang.ArithmeticException: / by zero
       at com.bjpowernode.javase.exception.ExceptionTest01.main(ExceptionTest01.java:14)


这个信息被我们称为:异常信息。这个信息是JVM打印的。


示例代码01:


public class ExceptionTest01 {
    public static void main(String[] args) {
        /*int a = 10;
        / 实际上JVM在执行到此处的时候,会new异常对象:new ArithmeticException("/ by zero");
        // 并且JVM将new的异常对象抛出,打印输出信息到控制台了。
        int b = 0;
        int c = a / b;
        System.out.println(a + "/" + b + "=" + c);*/
        // 此处运行也会创建一个:ArithmeticException类型的异常对象。
        //System.out.println(100 / 0);
        // 我观察到异常信息之后,对程序进行修改,更加健壮。
        int a = 10;
        int b = 0;
        if(b == 0){
            System.out.println("数字错误,b不能为0!");
            return;
        }
        // 程序执行到此处表示除数一定不是0
        int c = a / b;
        System.out.println(a + "/" + b + "=" + c);
    }
}


运行结果:


数字错误,b不能为0


2、java语言中异常是以什么形式存在的呢?


异常在java中以类的形式存在,每一个异常类都可以创建异常对象。

异常对应的现实生活中是怎样的?

火灾(异常类):

2008年8月8日,小明家着火了(异常对象)

2008年8月9日,小刚家着火了(异常对象)

2008年9月8日,小红家着火了(异常对象)

类是:模板。

对象是:实际存在的个体

钱包丢了(异常类):

2008年1月8日,小明的钱包丢了(异常对象)

2008年1月9日,小芳的钱包丢了(异常对象)


示例代码02:


public class ExceptionTest02 {
    public static void main(String[] args) {
        NumberFormatException num = new NumberFormatException("数字格式化异常!");
        //java.lang.NumberFormatException: 数字格式化异常!
        System.out.println(num);
        NullPointerException nul = new NullPointerException("空指针异常!");
        //java.lang.NullPointerException: 空指针异常!
        System.out.println(nul);
    }
}


3、异常处理机制


java中异常的作用是:增强程序健壮性。


java中异常以类和对象的形式存在。


Object下有Throwable(可抛出的)


Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)


Exception下有两个分支:


Exception的直接子类:编译时异常(要求程序员在编写程序阶段必须预先对这些异常进行处理,如果不处理编译器报错)


RuntimeException:运行时异常。(在编写程序阶段程序员可以预先处理,也可以不管,都行)


编译时异常和运行时异常,都是发生在运行阶段。编译阶段异常是不会发生的。


4、编译时异常因为什么而得名?


因为编译时异常必须在编译(编写)阶段预先处理,如果不处理编译器报错,因此得名。

所有异常都是在运行阶段发生的。因为只有程序运行阶段才可以new对象。

因为异常的发生就是new异常对象。


5、编译时异常和运行时异常的区别?


编译时异常一般发生的概率比较高。

举个例子:

你看到外面下雨了,倾盆大雨的。

你出门之前会预料到:如果不打伞,我可能会生病(生病是一种异常)。

而且这个异常发生的概率很高,所以我们出门之前要拿一把伞。

“拿一把伞”就是对“生病异常”发生之前的一种处理方式。


对于一些发生概率较高的异常,需要在运行之前对其进行预处理。


运行时异常一般发生的概率比较低。


举个例子:

小明走在大街上,可能会被天上的飞机轮子砸到。

被飞机轮子砸到也算一种异常。

但是这种异常发生概率较低。

在出门之前你没必要提前对这种发生概率较低的异常进行预处理。

如果你预处理这种异常,你将活的很累。


假设你在出门之前,你把能够发生的异常都预先处理,你这个人会更加

的安全,但是你这个人活的很累。


6、编译时异常还有其它名字:


受检异常:CheckedException


受控异常


运行时异常还有其它名字:


未受检异常:UnCheckException


非受检异常


再次强调:所有异常都是发生在运行阶段的


7、Java语言中对异常的处理包括两种方式:


第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级。

谁调用我,我就抛给谁。抛给上一级。上报

第二种方式:使用try…catch语句进行异常的捕捉。

这件事发生了,谁也不知道,因为我给抓住了。不会上报,不会上抛

举个例子:

我是某集团的一个销售员,因为我的失误,导致公司损失了1000元,

“损失1000元”这可以看做是一个异常发生了。我有两种处理方式,

第一种方式:我把这件事告诉我的领导【异常上抛】

第二种方式:我自己掏腰包把这个钱补上。【异常的捕捉】


张三 --> 李四 —> 王五 --> CEO


思考:

异常发生之后,如果我选择了上抛,抛给了我的调用者,调用者需要

对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式。


注意:Java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续

向上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果。终止java程序的执行。


示例代码03:


public class ExceptionTest03 {
    public static void main(String[] args) {
        /*
        * 程序执行到此处发生了ArithmeticException异常,
        * 底层new了一个ArithmeticException异常对象,
        * ,然后跑出了,由于是main方法调用了100/0,
        * 所以这个异常ArithmeticException抛给了main方法,
        * main方法没有处理,将这个异常自动抛给了JVM
        * JVM最终终止程序的执行
        *
        * ArithmeticException 继承RuntimeException,属于运行时异常
        * 在编写程序阶段不需要对这种异常进行预先的处理
        * */
        int i = 10;
        int a = 0;
        System.out.println(i / a);
        //这里的HelloWorld没有输出,没有执行
        System.out.println("HelloWorld!");
    }
}


示例代码04:


/*
* 以下代码报错的原因是什么?
*    因为doSome()方法声明位置上使用了:throws ClassNotFoundException
*    而ClassNotFoundException是编译时异常。必须编写代码时处理,没有处理编译器报错。
* */
public class ExceptionTest04 {
    public static void main(String[] args) {
        //main方法中调用doSome()方法
        //因为dosome()方法声明位置上有:throws ClassNOtFoundException
        //我们在调用doSome()方法时必须对这种对象进行预先的处理
        //如果不处理,编译器就报错
        //编译器报错信息: UnHandled exception:java.lang.ClassNotFoundException
        //doSome();
    }
    /**
     * doSome方法在方法声明的位置上使用了:throws ClassNotFoundException
     * 这个代码在表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常
     * 叫做类没找到异常,这个异常直接父类是:Exception,所以ClassNotFoundException属于编译时异常
     * @throws ClassNotFoundException
     */
    public static void doSome() throws ClassNotFoundException{
        System.out.println("异常测试方法!");
    }
}


示例代码05:


public class ExceptionTest05 {
    //第一种处理方式,把异常抛给上一级
    //在方法声明位置上继续使用:throws,来完成异常的继续上抛。抛给调用者。
    //上抛类似于推卸责任。(继续把异常传递给调用者)
    public static void main(String[] args) throws Exception{
       //第二种处理方式
        //捕捉等于把异常来下了,异常真正的解决了。(调用者是不知道的)
       try{
           doSome();
       }catch(ClassNotFoundException e){
           e.printStackTrace();
       }
    }
    public static void doSome() throws ClassNotFoundException{
        System.out.println("输出类找不到异常!");
    }
}


注意:


只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行。

另外需要注意,try语句块中的某一行出现异常,该行后面的代码不会执行。

try…catch捕捉异常之后,后续代码可以执行。


在以后的开发中,处理编译时异常,应该上报还是捕捉呢,怎么选?

如果希望调用者来处理,选择throws上报。

其它情况使用捕捉的方式。


示例代码06:


public class ExceptionTest06 {
    public static void main(String[] args) {
        //一般不建议在main方法上使用throws,因为这个异常如果真正的发生了,一定会抛给JVM。JVM只有终止。
        //异常处理机制的作用就是增强程序的健壮性。怎么能做到,异常发生了也不影响程序的执行。所以
        //一般main方法中的异常建议使用try..catch进行捕捉。main就不要继续上抛了。
        // 100 / 0这是算术异常,这个异常是运行时异常,你在编译阶段,可以处理,也可以不处理。编译器不管。
        //System.out.println(100 / 0); // 不处理编译器也不管
        // 你处理也可以。
        /*
        try {
            System.out.println(100 / 0);
        } catch(ArithmeticException e){
            System.out.println("算术异常了!!!!");
        }
         */
        //try.caytch把异常捕捉之后,这里的代码会继续执行
        System.out.println("main begin!");
        try {
            //try尝试
            m1();
            //以上代码出现异常,直接进入catch语句块中执行
        }catch(FileNotFoundException e){//catch后面的好像一个方法的形参
            //这个分支中可以使用e引用,e引用保存的内存地址是
            //catch是捕捉异常之后走的分支
            //在catch分支中干什么?处理异常
            System.out.println("文件异常,文件路径错误,或者文件不存在!");
        }
        //try..catch把异常抓住之后,这里的代码会继续执行
        System.out.println("main over!");
    }
    public static void m1() throws FileNotFoundException{
        System.out.println("m1 begin!");
        m2();
        //以上出现异常,这里是无法执行的!
        System.out.println("m1 over!");
    }
    //抛别的不行,抛ClassCastException说明你还是没有对FileNotFoundException进行处理
    //private static void m2() throws ClassCastException{
    //抛FileNotFoundException的父对象IOException,这样是对的。因为IOException包括FileNotFoundException
    //private static void m2() throws IOExcception
    //这样也可以,因为Exception包括所有的异常
    //private static void m2() throws Exception
    //throws后面也可以写多个异常,可以使用逗号隔开
    //private static void m2() throws ClassCastException,FileNotFoundException
    public static void m2() throws ClassCastException,FileNotFoundException{
        System.out.println("m2 begin!");
        //编译器报错的原因是:m3()方法声明位置上有:throws FileNotFoundException
        //我们在这里调用m3()没有对异常进行预处理,所以编译报错
        //m3();
        m3();
        //以上出现异常,这里是无法执行的!
        System.out.println("m2 over!");
    }
    public static void m3() throws FileNotFoundException {
        //调用SUN jdk中每个类的构造方法
        //这个类还没有接触过,后期IO流的时候就知道了
        //这里借助这个类学习以下异常处理机制
        //创建一个输出流对象,该流指向一个文件
        /*
        * 编译报错的原因是什么?
        * 第一:这里调用了一个构造方法:FileNotFoundException(String name)
        * 第二:这个构造方法的声明的位置上有:throws FileNotFoundException
        * 第三:通过类的继承结构看到:FileNotFoundException父类是IOException,IOException的父类是Exception
        * 最终得知:FileNotFoundException是编译时异常
        *
        * 错误原因?编译时异常要求程序员编写阶段必须对它进行处理,不处理编译器就报错
        * */
        //我们采用第一种处理方式:在方法声明的位置上使用throws继续上抛
        //一个方法体当中的代码出现异常之后,如果上报的话,此方法结束。
        new FileInputStream("D:\\Notepad++\\config.java");//\是转义
        System.out.println("如果以上代码出现异常,这里会执行吗?????????不会!!!");
    }
}


运行结果:


0a2653c851af460fa595bd959398a8f1.png


示例代码08:


public class ExceptionTest07 {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("D:\\Notepad++\\config.xml");
            System.out.println("以上出现异常,这里无法执行!");
        }catch(FileNotFoundException e){
            System.out.println("文件不存在!");
        }
        try{
            FileInputStream fis = new FileInputStream("D:\\Notepad++\\config.xml");
        }catch(IOException e){//多态 IOException e = new FileNotFoundException();
            System.out.println("文件不存在!");
        }
        try{
            FileInputStream fis = new FileInputStream("D:\\Notepad++\\config.xml");
        }catch(Exception e){//多态 Exception e = new FileNotFoundException();
            System.out.println("文件不存在!");
        }
        try{
            FileInputStream fis = new FileInputStream("D:\\Notepad++\\config.xml");
            fis.read();
        }catch(FileNotFoundException e){
            System.out.println("文件不存在!");
        }catch(IOException e){
            System.out.println("读文件报错了!");
        }
        try{
            FileInputStream fis = new FileInputStream("D:\\Notepad++\\config.xml");
            fis.read();
        }catch(Exception e){//多态 IOException e = new FileNotFoundException();
            System.out.println("文件不存在!");
        }
        /*try{
            FileInputStream fis = new FileInputStream("D:\\Notepad++\\config.xml");
            fis.read();
        }catch(IOException e){
            System.out.println("文件异常!");
        }catch(FileNotFoundException e){//报错,因为IOException已经包括FileNotFoundException
            System.out.println("文件不存在!");
        }*/
        // JDK8的新特性!
        try{
            FileInputStream fis = new FileInputStream("D:\\Notepad++\\config.xml");
            fis.read();
            System.out.println( 10 / 0);
        }catch(IOException | ArithmeticException | NullPointerException e){
            System.out.println("文件不存在 | 读文件报错 | 数字异常 | 空指针异常");
        }
    }
}


运行结果:


2d65d23f6d4748949b924e4057485923.png

相关文章
|
2月前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
73 1
|
2月前
|
Java API 调度
如何避免 Java 中的 TimeoutException 异常
在Java中,`TimeoutException`通常发生在执行操作超过预设时间时。要避免此异常,可以优化代码逻辑,减少不必要的等待;合理设置超时时间,确保其足够完成正常操作;使用异步处理或线程池管理任务,提高程序响应性。
83 12
|
2月前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
44 1
|
2月前
|
IDE 前端开发 Java
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
78 7
|
2月前
|
Java 编译器
如何避免在 Java 中出现 NoSuchElementException 异常
在Java中,`NoSuchElementException`通常发生在使用迭代器、枚举或流等遍历集合时,尝试访问不存在的元素。为了避免该异常,可以在访问前检查是否有下一个元素(如使用`hasNext()`方法),或者使用`Optional`类处理可能为空的情况。正确管理集合边界和条件判断是关键。
91 6
|
2月前
|
Java
Java异常捕捉处理和错误处理
Java异常捕捉处理和错误处理
68 1
|
2月前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
84 2
|
3月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
95 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
2月前
|
Java
如何在 Java 中处理“Broken Pipe”异常
在Java中处理“Broken Pipe”异常,通常发生在网络通信中,如Socket编程时。该异常表示写入操作的另一端已关闭连接。解决方法包括:检查网络连接、设置超时、使用try-catch捕获异常并进行重试或关闭资源。
117 5
|
2月前
|
存储 安全 Java
如何避免 Java 中的“ArrayStoreException”异常
在Java中,ArrayStoreException异常通常发生在尝试将不兼容的对象存储到泛型数组中时。为了避免这种异常,确保在操作数组时遵循以下几点:1. 使用泛型确保类型安全;2. 避免生类型(raw types)的使用;3. 在添加元素前进行类型检查。通过这些方法,可以有效防止 ArrayStoreException 的发生。
49 3