文章目录
异常机制
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语句块去释放占用的资源