黑马程序员——————> 异常处理之修复

------- android培训、java培训、期待与您交流! ----------


java的异常机制主要依赖于try, catch, finally, throw, throws五个关键字,其中try关键字后紧跟一个花括号扩起来的代码块,简称try块,它里面放置可能引发异常的代码。catch后对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块。多个catch块后还可以跟一个finally块,finally块用于回收在try块里打开的物理资源,异常机制会保证finally块总被执行。

throws关键字主要在方法签名中使用,用于声明该方法可能抛出的异常;而throw用于抛出一个实际的异常,throw可以单独作为语句使用,抛出一个具体的异常对象。

java7进一步增强了异常处理机制的功能,包括带资源的try语句,捕获多异常的catch两个新功能,这两个功能可以极好的简化异常处理。

java将异常分为两种,Checked异常和Runtime异常,java认为Checked异常都是可以在编译阶段被处理的异常,所以它强制程序处理所有的Checked异常。而Runtime异常则无须处理。Checked异常可以提醒程序员需要处理所以可能发送的异常。

try
{
   //业务实现代码
}
catch(Exception e)
{
   alert 输入不合法
   goto retry
}

如果执行try块里的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给java运行环境,这个过程被称为抛出异常(throw)

当java运行时环境收到异常对象时,会寻找能处理该异常对象的catch块,如果找到合适的catch块,则会把该异常对象交给该catch块处理,这个过程被称为捕获异常,如果java运行时环境找不到捕获异常的catch块,则运行时环境终止,java程序也将退出。

在java7以前,每个catch块只能捕获一种类型的异常:但从java7开始,一个catch块可以捕获多种类型的异常。使用一个catch块捕获多种类型的异常时需要注意如下两个地方。

1:捕获多种类型的异常时,多种异常类型之间用竖线|隔开。

2: 捕获多种类型的异常时,异常变量有隐式的final修饰,因此程序不能对异常变量重新赋值。

下面程序示范了java7提供的多异常捕获。

public class MultiExceptionTest
{
    public static void main(String[] args)
    {
        try
        {
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            int c = a / b;
            System.out.println("您输入的两个数相除的结果是:" + c );
        }
        catch(IndexOutOfBoundsException|NumberFormatException|ArithmeticException ie)
        {
            System.out.println("程序发生了数组越界,数字格式异常,算数异常之一");
            //捕获多异常时,异常变量默认有final修饰
            //所以下面代码有误
//            ie = new ArithmeticException("test");
        }
        catch(Exception e)
        {
            System.out.println("位置异常");
            //捕获一种类型的异常时,异常变量没有final修饰
            //所以下面的代码完全正确
            e = new RuntimeException("test");
        }

    }

}

访问异常信息:

如果程序需要在catch块中访问异常对象的相关信息,则可以通过访问catch块后的异常形参来获得。当java运行时决定调用某个catch块来处理该异常对象时,会将异常对象赋值给catch块后的异常参数,程序即可通过该参数来获得异常的相关信息。

所有异常对象都包含了如下几个常用方法。

getMessage():返回该异常的详细描述字符串

printStackTrace():将该异常的跟踪栈信息输出到标准错误输出

printStackTrace(PrintStrean s):将该异常的跟踪栈信息输出到指定输出流

getStackTrace():返回该异常的跟踪栈信息

下面程序演示了程序如何访问异常信息

public class AccessExceptionMsg
{
    public static void main(String[] args)
    {
        try
        {
            FileInputStream fis = new FileInputStream("a.txt");
        }
        catch(IOException ioe)
        {
            System.out.println(ioe.getMessage());
            ioe.printStackTrace();
        }

    }

}

上面程序调用了Exception对象的getMessage()方法来的到异常对象的详细信息,也使用了printStackTrace()方法来打印该异常的跟踪信息。

使用finally回收资源

有些时候,程序在try块里打开了些物理资源(例如数据库连接,网络连接和磁盘文件等),这些物理资源都必须显式回收。java的垃圾回收机制不会回收任何物理资源,垃圾回收机制只能回收堆内存中对象所占用的内存。

在哪里回收这些物理资源呢?在try块伦理回收?还是在catch块中进行回收?假设程序try块里进行资源回收,如果try块的某条语句引起了异常,该语句后的其他语句通常不会获得执行的机会,这将导致位于该语句之后的资源回收语句得不到执行。如果在catch块里进行资源回收,但catch块完全有可能得不到执行,这将导致不能及时回收这些物理资源。

为了保证一定能回收try块中打开的物理资源,异常处理机制提供了finally块。不管try块中的代码是否出现异常,也不管哪一个catch块被执行,甚至在try块或catch块中执行例如return语句,finally块总会被执行。完整的java异常处理语法结构如下:

try
{
    //业务实现代码
    ....
}
catch(SubException e)
{
    //异常处理块 1
    ...
}
catch(SubException e)
{
    //异常处理块 2
    ...
}
finally
{
    //资源回收块
    ...
}

异常处理语法结构中只有try块是必需的,也就是说,如果没有try块,则不能有后面的catch块和finally块:catch块和finally块都是可选的,但catch块和finally块至少出现其中之一,也可以同时出现:可以有多个catch块,捕获父类异常的catch块必须位于捕获子类异常的后面:但不能只有try块,既没有catch块,也没有finally块;多个catch块必须位于try块之后,finally块必须位于所有的catch块之后。

除非在try块,catch块中调用了退出虚拟机的方法,否则不管在try块,catch块中执行怎样的代码,出现怎样的情况,异常处理的finally总会被执行。

在通常情况下,不要在finally块中使用如return或throw等导致方法终结的语句,一旦在finally块中使用,将会导致try块,catch块中return,throw语句失效。

异常处理流程代码可以放在任何可执行代码的地方,因此完整的异常处理流程即可放在try块里,也可放在catch块里,还可放在finally块里。

java7的自动关闭资源的try语句

当程序使用finally块关闭资源时,程序会显得异常臃肿。java7允许在try关键字后紧跟一对圆括号,圆括号可以声明,初始化一个或多个资源,此处的资源指的是那些必须在程序结束时显式关闭的资源,try语句在该语句结束时自动关闭这些资源。

为了保证try语句可以正常关闭资源,这些资源实现类必须实现AutoCloseable或Closeable接口,实现这两个接口就必须实现close()方法。

下面程序示范了如何使用自动关闭资源的try语句

 1 public class AutoCloseTest {
 2
 3     public static void main(String[] args) throws IOException
 4     {
 5         try(    //声明,初始化两个可关闭的资源
 6                 //try语句会自动关闭这两个资源
 7                 BufferedReader br = new BufferedReader(new FileReader("AutoCloseTest.java"));
 8
 9                 PrintStream ps = new PrintStream(new FileOutputStream("a.txt")))
10         {
11             //使用两个资源
12             System.out.println(br.readLine());
13             ps.println("庄生晓梦迷蝴蝶");
14         }
15
16
17     }
18
19 }

上面的程序分别初始化了两个IO流,由于BufferedReader PrintStream都实现了Closeable接口,而且它们放在try语句中声明,初始化,所以try语句会自动关闭它们。因此上面程序是安全的。

自动关闭资源的try语句相当于包含了隐式的finally块(这个finally块用于关闭资源),因此这个try语句可以既没有catch块,也没有finally块。当然,如果主程序需要,自动关闭资源的try语句后也可以带多个catch块和一个finally块。

java7几乎把所有的资源类(包括文件IO的各种类,JDBC编程的Connection,Statement等接口)进行了改写,改写后资源类都实现了AutoCloseable或Closeable接口。

时间: 2024-08-08 09:32:53

黑马程序员——————> 异常处理之修复的相关文章

黑马程序员——————> 异常处理之抛出

------- android培训.java培训.期待与您交流! ---------- java的异常被分类为两大类,Checked异常和Runtime异常(运行时异常).所有的RuntimeException类及其子类的实例被称为Runtime异常:不是RuntimeException类及其子类的异常实例则被称为Checked异常. 对于Checked异常的处理方式有如下两种. 1:当前方法明确知道如何处理该异常,程序应该使用try...catch块来捕获该异常,然后在对应的catch块中修复

黑马程序员——IO篇

------- android培训.java培训.期待与您交流! ---------- IO(Input Output)流 1.IO流用来处理设备之间的数据传输 2.Java对数据的操作是通过流的方式 3.Java用于操作流的对象都在IO包中 4.流按操作数据分为两种:字节流与字符流 . 字符流的数据字节流其实都能处理,因为无论什么在计算机上最后都是以字节存在的,但是其中有一部分数据它是以文本形式存在的,所以为了方便有了字符流,字符流里融合了编码表,而只有文字用到了编码表,所以字符流用来处理文本

黑马程序员——【Java高新技术】——代理

一.“代理概述”及“AOP概念” (一)代理概述 1.问题:要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如,异常处理.日志.计算方法的运行时间.事务管理等等,如何去做? 解答:编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码. 2.代理原理图,如下: 3.代理的优点 如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类.还是代理类,这样以后很容易切换.例如,想要日志功能时就

黑马程序员___java断言

----------- android培训.java培训.java学习型技术博客.期待与您交流! --------- 下面介绍一下断言在JAVA中的使用,JAVA是从JDK1.4才开始支持断言的(添加了关键字assert),请注意老版的JRE不支持. 断言概述   编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设  可以将断言看作是异常处理的一种高级形式  断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真  可以在任何时候启用和禁用断言验证,因此可以在测

黑马程序员_Java基础加强(下)

8.注解类 注解相当于一种标记,加了注解就等于打上了某种标记,没加就等于没打特殊标记,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记就去干什么事,标记可以加在包.类.字段.方法,方法的参数以及局部变量上. 注解的应用结构图: 为注解增加属性 定义基本类型的属性和应用属性 在注解类中增加String color(); @MyAnnotation(color = "red") 用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法 MyAnno

黑马程序员——java高新---注解、泛型等

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.注解 什么是注解? 答:对于过时的语句,java会提示过时了,通过@SuppressWarnings("Deprecation")可以在DOS命令行中取消提示,但Eclipse无法取消.这就是注解,相当于标记.编译器.开发工具.javac通过反射获得注解里的内容,进而明确应该做什么.不应该做什么.注解可以加在包.类.属性.方法.参数及局部变量之上.一个注解就是一个类. java.

黑马程序员—张老师基础加强7-动态代理

代理: 要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能. 例如:异常处理,日志和计算方法的运行时间,事物管理等,怎么做 如 在运行前后增加计算时间的方法.show(){ sop(); } 编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码. 动态代理: 要为系统中的各种接口的类增加代理功能,那需要太多代理类. jvm可以在运行期间动态生成出类的字节码,这种动态生成的类往往被调用作代理类, 即动态代理类. jvm生成动态类

黑马程序员_毕向东_Java基础视频教程_Java基础学习知识点总结

黑马程序员_毕向东_Java基础视频教程 Java基础学习知识点总结 2016年01月06日  day01 一.基础知识:软件开发 1.什么是软件?软件:一系列按照特定顺序组织的计算机数据和指令的集合. 2.常见的软件:系统软件:如:DOS,Windows,Linux等.应用软件:如:扫雷,迅雷,QQ等. 3.什么是开发?制作软件. 二.基础知识:人机交互方式 4.软件的出现实现了人与计算机之间的更好的交互. 5.交互方式:图形化界面:这种方式简单直观,使用者易于接受,容易上手操作.命令行方式:

黑马程序员——基础加强篇

------- android培训.java培训.期待与您交流! ---------- MyEclipse相关知识 Workspace与project 切换工作空间:File---Switch Workspace---Other 一个工作间包含多个工程,切换工作间之后,会影响里面的工程,例如快捷键什么的都要重新配置如果重新配了之后快捷键还没有用就要考虑下那个快捷键是不是冲突了    视图管理与程序调试 可以通过Window---Show View来添加各种透视图. 调试程序的时候可以在代码右边双