异常的处理和自定义
异常:异常就是Java程序在运行过程中出现的错误
异常由来:问题也是现实生活中一个具体事务,也可以通过java 的类的形式进行描述,并封装成对象。
其实就是Java对不正常情况进行描述后的对象体现。 我们见过的异常,角标越界异常,空指针异常
异常分类
异常的处理: jvm发现运算是已经违反了数学运算规则,java将这种常见的问题进行描述,并封装成了对象叫做ArithmeticException 当除0运算发生后,jvm将该问题打包成了一个异常对象. 并将对象抛给调用者main函数,new ArithmeticException("/by zero"); main函数收到这个问题时,有两种处理方式:
1,自己将该问题处理,然后继续运行
2,自己没有针对的处理方式,只有交 给调用main的jvm来处理 jvm有一个默认的异常处理机制,就将该异常进行处理.并将该异常的名称,异常的信息.异常出现的位置打印在了控制台上 同时将程序停止运行
常见的异常处理方式,代码如下:
try{}...catch(){}方法
1 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.text.ParseException; 7 import java.text.SimpleDateFormat; 8 9 /* 10 * JVM默认处理异常的方式: 11 * 终止程序 12 * 将异常的错误信息打印到控制台 13 * 14 * 自己的处理方式: 15 * try{ 16 * 可能会发送异常的代码; 17 * }catch(异常的类名 对象名){ 18 * 处理方式; 19 * } 20 * 21 * 运行时期异常的处理方案: 22 * 更改代码(更常用) 23 * 使用具体的语句进行处理 24 * 编译时期异常:只能使用具体的语句进行处理 25 */ 26 public class ExceptionDemo2 { 27 public static void main(String[] args) { 28 test5(); 29 System.out.println("over"); 30 } 31 //开发中的一般处理方式 32 private static void test5() { 33 try { 34 int i = 1 / 0; 35 new SimpleDateFormat().parse(""); 36 new FileInputStream(new File("")); 37 } catch (Exception e) { 38 // System.out.println("除数为零了"); 39 e.printStackTrace(); 40 } 41 } 42 43 //JDK1.7新特性:异常1|异常2|... 44 private static void test4() { 45 try { 46 int i = 1 / 0; 47 new SimpleDateFormat().parse(""); 48 new FileInputStream(new File("")); 49 } catch (ArithmeticException|ParseException|FileNotFoundException e) { 50 // System.out.println("除数为零了"); 51 e.printStackTrace(); 52 } 53 } 54 55 //异常中存在子父类关系时,父类的异常捕获必须放在最后面的位置 56 private static void test3() { 57 try { 58 int i = 1 / 0; 59 new SimpleDateFormat().parse(""); 60 new FileInputStream(new File("")); 61 } catch (ArithmeticException e) { 62 // System.out.println("除数为零了"); 63 e.printStackTrace(); 64 }catch (ParseException e) { 65 // System.out.println("要解析的文本日期格式不正确"); 66 e.printStackTrace(); 67 }catch (Exception e) {//其余的任何异常,我都可以捕获 68 e.printStackTrace(); 69 } 70 } 71 72 //异常合并处理 73 private static void test2() { 74 try { 75 int i = 1 / 0; 76 new SimpleDateFormat().parse(""); 77 } catch (ArithmeticException e) { 78 // System.out.println("除数为零了"); 79 e.printStackTrace(); 80 }catch (ParseException e) { 81 // System.out.println("要解析的文本日期格式不正确"); 82 e.printStackTrace(); 83 } 84 } 85 86 //异常单独处理 87 private static void test() { 88 try { 89 int i = 1 / 0; 90 } catch (ArithmeticException e) { 91 // System.out.println("除数为零了"); 92 e.printStackTrace(); 93 } 94 try { 95 new SimpleDateFormat().parse(""); 96 } catch (ParseException e) { 97 // System.out.println("要解析的文本日期格式不正确"); 98 e.printStackTrace(); 99 } 100 } 101 }
Throwable中的方法:
getMessage() 获取异常信息,返回字符串。
toString() 获取异常类名和异常信息,返回字符串。
printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。
printStackTrace(PrintStream s) 通常用该方法将异常内容保存在日志文件中,以便查阅
1 import java.io.PrintWriter; 2 import java.text.SimpleDateFormat; 3 import java.util.Date; 4 5 public class ExceptionDemo3 { 6 public static void main(String[] args) { 7 try { 8 System.out.println(new SimpleDateFormat().format(new Date())); 9 new SimpleDateFormat().parse("18-1-15 上午9:45"); 10 int i = 1 / 0; 11 } catch (Exception e) { 12 // public String getMessage()返回此 throwable 的详细消息字符串 13 //System.out.println(e.getMessage());/// by zero 14 15 //public String toString()返回此 throwable 的简短描述 16 //System.out.println(e.toString());//java.lang.ArithmeticException: / by zero 17 18 //public void printStackTrace()将此 throwable 及其追踪输出至标准错误流 19 e.printStackTrace(); 20 21 //public void printStackTrace(PrintWriter s)将此 throwable 及其追踪输出到指定的 PrintWriter 22 //PrintWriter可以将字符串输出到一个文件中 23 try { 24 PrintWriter pw = new PrintWriter("D:/error.txt"); 25 e.printStackTrace(pw); 26 pw.close(); 27 } catch (Exception e1) { 28 e1.printStackTrace(); 29 } 30 } 31 System.out.println("over"); 32 } 33 }
编译时异常和运行时异常的区别:
java中的异常被分为两大类:编译时异常和运行时异常。
所有的RuntimeException类及其子类的实例被称为运行时异常。
其他的异常就是编译时异常 编译时异常 Java程序必须显示处理,否则程序就会发生错误,无法通过编译 运行时异常 无需显示处理,也可以和编译时异常一样处理
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; /* * throw:抛出一个具体的异常对象,用在方法的内部,只能抛出一个异常对象,表示一定发送了某个异常 * 原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws 区别: 后续程序需要继续运行就try 后续程序不需要继续运行就throws */ public class ExceptionDemo6 { public static void main(String[] args) throws FileNotFoundException { // 运行时期异常 //test(); //编译时期异常 test2(); System.out.println("over"); } private static void test2()throws FileNotFoundException { try { new FileInputStream(new File("")); } catch (FileNotFoundException e) { throw new FileNotFoundException("文件路径不正确"); } } private static void test() { // 先捕获这个异常吧,然后自己再处理抛出 try { int i = 1 / 0; } catch (Exception e) { // public ArithmeticException(String s)构造具有指定详细消息的 // ArithmeticException throw new ArithmeticException("除数为0了"); } } }
子类重写父类方法出现异常的处理方式
1.子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。
2.如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
3.如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
import java.io.FileNotFoundException; import java.text.ParseException; import java.text.SimpleDateFormat; public class ExceptionDemo7 { public static void main(String[] args) { } } class Father{ public void test()throws NullPointerException,FileNotFoundException,ParseException{ } public void run(){ } } class Son extends Father{ // 子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。 // 如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常 @Override public void test() throws ArrayStoreException, FileNotFoundException, ParseException { super.test(); } // 如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws @Override public void run() { try { new SimpleDateFormat().parse(""); } catch (ParseException e) { e.printStackTrace(); } } }
异常总结:
finally的特点作用:
finally的特点 被finally控制的语句体一定会执行 特殊情况:在执行到finally之前jvm退出了(比如System.exit(0))
finally的作用 用于释放资源,在IO流操作和数据库操作中会见到
throws:定义功能方法时,需要把出现的问题暴露出来让调用者去处理。那么就通过throws在方法上标识。
throw: 在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。
throws和throw的区别:
throws 用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开 表示抛出异常
由该方法的调用者来处理 throws表示出现异常的一种可能性,
并不一定会发生这些异常
throw 用在方法体内,跟的是异常对象名 只能抛出一个异常对象名 表示抛出异常,
由方法体内的语句处理 throw则是抛出了异常,执行throw则一定抛出了某种异常
我们到底该如何处理异常呢?
原则:如果该功能内部可以将问题处理,用try,如果处理不了,交由调用者处理,这是用throws
区别:
后续程序需要继续运行就try
后续程序不需要继续运行就throws
自定义异常:
人的年龄必须在1-260之间
很明显java没有对应的异常,
需要我们自己来做一个异常 自定义异常 继承自Exception 继承自RuntimeException
public class CustomException { public static void main(String[] args) { Person p = new Person("张三", 18, '男'); System.out.println(p); } }
public class AgeException extends RuntimeException { @Override public String getMessage() { return "人的年龄必须在1-260之间"; } }
1 /* 2 * 人的年龄必须在1-260之间 3 很明显java没有对应的异常,需要我们自己来做一个异常 4 自定义异常 5 继承自Exception 6 继承自RuntimeException 7 */ 8 public class Person { 9 private String name; 10 private int age; 11 private char sex; 12 public Person() { 13 super(); 14 } 15 public Person(String name, int age, char sex) { 16 super(); 17 this.name = name; 18 this.sex = sex; 19 checkAge(age); 20 this.age = age; 21 } 22 private void checkAge(int age) { 23 if(age<0 || age>260){ 24 //抛出异常 25 throw new AgeException(); 26 } 27 } 28 public String getName() { 29 return name; 30 } 31 public void setName(String name) { 32 this.name = name; 33 } 34 public int getAge() { 35 return age; 36 } 37 public void setAge(int age) { 38 checkAge(age); 39 this.age = age; 40 } 41 public char getSex() { 42 return sex; 43 } 44 public void setSex(char sex) { 45 this.sex = sex; 46 } 47 @Override 48 public String toString() { 49 return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]"; 50 } 51 }