【Java 10】异常处理 - try-catch-finally、throws、throw、自定义异常类

25 篇文章 0 订阅
20 篇文章 0 订阅

异常处理

image-20200813101804110

1 异常概述与异常体系结构

image-20200813102158173

image-20200813103055126

image-20200813103124550

1.1 异常体系结构

image-20200813104139717

2 常见异常

FileNotFoundException

IOXException

@Test
public void test(){
    File file = new File("hello.txt");
    FileInputStream fis = new FileInputStream(file);
    
    int data = fis.read();
    while(data != -1){
        System.out.print((char)data);
        data = fis.read();
    }
    
    fis.close();
}

NullpointerException

@Test
public void test(){
    int[] arr = null;
    System.out.println(arr[3]);
    
    String str = "abc";
    str = null;
    System.out.println(str.charAt(0));
}

ArrayIndexOutOfBoundsException

@Test
public void test(){
    int[] arr = new int[3];
    System.out.println(arr[3]);
    
    String str = "abc";
    System.out.println(str.charAt(3));
}

ClassCastException

@Test
public void test(){
    Object obj = new Date();
    String str = (String)obj
}

NumberFormatException

@Test
public void test(){
    String str = "123";
    str = "abc";
    int num = Integer.parseInt(str);
}

InputMismatchException

@Test
public void test(){
    Scanner scanner = new Scanner(System.in);
    int score = scanner.nextInt();//输入不匹配的
}

ArithmeticException

@Test
public void test(){
    int a = 10;
    int b = 0;
    int c = a/b;
}

3 异常处理机制

image-20200813120442688

Snipaste_2020-08-13_12-09-34

异常的处理:抓抛模型

过程一:“抛”:程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出。一旦抛出对象以后,其后的代码就不再执行。

关于异常对象的产生:

  1. 系统自动生成的异常对象
  2. 手动的生成一个异常对象,并抛出(throw)

过程二:“抓”:可以理解为异常的处理方式:

  1. try-catch-finally
  2. throws + 异常类型

3.1 try-catch-finally

自己处理

3.1.1 格式
try{
    
	//可能出现异常的代码
    
}catch(异常类型1 变量名1){
    
}catch(异常类型2 变量名2){
    
}catch(异常类型3 变量名3){
    
}
...
finally{
    
    //一定会执行的代码
    
}
3.1.2 说明
  1. finally是可选的

  2. 使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配

  3. 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成后,就跳出当前的try-catch结构(在没有写finally情况下)。继续执行其后的代码

  4. catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓

    catch中的异常类型如果满足子父类关系,则要求子类一定声明在父类的上面。否则,报错

  5. 常用的异常对象处理的方式:

    1. String getMessage()
    2. printStackTrace()
  6. 在try结构里声明的变量,在出了try结构后,就不能调用

  7. try-catch-finally结构可以嵌套

3.1.3 代码举例
@Test
public void test(){
    
    int num = 0;
    String str = "123";
    str = "abc";
    try{
        num = Integer.parseInt(str);
    }catch(NumberFormatException e){
        
        //1.
        System.out.println("出现数值转换异常");
        //2.String getMessage();
        System.out.println(e.getMessage());//For input string: "abc"
        //3.printStackTrace();
        e.printStackTrace();//java.lang.NumberFormatException: For input string: "abc"
        
    }catch(NullPointerException e){
        System.out.println("出现空指针异常");
    }catch(Exception e){
        System.out.println("出现异常");
    }
    
    num = 1;
   
}
3.1.4 finally
  1. finally是可选的
  2. finally中声明的是一定会被执行的代码。即使catch中又出现异常了,try中有return语句,catch中有return语句
  3. 像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动的回收的,我们需要自己手动的进行资源的释放。此时的资源释放,就需要声明在finally中
@Test
public void test(){
    
    int a = 10;
    int b = 0;
    try{
        System.out.println(a / b);
    }catch(ArithmeticException e){
        e.printStackTrace();
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        System.out.println("出现过异常");
    }
   
}
@Test
public void test(){
    FileInputStream fis = null;
    try{
        File file = new File("hello.txt");
    	fis = new FileInputStream(file);
    
    	int data = fis.read();
    	while(data != -1){
        	System.out.print((char)data);
        	data = fis.read();
    	}
    }catch(FileNotFoundException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }finally{
        try{
            if(fis != null){//FileNotFoundException后执行这个,防止创建失败还是空指针,出现空指针异常
                fis.close();
            }
        }catch(IOException e){
            e.printStackTrace();
        }
    }
}
3.1.5 体会
  1. (延迟异常)使用try-catch-finally处理编译时异常,使得程序在编译时就不再报错,但是运行时仍可能报错。相当于我们使用try-catch-finally将一个编译时可能出现的异常延迟到运行时出现
  2. 开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。针对编译时异常,我们说一定要考虑异常的处理
3.1.6 快捷操作

image-20200813131632105

3.2 throws + 异常类型

往上报,喊人处理

  1. “throws + 异常类型”写在方法声明处。指明此方法执行时,可能抛处的异常类型。

    一旦此方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。异常代码后续的代码,就不再执行

  2. try-catch-finally:真正的将异常处理了

    throws的方式只是将异常抛给了方法的调用者。并没有真正将异常处理掉

public class ExceptionTest{
    
    public static void main(String[] args)n{
        try{
            method2();
        }catch(IOException e){
            e.printStackTrace()''
        }
        
    }
    
    public static void method2() throws IOException{
        method1();
    }
    
    public static void method1() throws FileNotFoundException,IOException{
        File file = new File("hello.txt");
    	FileInputStream fis = new FileInputStream(file);
    
    	int data = fis.read();
    	while(data != -1){
        	System.out.print((char)data);
        	data = fis.read();
   	 	}
    
    	fis.close();
    }
    
}

3.3 开发中如何选择使用try-catch-finally还是使用throws?

  1. 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中有异常,必须使用try-catch-finally方式处理
  2. 执行的方法中,先后又调用了另外的几个方法,着几个方法是递进关系执行的。我们建议着几个方法使用throw的方式进行处理,而执行的方法a可以考虑使用try-catch-finally方式进行处理

4 手动抛出异常(throw)

内容测试中,敬请期待

public class ExceptionTest{
    
    public static void main(String[] args)n{
        
        try{
            Student s = new Student();
        	s.regist(-1);
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
        
        
    }
    
}

class Student throws Exception{
    
    private int id;
    
    public void regist(int id) throws Exception{
        if(id > 0){
            this.id = id;
      	}else{
            //手动抛出一个异常对象
            //throw new RuntimeException("您输入的数据非法!");//RuntimeException(Message);
            throw new Exception("您输入的数据非法!");
        }
    }
    
}

5 用户自定义异常类

如何自定义异常类?

  1. 继承与现有的异常结构:RuntimeException、Exception
  2. 提供全局常量序列版本号:serialVersionUID
  3. 提供重载的构造器
public class MyException extends RuntimeException{
	
    static final long serialVersionUID = -7034897193246939L;
        
    public MyException(){
        
    }
    
    public MyException(String msg){
        super(msg);
    }
    
}

6 见解

为什么使用异常处理?

比如:给用户友好方式呈现:一个产品在使用中出现问题,如果没有处理则可能用户会直接在页面看到这些异常,感官非常不好,如果使用异常处理,则可以页面显示“亲,这里出现问题,请之后再访问”,然后后台修改。该改的还是得改

7 练习

public class EcmDef{
	public static void main(String[] args){
        
        try{
            int i = Integer.parseInt(args[0]);
        	int j = Integer.parseInt(args[1]);
            int result = ecm(i,j);
        }catch(EcDef e){
            System.out.println(e.getMessage());
        }catch(NumberFormatExceptionn e){
        	System.out.println("数据类型不一致");
    	}catch(ArrayIndexOutOfBoundsException e){
        	System.out.println("缺少命令行参数");
    	}catch(ArithmeticExceptionn e){
        	System.out.println("除0");
    	}
        
        
    }
    
    public int ecm(int i,int j) throws EcDef{
        if(i < 0 || j < 0){
            throw new EcDef("分子或分母为负数了")
        }
        return i/j;
    }
}

class EcDef extendsextends Exception{
	
    static final long serialVersionUID = -7034897193public EcDef(){
        
    }
    
    public EcDef(String msg){
        super(msg);
    }
    
}

8 面试题

throw和throws的区别?

throw表示抛出一个异常类的对象,生成异常对象的过程。声明在方法体内

throw是属于异常处理的一种方式。声明在方法的声明处

image-20200813173152393

9 总结

image-20200813171449695

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值