1. 正确关闭资源
- 开发中打开的一些物理资源,必须显示进行关闭。Java回收机制是内存管理的一部分,只能对堆内存回收,对程序中打开的物理资源无能为力。必须进行显式关闭资源
2. finally
- 不论try块是正常结束,还是中途非正常退出,即使其包含return语句,finally块都会执行
- 但是碰到System.exit(0)时呢?System.exit(0)将停止当前线程和所有其他当场死亡的线程。finally块不能使已经停止的线程继续执行,因此,其中的方法就得不到执行
- 那么遇到System.exit(0)应该怎么关闭资源呢?
- 注册关闭钩子,因为System.exit(0)被调用时,虚拟机退出前要执行清理工作:执行系统中注册的所有关闭钩子
public class ExitHook { public static void main(String[] args) throws IOException { final FileOutputStream fos; fos = new FileOutputStream("a.bin"); System.out.println("打开物理资源"); Runtime.getRuntime().addShutdownHook(new Thread(){ public void run() { if (fos != null) { try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("关闭了物理资源"); } }); // 退出程序 System.exit(0); } }
关闭钩子负责在程序退出时回收系统的资源
- 注册关闭钩子,因为System.exit(0)被调用时,虚拟机退出前要执行清理工作:执行系统中注册的所有关闭钩子
- 只要Java虚拟机不退出,不管try块正常结束,还是遇到异常非正常退出,finally块总会获得执行机会
- 当Java程序try、catch块中遇到了return语句时,并不会立即执行该语句,而是:去寻找异常处理流程中是否包含finally块,若无,方法执行return结束;若有,开始执行finally块,当finally块执行完后,调回去执行return语句结束,如果finally块中含有return语句,则直接在finally块中结束方法,不会再跳回去执行try块中的return语句
- 当Java程序try、catch块中遇到了throw语句时,并不会立即执行该语句,抛出异常,而是:去寻找异常处理流程中是否包含finally块,若无,方法执行throw抛出异常;若有,开始执行finally块,当finally块执行完后,调回去执行throw抛出异常,如果finally块中含有return语句,则直接在finally块中结束方法,不会再跳回去执行try块中的throw抛出异常
3. catch块
- 对Java的异常捕捉,每个try至少 需要 一个 catch或者finally块
- 异常捕获时,先捕获小异常,再捕获大异常
- 不要用异常来进行流程控制:难以阅读、运行速度慢。异常是为捕获异常而存在的,不能用其进行流程控制
- 只可以捕获可能抛出的异常
- 可以在任意想捕获异常的地方捕获RuntimeException异常、Exception异常,但是对于其他checked异常(Exception异常是个另类),只有当可能抛出该类异常时才能 捕获,否则编译错误
- 实际修复
- 方法知道怎么修复异常,try...catch
- 方法不知道怎么修复,抛出
- 在catch块中不进行修复又调用抛出异常的该方法,造成无线递归,StackOverflowError
- 无论如何不要在finally块中调用可能引起异常的方法,这将导致该方法的异常不能被正常抛出,甚至StackOverflowError错误也不能终止程序,只能采用强行结束进程
4.继承得到的异常
- 子类重写父类父类的方法,不能声明抛出比父类类型更多、范围更大的异常。也就是说只能抛出其子类、相同的、或者不抛出
- 实现接口中的方法时抛出异常要求同上。当是实现多个接口时,多个接口若有相同的方法,在实现该方法时,抛出的异常只能是多个接口分别可以抛出的异常类型的交集,即必须满足每个接口的要求。(方法不抛出异常,肯定是其的一个交集)