JAVASE part09-异常

异常

1.异常概述

异常: 不正常的情况

举例: 周末天气很好,我们出去骑车。骑自行车去成都绿道

​ 问题1: 去骑自行车,租车,租车后发现,没有气了

​ 问题2: 换一辆,开始骑了, 感觉绿道 ,happy 的不得了, 突然有个小石头,小小摔倒了

​ 问题3: 骑着骑着,发现,路段了

概念: 异常指的是在程序的运行过程中发生的不正常的事件

异常体系(异常分类)

​ Throwable (超类)

error (严重) Exception

​ RuntimeException (运行时异常) 其它(编译时异常)

严重问题: Error 我们不处理。 这种错误太严重了, OutOfMemoryError 计算中觉见的错误,内存溢出

​ 问题: Exception

​ 编译期问题: 不是RuntimeException 类及它子类的异常,

​ 运行期问题: 是RuntimeException 类强它的子类的异步

3.异常体系

异常体系

4.jvm 默认如何处理异常

如果程序出现异常,我们没有处理,它会打印异常信息到控制台, 并且终止程序

5.Throwable类的常见方法

  1. e.printStackTrace() 打印异常信息到控制台( 出现类什么类型的异常+信息+位置)

  2. e.getMessage() 异常信息,如果想打印需要自己打印

  3. e.toString() 出现类什么类型的异常+信息

注: System.exit(0); 退出程序

6.异常处理

自己处理

​ 注:

  1. 在使用catch 对异常进行处理时,catch声明的异常类型应该和实际抛出的异常类型,相同,或者是继承关系,才能捕获。

  2. 方法中的异常,可以在方法里进行处理,也可以在调用方法时,进行处理

单个异常处理

​ 语法:

try{

   可能出现异常的代码块
   
}catch(异常类型 异常名){

   针对这个异常进行处理
   
}finilly{

   都会执行,释放资源相关代码
}

注: try里面的代码越少越好

单个异常

多个异常处理
try{
   可能出现异常的代码块
}catch(异常类型 异常名){
   针对这个异常进行处理
}catch(异常类型 异常名){
   针对这个异常进行处理
}catch(异常类型 异常名){
   针对这个异常进行处理
}
finilly{
   都会执行,释放资源相关代码
}

多个异常

7.抛出异常

throws

通过throws关键字将异常交给调用者来处理, 可以抛出多个异常,多个异常之间用逗号

throws作用:

定义一个方法的时候可以使用throws关键字声明,使用throws关键字声明的方法表示此方法不处理异常,而交给方法的调用者进行处理

注:

  1. 调用的方法如果 throws 抛出了异常,调用方法时,要进行处理(1. try … catch … 2. 用throws 向外抛出)
  2. 重写一个方法时,throws 抛出的异常,父类不能小于子类的范围(子不能比坏)

throw

抛出异常, 可以确定出现异常

语法:

throw new 异常类型("异常信息"); 

  if(num2 == 0){
            throw new ArithmeticException("除数不能为0");
        }
        System.out.println(num/num2);

8.throw 与 throws的区别

  1. throws用在方法名后面,跟的是异常类名,throw是用在方法体中,跟的异常对象

  2. throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象

  3. throws表示抛出异常,由该方法的调用者来处理, throw表示抛出异常,由方法体内的语句处理

  4. throws表示出现异常的一种可能性,并不一定发生这些异常,throw则是抛出了具体的异常,真是的产生了一个Exception对象

9.finally

放在finally中的代码,不管程序是否发生异常都会执行

只有程序执行了try块中的代码,finally就都会执行前提是没有执行System.exit ()

try块中写return 也没有用, finally 中的代码还是要执行

组合形式:

try{}  catch(){}
try{}  catch(){}   catch(){}  catch(){} ...
try{}  finally{}
try{}  catch(){} finally{}
try{}  catch(){}   catch(){}  catch(){} ...finally{}

10.return 与 finally 相关的面试题

在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。

在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,

执行完finally之后,在从中取出返回结果,

因此,即使finally中对变量x进行了改变,但是不会影响返回结果。它应该使用栈保存返回值。

public class Example07 {
    public static void main(String[] args) {
        System.out.println(test());
    }
    public static int test(){
        int x = 1;
        try{
            x++;  // 2
            return x; // return 2
        }finally {
            ++x;  //3
            System.out.println(x);  //3
        }
    }
}

面试题

final,finally,finalize的区别?

final:最终的 可以修饰类(类不能被继承) 成员变量(变量就不能重新赋值)  成员方法(不能被重写)
finally: 是异常处理的一部分,放在里面的代码不管是否发生异常都会执行
finalize: Object类中的一个方法,用于垃圾回收器回收对象的时候调用

自定义异常

  1. 用户名不能为空

  2. 用户名的年龄需要在0-150之间

class MyException extends Exception{
    private String message;
    public MyException(){

    }
    public MyException(String message){
        this.message = message;
    }
    @Override
    public String getMessage() {
        return message;
    }
}
class Student2{
    private int age;
    public void setAge(int age) throws MyException{
        if(age>=0 && age <= 150){
            this.age = age;
        }
        else{
            throw new MyException("年龄必须在0-150之间");
        }
    }
}
public class Example08 {
    public static void main(String[] args) throws MyException {
//        String username = "";
//        if(username.length() ==0){
//            throw new MyException("用户名不能为空");
//        }

        int age =-1;
        Student2 stu = new Student2();
        stu.setAge(age);
    }
}

ClassCastException: 类不兼容

NullpointException:空指针

ArrayIndexOutofboundException: 数组下标超界

ArithmeticException: 计算出错

测试:

第一题

题目(try-catch,局部变量)有如下代码

public class TestTryCatch{

public static void main(String args[]){

System.out.println( ma() );

}

public static int ma(){

int n;

try{

n = 10/0;

}catch(Exception e){

}

return n;

}

}

选择正确答案:

A. 编译不通过

B. 编译通过,输出-1

C. 编译通过,输出 0

第二题

题目:(方法覆盖)

import java.io.*;

class MySuper{

public void m() throws IOException{}

}

class MySub extends MySuper{

public void m() throws EOFException{}

}

class MySub2 extends MySub {

public void m() throws FileNotFoundException{}

}

输出效果
题目(异常处理)有如下代码

import java.io.*;

import java.sql.*;

public class TestTryCatch{

public static void main(String args[]){

try{

ma(10);

System.out.println(“No Exception”);

}catch(EOFException ex1){

System.out.println(“ex1”);

} catch(IOException ex2) {

System.out.println(“ex2”);

} catch(SQLException ex3) {

System.out.println(“ex3”);

}

}

public static void ma(int n) throws Exception{

if (n == 1){

throw new IOException();

}else if (n == 2){

throw new EOFException();

}else if (n == 3) {

throw new SQLException();

}

}

}

选择正确答案:

A. 编译不通过

B. 编译通过,输出 No Exception

C. 编译通过,输出 ex1

D. 编译通过,输出 ex2

E. 编译通过,输出 ex3

输出效果

面试题

第一题:编译期异常和运行期异常的区别?

运行时异常包括 RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常。 Java 编译器不会检查运行时异常。

受检异常是Exception 中除 RuntimeException 及其子类之外的异常。 Java 编译器会检查受检异常。

RuntimeException异常和受检异常之间的区别:是否强制要求调用者必须处理此异常,如果强制要求调用者必须进行处理,那么就使用受检异常,否则就选择非受检异常(RuntimeException)。一般来讲,如果没有特殊的要求,我们建议使用RuntimeException异常。

第二题:throw和throws的区别

Java 中的异常处理除了包括捕获异常和处理异常之外,还包括声明异常和拋出异常,可以通过 throws 关键字在方法上声明该方法要拋出的异常,或者在方法内部通过 throw 拋出异常对象。

throws 关键字和 throw 关键字在使用上的几点区别如下:

throw 关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查异常和非受查异常都可以被抛出。

throws 关键字用在方法声明上,可以抛出多个异常,用来标识该方法可能抛出的异常列表。一个方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否则也要在方法签名中用 throws 关键字声明相应的异常。

第三题:final,finally,finalize的区别?

final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值。

finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。

finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,Java 中允许使用 finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

第四题:Error 和 Exception 区别是什么?

Error 类型的错误通常为虚拟机相关错误,如系统崩溃,内存不足,堆栈溢出等,编译器不会对这类错误进行检测,JAVA 应用程序也不应对这类错误进行捕获,一旦这类错误发生,通常应用程序会被终止,仅靠应用程序本身无法恢复;

Exception 类的错误是可以在应用程序中进行捕获并处理的,通常遇到这种错误,应对其进行处理,使应用程序可以继续正常运行。

第五题:JVM 是如何处理异常的?

在一个方法中如果发生异常,这个方法会创建一个异常对象,并转交给 JVM,该异常对象包含异常名称,异常描述以及异常发生时应用程序的状态。创建异常对象并转交给 JVM 的过程称为抛出异常。可能有一系列的方法调用,最终才进入抛出异常的方法,这一系列方法调用的有序列表叫做调用栈。

JVM 会顺着调用栈去查找看是否有可以处理异常的代码,如果有,则调用异常处理代码。当 JVM 发现可以处理异常的代码时,会把发生的异常传递给它。如果 JVM 没有找到可以处理该异常的代码块,JVM 就会将该异常转交给默认的异常处理器(默认处理器为 JVM 的一部分),默认异常处理器打印出异常信息并终止应用程序。

第六题:try-catch-finally 中哪个部分可以省略?

catch 可以省略

原因:

更为严格的说法其实是:try只适合处理运行时异常,try+catch适合处理运行时异常+普通异常。也就是说,如果你只用try去处理普通异常却不加以catch处理,编译是通不过的,因为编译器硬性规定,普通异常如果选择捕获,则必须用catch显示声明以便进一步处理。而运行时异常在编译时没有如此规定,所以catch可以省略,你加上catch编译器也觉得无可厚非。

理论上,编译器看任何代码都不顺眼,都觉得可能有潜在的问题,所以你即使对所有代码加上try,代码在运行期时也只不过是在正常运行的基础上加一层皮。但是你一旦对一段代码加上try,就等于显示地承诺编译器,对这段代码可能抛出的异常进行捕获而非向上抛出处理。如果是普通异常,编译器要求必须用catch捕获以便进一步处理;如果运行时异常,捕获然后丢弃并且+finally扫尾处理,或者加上catch捕获以便进一步处理。

至于加上finally,则是在不管有没捕获异常,都要进行的“扫尾”处理。

第七题:try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

会执行,在 return 前执行。

注意:在 finally 中改变返回值的做法是不好的,因为如果存在 finally 代码块,try中的 return 语句不会立马返回调用者,而是记录下返回值待 finally 代码块执行完毕之后再向调用者返回其值,然后如果在 finally 中修改了返回值,就会返回修改后的值。显然,在 finally 中返回或者修改返回值会对程序造成很大的困扰,C#中直接用编译错误的方式来阻止程序员干这种龌龊的事情,Java 中也可以通过提升编译器的语法检查级别来产生警告或错误。

第八题:常见的 RuntimeException 有哪些?

ClassCastException(类转换异常)

IndexOutOfBoundsException(数组越界)

NullPointerException(空指针)

ArrayStoreException(数据存储异常,操作数组时类型不一致)

还有IO操作的BufferOverflowException异常

  • 25
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值