Java 异常机制:两种异常一错误、异常处理、自定义异常

异常机制


1、两种类型的异常 一个错误

  • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在的文件时,一个异常就发生了,这些异常在运行时不能被简单的忽略。
  • 运行时异常:运行时异常时可能被程序员避免的异常。
  • 错误ERROR:错误不是异常,而是脱离程序员控制的问题。例如栈溢出时,一个错误就发生了,它们在编译也检查不到。

2、异常体系结构

在这里插入图片描述

Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。

AWTError 当发生严重的 Abstract Window Toolkit 错误时,抛出此错误

EOFException 表示在输入过程中意外地到达文件结束或流结束。

ArithemeticException 算数异常

InterruptedException 线程sleep方法的中断异常

UnknownHostException 不知道地址异常

ConnectException 客户端连接异常

IllegalStateException 流被使用了一次,再次使用,就会报该异常

ConcurrentModificationException 并发修改异常

在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Excepton。

面试问题

throwable有几个分支?常见exception有哪些? 见体系图(背住,笔试)

一行代码实现内存溢出?

int[] intArray = new int[1_000_000_000]; // 数组会分配空间,不断扩展内存 OutOfMemoryError

堆栈溢出?

public void test(){ // 无限递归
    test();
} // StackOverflowError 堆栈溢出

3、异常处理5个关键字

抛出异常、捕获异常

try、catch、finally、throw、throws

1)try、catch、finally 捕获异常

public class Test{
    public static void main(String[] args){
        int a = 1;
        int b = 0;
        
        try{ // try异常监控区域
            System.out.println(a/b);
        }catch(ArithmeticException e){ // catch捕获异常并处理异常
            System.out.println("程序出现异常,变量b不能为0");
        }finally{ // 处理善后工作,不管上代码块执不执行,最终都会执行finally里的代码
            System.out.println("finally");
        }
        
        // finally 可以不写,往往是必写的,它的作用是可以关闭IO等资源的关闭!比如如果scanner需要捕获异常,后面有需要关闭scanner流,则需要在finally中进行处理
    }
}
public class Test{
    public static void main(String[] args){
        int a = 1;
        int b = 0;
        
        try{
            System.out.println(a/b);
        }catch(Error e){
            System.out.println("Error");
        }catch(Exception e){
            System.out.println("Exception");
        }catch(Throwable t){
            System.out.println("Throwable");
        }finally{
            System.out.println("finally");
        }
    }
}

可使用多个catch,但是从上至下的捕获类型为以此增大。具体看异常体系结构

2)throw、throws 声明异常

public class Test{
    public static void main(String[] args){
        try{
            new Test.test(1,0);
        }catch(ArithmeticException e){
            // e.printStackTrace(); 打印异常
            System.out.println("程序出现异常,变量b不能为0");
        }
    }
    
    public void test(int a, int b) throws ArithmeticException{
        if( b == 0 ){
            throw new ArithmeticException();
        }
    }
}

throw是方法里语句上使用的抛出异常,throws是在方法上使用的抛出异常。


4、自定义异常

自定义异常继承Exception类就可以了

MyException.java

public class MyException extends Exception{
    private int detail;
    
    public MyException(int a){
        this.detail = a;
    }
    
    @Override
    public String toString(){
        return "MyException{"+detail+"}";
    }
}

Test.java

public class Test{
    public static void main(String[] args){
        try{
            new Test.test(11);
        }catch(MyException e){
            System.out.println(e);
        }
    }
    
    public void test(int a) throws MyException{
        if(a>10){ // 如果值大与10就抛出自定义的异常
            throw new MyException(a);
        }
        System.out.println("OK");
    }
}

// 会输出 MyException{11}

5、实际应用中关于异常的经验总结

  • 处理运行时异常时,采用逻辑去合理规避,同时辅助 try-catch 处理
  • 在多重catch块后面,可以增加一个catch(Exception)来处理可能会被遗漏的异常
  • 对于不确定的代码,也可以加上 try-catch ,处理潜在的异常
  • 尽量去处理异常,切忌只简单地掉用 printStackTrace() 去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
疯狂Java讲义课后题 自己编写的 对于这个程序,最关键的在于判断是否连成5个棋子 一般的棋盘大小为15*15, 用大小为[15][15]的二维数组来盛放棋盘 要判断是否连成5个棋子,就要对棋子的周围进行遍历 这里规定遍历的方式为(左,右),(上,下),(左上,右下),(右上,左下) 4种最特殊的情况:  左上角:只进行右,下,右下  左下角:只进行右,上,右上  右上角:只进行左,下,左下  右下角:只进行左,上,左上 4种特殊情况(不含4个角):  上边界:不进行上遍历  下边界:不进行下遍历  左边界:不进行左遍历  右边界:不进行右遍历 对其他位置的遍历则为(左,右),(上,下),(左上,右下),(右上,左下) 每下一个棋子,都要判断它所处的位置来选择遍历的方式且每次遍历时都要判断是否到达边界,以防数组越界 这样的话,现实起来就会挺复杂 所以改进的方法是这样的: 用大小为[17][17]的二维数组来盛放棋盘 这样就可对每个位置的棋子用相同的遍历方式来遍历,即(左,右),(上,下),(左上,右下),(右上,左下)。并且不需要判断是否到达边界,大大降低了复杂性。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 棋盘为如图所示的那么大。而实际上程序中规定的“棋盘”为中间的部分(即棋子只能摆在从1-15的位置上,否则会被程序告知摆放的位置不对),这样一来,不管棋子位于“棋盘”中的哪个位置,都可以采用(左,右),(上,下),(左上,右下),(右上,左下)的方式遍历而不会发生数组越界的错误,且无需判断是否到达边界。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值