Android里的常见异常

来源:互联网 发布:嵌入式算不算人工智能 编辑:程序博客网 时间:2024/05/01 22:24
 

异常概述

1 什么叫异常

l 编译错误:不能生成class文件;编译期异常!

l 异常:运行class时出现错误。

2 谁能产生异常

  方法,即行为!只有行为能异常,数据不能自己就异常!

3 异常是方法返回的另一个途径

  调用一个方法,有两种可能:要么正确的返回预期的值;要么返回一个异常类的对象!

4 异常的分类

异常类的祖先:Throwable

Throwable有两个子类:ErrorException

ExceptionRuntimeException以及其子类(都是不受检查),以及非RuntimeException(受检查)

5 异常涉及的关键字

  throw(抛出)、throws(声明)、try(监控区)、catch(捕获)、finally(总是执行)

声明异常

声明异常需要使用throws关键字!

给谁声明?当然是方法了!

什么叫声明异常?说这个定义的方法有可能出现异常!

1 声明异常的语法

public void fun() throws 异常名称1,异常名称2 {

}

声明异常:声明多个异常,最好不要有继承关系!

限制:当子类重写父类方法时,异常不能声明父类方法没有声明的异常!也就是说,父类给出了一个异常的范围,子类不能出格!

上面说的都是受检查的!

2 声明异常的方法说明什么

  声明异常的方法说明这个方法有可能返回一个正常的值(返回值类型一样),或者返回一个声明的异常类型的对象!

3 调用声明异常的方法

l 对受检查异常而言只有两条路可选

l 对不受检查的异常而言就无所谓了

4main也可以声明异常

  main可不可以声明异常?可以!main要是出了异常,这个异常就给了JVM了,JVM怎么处理呢?终止程序的运行!打印异常调用栈!

抛出异常

一些运算会出异常:10 / 0,就会出现异常!

调用了一个出现异常的方法:你调用的方法它出现了异常,至于它内部怎么出的你不用管!

手动抛出:使用关键字throw手动抛出一个异常!

class TryException{public static void main(String[] args){try{int n = fun(10,1);//如果该语句不异常,则输出n;System.out.println(n);}catch (Exception e){//抓住异常,并处理System.out.println("异常已处理");}}//把异常信息声明出去,给调用者处理的机会public static int fun(int a,int b)throws Exception{ //该程序可能会有异常return a/b; //返回a/b的值}}


1 调用声明异常的方法

l 当调用一个声明了异常的方法时,说明你这个方法也有可能出这异常!这说明你需要给这个方法声明一下异常!编译器要求受检查的异常这样来做,对不受检查的它装没看见!

2 调用了没有声明异常的方法(抛出不受查检的异常)

在一个没有声明异常的方法中,可以抛出不受查检的异常。

一个没有抛出异常语句的方法中,可以声明异常!

抛出异常的限制

1 抛出不受查检的异常没有限制

一个方法没有声明异常,但也可以抛出不受检查的异常!

一个方法没有声明异常,不可以抛出受检查的异常!

2 在声明了异常的方法中抛出异常

在声明了异常的方法中可以抛出异常!但要对应!!!

你的方法声明了SQLException,但你抛出的是IOException,这是不行的!还是在欺骗!

3 在try中抛出异常,有对应的catch捕获
class Test{public static void main(String[] args)throws Exception{fun();}public static void fun() throws Exception{//当成受检查异常看待!try{throw new IOException();//抛出一个IO类型异常}catch(IOException ex){System.out.println("这里出理了IO异常");//这里处理的是IOException类型的异常}catch(RuntimeException ex){//这里处理的是RuntimeException}}}


说明:

l 方法内抛出受检查异常,那么你的方法就需要声明这个受检查异常。(也可以处理了它)

l 如果你的方法调用了一个声明受检查异常的方法时,那么说明你这个方法也存在危险!你这个方法也需要声明这个受检查异常。例如一个方法声明了Exception,因为Exception包含了受检查异常,所以调用这个方法的方法,也需要声明Exception


2 可以有多个catch

l 多个catch的语法:多个catch中间不能有其它的代码!

l 多个catch处理的异常类型不能相同;

l 多个catch处理的异常类型存在继承关系时,子类在上,父类在下。

l catch处理的异常类型,如果在try中不可能存在,那么编译器就要看你受不受查检了,如果受,那么编译出错!

3catch中异常类型是受检查异常(不包括Exception)时

Exception比较特殊,他包含了受检查和不受检查,当throws时,编译器把它当成受查检;

当在catch中处理Exception时,编译器把它当着不受检查。

4try中不能抛出catch中没有捕获的异常(不受查检的可以)

  Try中如果没有出现任何IOExcepiton的语句,那么catch就不能处理IOException。当然不受查检的异常编译器不管。

5catch中可以抛出异常,但需要在方法上声明

  Catch中也可以使用throw语句,但catch不在try中,也就不受监控,在catch中使用throw语句就直接返回异常了。

总是执行

1 只有finllay中的代码总是执行

finally块中放必须要执行的代码:例如关闭IO流的连接,还有数据库的连接,网络的连接!

finally块的特点:肯定会执行!

2 至上而下,到finllay开始执行

  当方法内在执行finally之间,没有返回的语句(抛出异常返回和return返回),那么finally会很安静的等待到他来执行。

3 在执行finllay之前,方法要返回(异常返回和return返回)

  当方法内在执行finally之间,存在返回的语句(抛出异常返回和return返回),那么finally会插队来执行。就是在你返回之前那一瞬间,finllay会先来执行,然后再让你返回!

4 如果在finally中返回

    当finally插队执行时(这是因为之前有返回语句才会插队执行),如果finllay中存在返回语句(抛出异常返回和return返回),那么原来的返回语句就无效了!

5 当finally插入执行

finally插队执行时,finllay中如果使用了局部变量,那么局部变量都在finally块中有自己的一份拷贝!例如:

int fun() {

    int i = 1;

try {

   if(true) {

    return I;

}

} catch(RuntimeException e) {

} fainlly {

    i++;

}

}

上面代码中,finally块中的i,已经不在是局部变量i,而是在finally块执行之前,在finally块中已经创建了一个新的变量,它的值是由局部变量i拷贝过来的!所以finally块的中变量自增,不会影响到局部变量i

常见异常

1 OutOfMemoryError(内存溢出错误)

  当创建一个特别大的数组时,因为堆区没空间了,才会出现这个Error

2 StackOverflowError(调用栈溢出错误)

当调用栈中的方法太多了,一直压啊~~~,没有出栈的,就出现了这个Error

例如无限递归调用!

3 NoSuchMethodError(没有这个方法错误)

当调用一个方法时,而这个方法已经不在存在了,才会出现这个问题!

例如你运行一个没有main的类时,就会出现这个问题。

4 NoClassDefFoundError(没有找到类错误)

  当一个类使用另一个类时,而要使用的这个类已经不存在了,那么就会出现这个Error

5 ArithmeticException(算术异常)

  算术异常,因为整数除以0时就会引发!一般就是这个能引发,其它还真不知道!

6 ArrayIndexOutOfBoundsException(数组下标越界异常)

当给出一个错误的下标时会出现这个异常!

数组下标的范围是:0 ~ arr.length - 1

7ClassCastException

当强制类型转换失败时,出现这个异常!

向下转型的前提是向上转型。如果没有向上转型,就不可能向下转型!

Person p = new Person();

Student s = (Student)p;//出现错误!

Person p = new Student();

Student s = (Student)p;

Person p = new Teacher();

Student s = (Person)p;//出现错误!

8IllegalArgumentException

表示向方法传递了一个不正确的参数!

setAge(int age)

当调用setAge()方法时,给了一个200,或者是-100,都应该抛出这个异常!

我们叫它为:非法参数异常!

Integer.parseInt(String);//传递一个”abc”就出现这个异常!

我们定义一个方法,无法去要求类型不int,而且范围为18~100,这是做不到的,也只能在方法内自己写if()语句来判断,如果判断为错误,我们就用抛出异常的手段来告诉调用者,这样是错误的!

9NullPointerException

当调用一个null时,我们叫使用一个null时会出现这个异常!

String s = null;//没有编译错误,运行也没有问题。

s.length();//出错了,什么异常呢?NullPointerException!

给引用赋值为null没有错,但使用null就出这个异常!

放心吧,你总有一天会让它给你害了的!

出了这个错,先找到谁null,然后看看它为什么null了。

Throwable

1String getMessage()

  异常类都有一个Message属性,可以设置,也可以使用本方法来获取!

2String toString()

  异常类的名称:异常的信息

3void printStackTrace()

  把异常调用栈信息打印到控制台(标准错误流)上!

4Throwable getCause()

获取起因!起因是另一个异常类的对象!

异常类允许我们指定一个起因,这种方式可以帮助我们转换异常的类型!

甚至把受检查异常可以转换成不受检查的异常。当然,反之也行!

5Throwable initCause()

设置当前异常对象的起因!

起因如果为自己,可以设置起因,如果起因不是自己,那么就不能处置,硬设置会抛出异常!

自定义异常

l 异常类之间最大的区别是什么:类名称!

l 同一类型的异常对象的最大区别是什么:信息!!!

给自己的异常类起个好名字

创建异常对象,要给个好信息!

1 从Exception或其子类派生自定义异常

我们的异常类,应该从Exception或是其子类开始继承!

2 给异常类起个好名字

  通过名字就知道自己哪里出现了错误!

3 给出与Exception一样参数的四个构造器

(String msg, Throwable)

()

(String)

(Throwable)

一个方法都不用写!

4 在适当的时候使用异常类

If(!stack.empty()) {

   Stack.pop(“xxx”);

}

try {

    stack.pop();

} catch(Exception e) {

}

try/catch会使你的程序慢下来,而且你的程序可读性也很差!