异常

概念
异常:程序在运行时出现不正常的情况
由来
问题也就是现实生活中的一个具体事物,也可以通过JAV类的形式进行描述,并封装成对象,其实就是JAVA对不正常情况描述后的对象体现
分类
可处理:Exception
运行时异常(unchecked exception):一般可以通过针对的处理方式进行处理,程序员完全可以根据自己的经验,提前预判会不会出问题
非运行时异常【检查异常】(checked exception):程序员能够对其作出处理
不可处理:Error
一般不编写针对性的代码进行处理
Throwable
  Throwable 类是 Java 语言中所有错误或异常的超类[父类]
异常的处理
异常分为2种
1.编译时被检测的异常
2.编译时不被检测的异常(运行时异常RuntimeException以及其子类)
<---检查异常[checked]:需要我们人为的去处理--->
技巧:如果程序出现异常,我们应该怎么去观察
错误的堆栈信息(先进后出),一般我们调用类的信息都在下面,就找认识的
示例

处理方法
  <-------捕获异常------->
            我有一辆车,车的杀出有点不好使,假如别人来借我的车,我需要把这个消息告诉他,他发现问题有点麻烦,直接自己就处理了
            别人在使用这个车的时候就没有刹车的问题
代码格式一
1 try【进行捕获】 2 { 3 可能出现异常的代码 4 }catch(异常类 变量){ 5 具体处理方法 6 }catch(异常类 变量){ 7 具体处理方法 8 }
示例代码
1 public class Exam { 2 public static void main(String[] args) { 3 test(); 4 } 5 6 public static void test() { 7 try { 8 InputStream inputStream = new FileInputStream(""); 9 } catch (FileNotFoundException e) { 10 System.out.println("Exam.test(我是catch)"); //Exam.test(我是catch) 11 } 12 13 }
代码格式二
1 try【进行捕获】 2 { 3 可能出现异常的代码 4 }catch(异常类 对象){ 5 具体处理方法 6 }catch(异常类 对象){ 7 具体处理方法 8 }finally{ 9 10 }
示例代码
1 public class Exam { 2 public static void main(String[] args) { 3 test(); 4 } 5 6 public static void test() { 7 try { 8 InputStream inputStream = new FileInputStream(""); 9 } catch (FileNotFoundException e) { 10 System.out.println("Exam.test(我是catch)"); //Exam.test(我是catch) 11 }finally { 12 13 } 14 15 } 16 }
注意:catch异常的时候 一定将父类/大的的异常放在后面,精确的异常放在前面【Exception异常最大】
代码格式三
注意:catch是用于处理异常,如果没有catch就代表没有被处理过,如果该异常是检测时异常,那么必须声明
1 try【进行捕获】 2 { 3 可能出现异常的代码 4 }finally{ 5 6 }
示例代码
1 public class FinallyDemo { 2 private static int a; 3 private static int b; 4 5 public static void main(String[] args) { 6 demo(4,1); 7 } 8 9 public static void demo(int a,int b) { 10 11 try { 12 int c = a / b; 13 System.out.println(c); //4 14 15 } finally { 16 System.out.println("我是一定执行的"); //我是一定执行的 17 } 18 } 19 }
运行机制
try里面代码一旦有一行出现异常,try里面的代码都不会被执行,而且只会执行一个catch,不会所有的都执行
但是try大括号后面的代码还是会继续执行【catch,finally】
1 public class Exam { 2 public static void main(String[] args) { 3 testTryCatchFinally(); 4 5 6 } 7 8 public static void testTryCatchFinally() { 9 try { 10 System.out.println("ABC"); //ABC① 11 int a = 1 / 0; //③ 出现异常 12 InputStream inputStream = new FileInputStream(""); 13 } catch (FileNotFoundException e) { 14 System.out.println("HelloTry.testTryCatchFinally(我是catch)"); 15 } catch (IOException e) { 16 e.printStackTrace(); 17 } finally { 18 System.out.println("我是finally"); //② 19 } 20 } 21 22 }

关键字try不能单独存在,后面必须跟catch或者finally
顺序是 try{} [catch] [finally]
执行的顺序是 try catch finally
对捕获的异常对象进行常见方法操作
1.String Message //异常信息
2.String toString //异常名称:异常信息
3.printStackTrace /*异常名称:异常信息
异常位置*/
注意:其实JVM默认的处理机制,就是在调用printStackTrace 方法,打印堆栈的跟踪信息
示例代码
1 public class ExceptionDemo1 { 2 public static void main(String[] args) { 3 Demo demo = new Demo(); 4 5 try { 6 int x = demo.demo1(4, 0); 7 System.out.println(x); 8 } catch (Exception e) { 9 System.out.println(e.getMessage()); /// by zero 10 System.out.println(e.toString()); // java.lang.ArithmeticException: / by zero 11 12 e.printStackTrace(); 13 /* 14 * java.lang.ArithmeticException: / by zero at 15 * com.wcy.Exception.Demo.demo1(ExceptionDemo1.java:25) at 16 * com.wcy.Exception.ExceptionDemo1.main(ExceptionDemo1.java:8) 17 */ 18 19 } 20 21 } 22 23 } 24 25 class Demo { 26 int demo1(int a, int b) { 27 return a / b; 28 } 29 }
对异常的声明
throws:在功能上通过throws关键字声明了该功能有可能会出现问题
注意:最后一次抛出异常,是将异常抛给虚拟机[JVM]的
示例代码
1 public class ExceptionDemo1 { 2 public static void main(String[] args) throws Exception { 3 Demo demo = new Demo(); 4 5 int x = demo.demo1(4, 0); 6 System.out.println(x); 7 8 } 9 10 } 11 12 class Demo { 13 int demo1(int a, int b)throws Exception {//在功能上通过throws关键字声明了该功能有可能会出现问题 14 return a / b; 15 } 16 }
对多异常的操作
1.在声明异常时,建议声明更为具体的异常,这样处理起来更具体
2.对方声明几个异常,就应该有几个catch块,不要定义多余的catch块
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
建议:在进行catch处理时,catch中一定要定义具体的处理方式
不要简单的定义一句 e.printStackThrac()
也不要简单的就书写一条输出语句
3.异常在子父类覆盖中的体现
(1)子类在覆盖父类时,如果父类方法抛出异常,那么子类覆盖方法,只能抛出父类的异常或者该异常的子类
(2)如果父类方法抛出多个异常,那么子类在覆盖方法时,只能抛出父类异常的子类
(3)如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法是也不可以抛出异常,如果子类方法发生了异常就必须进行try...catch处理,一定不能抛
(4)总结说明:
在继承中,重写方法的时候,子类的异常要小于等于父类的异常
如果子类的异常大于父类的异常那么会导致多态无法运行
只能try抓到这个异常
抛出异常的时候,尽量不要抛有父子关系的,如果有父子关系,直接抛出一个父类异常就可以了
示例代码
子父类关系
AException
—BException
CException
1 public class FuziExceptionDemo { 2 public static void main(String[] args) throws CException, AException { 3 Demo demo = new Demo(); 4 demo.function(new Fu()); 5 6 } 7 } 8 9 class AException extends Exception { 10 public AException() { 11 System.out.println("我是A异常"); 12 } 13 } 14 15 class BException extends AException { 16 public BException() { 17 System.out.println("我是B异常"); 18 } 19 } 20 21 class CException extends Exception { 22 public CException() { 23 System.out.println("我是C异常"); 24 } 25 } 26 27 class Fu { 28 public void test1() throws AException { 29 throw new AException(); 30 } 31 } 32 33 class Zi extends Fu { 34 public void test2() throws CException { 35 throw new CException(); 36 } 37 } 38 39 class Demo { 40 public void function(Fu fu) throws AException { 41 try { 42 fu.test1(); 43 } catch (AException e) { 44 45 } 46 /* 47 * catch (BException e) { } 48 */ 49 50 catch (CException e) { 51 52 } 53 54 } 55 }
视图

finally
特性
1.定义一定执行的代码
2.通常用来执行关闭资源操作
      finally的特性是无论try中的语句是否有问题,finally里的内容都会输出,只有四种情况时finally里的内容不会执行输出,当有return出现时,也是先执行finally再执行return,而且当有多个return是会输出最后面的return
示例代码
1 public class Exam { 2 public static void main(String[] args) { 3 System.out.println(testReturn()); 4 5 } 6 public static int testReturn() { 7 try { 8 System.out.println("我是try"); //我是try 9 int a = 1 / 0; 10 return 1; 11 } catch (Exception e) { 12 System.out.println("我是catch"); //我是catch 13 return 2; //2 14 } finally { 15 System.out.println("我是finally"); //我是finally 16 // return 3; // //3 17 } 18 // return 4; // // //4 19 // System.out.println("HelloTry.testReturn(我是程序之外的代码)"); 20 } 21 }
不执行finally的情况
  1)在finally语句块中发生了异常。
			  2)在前面的代码中用了System.exit()退出程序。
			  3)程序所在的线程死亡。
			  4)关闭CPU。
            <-------抛出异常------->
              我有一辆车,车的刹车有点不好使,假如别人来借我的车,我需要把这个消息告诉他,那么他也需要注意刹车的问题
示例代码
1 public class Exam { 2 public static void main(String[] args) throws FileNotFoundException { 3 test(); 4 } 5 6 public static void test() throws FileNotFoundException { 7 8 InputStream inputStream = new FileInputStream(""); 9 } 10 }
<---非检查异常[运行时异常][RuntimeException]--->
特性
在Exception中有一个特殊的子类异常RuntimeException[运行时异常]
如果在函数内抛出该异常,函数上可以不用声明,编译一样通过
如果在函数上声明了该异常,调用者可以不用进行处理[try...catch或者throws],编译一样通过
之所以不用在函数上声明,是因为不需要让调用者处理
当异常发生时,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码进行修正
自定义异常时,如果该异常的发生,无法再继续进行运算,那就让自定义异常继承RuntimeException
示例代码
1 public class RuntimeExceptionDemo { 2 //调用者不用处理就可以 3 public static void main(String[] args) { 4 Test test=new Test(); 5 test.demo(4, -1); 6 7 } 8 } 9 10 class ArithmeticException extends RuntimeException{ 11 12 13 public ArithmeticException() { 14 System.out.println("出现负数异常"); 15 } 16 } 17 18 class Test{ 19 public int demo(int a,int b)throws ArithmeticException { 20 int c=a/b; 21 if (b<0) { 22 throw new ArithmeticException(); 23 } 24 25 System.out.println(c); 26 return c; 27 28 } 29 }
视图

比较常见的运行时异常
java.lang.ArithmeticException【算术运算中,被0除或模除】
 1 public class Exam {
 2     public static void main(String[] args) throws Exception {
 3         test();
 4     }
 5     
 6     private static void test() {
 7         int a=10;
 8         int b=0;
 9         System.out.println(a/b);
10     }
11     
12 }
 
java.lang.NullPointerException【空指针异常】
 1 public class Exam {
 2     public static void main(String[] args) throws Exception {
 3         test();
 4     }
 5     
 6     private static void test() {
 7         String aString=null;
 8         System.out.println(aString.length());
 9     }
10     
11 }

java.lang.ClassCastException【类转换异常】
 1 public class Exam {
 2     public static void main(String[] args) throws Exception {
 3         
 4     }
 5     
 6     private static void test() {
 7         Student student = (Student) new Object();
 8     }
 9     
10 }
java.lang.ArrayIndexOutOfBoundsException【数组角标越界异常】
java.lang.StringIndexOutOfBoundsException【字符串角标越界异常】
 1 public class Exam {
 2     public static void main(String[] args) throws Exception {
 3         test();
 4     }
 5     
 6     private static void test() {
 7         int[] nums = new int[10];
 8         System.out.println(nums[10]);
 9     }
10     
11 }

java.lang.NumberFormatException【数字格式异常】
数字格式异常,例如提示 For input string: "1 " 提示,这就告诉我们你当前想把 "1 " 转换成数字类型时出错了
 1 public class Exam {
 2     public static void main(String[] args) throws Exception {
 3         test();
 4     }
 5     
 6     private static void test() {
 7         String str = "10a";
 8         System.out.println(Integer.parseInt(str));
 9     }
10     
11 }

java.lang.InputMismatchException 【输入类型不符合异常】
获取的标记与期望类型的模式不匹配,或者该标记超出期望类型的范围
示例代码
1 import java.util.Scanner; 2 3 public class ExceptionNoclass { 4 public static void main(String[] args) { 5 System.out.println("输入一个数据"); 6 Scanner scanner=new Scanner(System.in); 7 scanner.nextInt(); 8 } 9 }
视图

自定义异常
因为项目中会出现一些特有的问题,而这些问题并没有被JAVA所描述并封装对象,所以对这些特有的问题可以按照JAV对问题封装的思想,将特有的问题进行自定义的异常封装
示例代码
1 class MyselfExceptionDemo extends Exception{
2     
3 }
当函数内部出现throw抛出异常对象,那么就必须要给对应的处理动作
要么在内部用try...catch处理
要么在函数上声明,让调用者处理
一般情况下,函数内出现异常,函数上需要声明
抛出异常代码
 1 public class MyselfException {
 2     public static void main(String[] args) {
 3         TestDemo testDemo = new TestDemo();
 4         try {
 5             testDemo.test(4, -1);
 6         } catch (MyselfExceptionDemo e) {
 7             System.out.println(e.toString()); // com.wcy.Exception.MyselfExceptionDemo
 8         }
 9     }
10 }
11 
12 class MyselfExceptionDemo extends Exception {
13 
14 }
15 
16 class TestDemo {
17 
18     public int test(int a, int b) throws MyselfExceptionDemo {
19         int c = a / b;
20 
21         if (b < 0) {
22             throw new MyselfExceptionDemo(); // 抛出自定义异常
23         }
24 
25         System.out.println(c);
26         return c;
27     }
28 
29 }
无异常正常运行代码
 1 public class MyselfException {
 2     public static void main(String[] args) {
 3         TestDemo testDemo = new TestDemo();
 4         try {
 5             testDemo.test(4, 1);  //4
 6         } catch (MyselfExceptionDemo e) {
 7             System.out.println(e.toString()); 
 8         }
 9     }
10 }
11 
12 class MyselfExceptionDemo extends Exception {
13 
14 }
15 
16 class TestDemo {
17 
18     public int test(int a, int b) throws MyselfExceptionDemo {
19         int c = a / b;
20 
21         if (b < 0) {
22             throw new MyselfExceptionDemo(); // 抛出自定义异常
23         }
24 
25         System.out.println(c);
26         return c;
27     }
28 
29 } 
误区:
打印的结果中只有异常的名称,没有异常的信息?
因为打印的异常没有定义信息
如何定义异常信息?
因为父类已经把异常信息的操作完成了,所以只需要子类在构造时[构造方法/构造器],将异常信息传递给父类,用super()传递
那么传递之后,就可以用getMessage()方法,获取自定义的异常信息了
为什么说父类已经把异常信息定义操作都完成了?
    因为Exception继承自Throwable,在Throwable类中,早已经定义好了设定自定义异常信息的方法(Throwable(String message)),并且是构造方法。由于Exception继承自Throwable,是Throwable的一个分支,并且默认构造方法中有(Exception(String message))这个方法,自定义异常类继承自Exception,所以自定义异常类可以直接调用这个父类的构造器方法,所以在使用时只需要直接调用就可以了,方法是在构造器中用super()调用
为什么要继承Exception?
因为异常体系有一个特点:异常类和异常对象都被抛出,他们都具备可抛性,这个可抛性是Throwable这个体系中特有的。只有这个体系中的类和对象才可以被throws和throw操作抛出
自定义异常可不可以继承别的类?
自定义异常可以继承Exception也可以继承RuntimeException,但是继承Exception时一定要进行(try...catch或throws处理),继承RuntimeException[运行时异常]则不需要进行处理,这个是RuntimeException类以及其子类特有的属性
关联阅读
  构造器能不能够继承?
不能,因为子类继承父类的时候,先运行父类构造函数;具体的说就是运行父类时就会先“调用”父类的构造函数,注意“调用”和继承不是一个含义,实质上是“自动运行”。
简单的理解就是因为构造器得名字和类名相同所以比如说B继承A,那么A得构造器是A(),但是B得构造器是B(),所以A()不能是B得构造器
继承(extends)的含义其实是“扩展”,子类完全没必要扩展父类的构造函数,因为反正每次调子类的时候都会“自动运行”它父类的构造函数,如果真的需要子类构造函数特殊的形式,子类直接修改或重载自己的构造函数就好了。
示例代码
 1 public class MyselfException {
 2     public static void main(String[] args) throws MyselfExceptionDemo {
 3         Test test=new Test();
 4         test.demo(4, -1);
 5     }
 6 }
 7 
 8 class MyselfExceptionDemo extends Exception{
 9     public MyselfExceptionDemo(String message) {
10         super(message);
11     }
12 }
13 
14 class Test{
15     public int demo(int a,int b) throws MyselfExceptionDemo {
16         int c=a/b;
17         if(b<0){
18             throw new MyselfExceptionDemo("出现了除数为负数额异常");//com.wcy.Exception.MyselfExceptionDemo: 出现了除数为负数额异常
19         }
20         
21         
22         return c;
23     }
24 }
throw和throws的区别?
1.throws使用在函数上(大括号和小括号之间)
throw使用在函数内
2.throws后面跟的是异常类,可以跟多个,用逗号隔开
throw后面跟的是异常对象
示例代码
 1 class Test{                        //函数上(小括号和大括号之间)后面跟的是异常类,可以跟多个,用逗号隔开
 2     public int demo(int a,int b) throws MyselfExceptionDemo {
 3         int c=a/b;
 4         if(b<0){
 5             //函数内 后面跟的是异常对象
 6             throw new MyselfExceptionDemo("出现了除数为负数额异常");
 7         }
 8         
 9         
10         return c;
11     }
12 }
                    
                

                
            
        
浙公网安备 33010602011771号