Java异常处理机制
Throwable类是Java语言中所有错误和异常的超类。只有作为该类(或其子类之一)实例的对象才由Java虚拟机抛出,或者可以由Java throw语句抛出。类似地,只有这个类或它的一个子类可以是catch子句中的参数类型。为了在编译时检查异常,Throwable类和Throwable类的任何子类(不同时是RuntimeException或Error的子类)都被视为已检查异常。
异常是程序在编译或运行过程出现的例外,这些例外在有的可以避免有的却无法避免。
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
1、异常分类
package LESSON10; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class demo1 { /**
异常时程序在编译或运行过程中出现的例外,这些例外有的可以避免有的却无法避免 异常:编译期异常和运行期异常 */ public static void main(String[] args) { //运行期异常:RuntimeException 可以避免 //算术异常java.lang.ArithmeticException // System.out.println(1/0); String str=null; //空指针异常java.lang.NullPointerException // System.out.println(str.length()); //数组下标越界异常java.lang.ArrayIndexOutOfBoundsException int arr[]=new int[3]; // System.out.println(arr[3]); //字符串下标越界异常java.lang.StringIndexOutOfBoundsException String s="abc"; // System.out.println(s.charAt(3)); //输入不匹配异常java.util.InputMismatchException // System.out.println("输入:"); // new Scanner(System.in).nextInt(); //类型转换异常java.lang.ClassCastException Object obj=new Object(); // String ss=(String)obj;
//数字格式异常java.lang.NumberFormatException
String sss="abc";//字符串内是数字不会报异常如String sss="123"
Integer.valueOf(sss); //编译期异常 无法避免 String time="2019/06/05 22:22:22"; SimpleDateFormat sdf2=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); try { //解析异常ParseException Date d = sdf2.parse(time);// 解析字符串的文本,生成 Date。 System.out.println(d); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package ceshi; public class ceshi2 { public static void drink(){ System.out.println("喝"); } public void eat(){ System.out.println("吃"); this.eat(); } public static void main(String[] args) { ceshi2 ceshi=new ceshi2(); ceshi.eat();//java.lang.StackOverflowError堆栈溢出错误 运行期异常 } }
2、异常处理
package LESSON9; import java.text.ParseException; import java.text.SimpleDateFormat; public class demo6 { public void test1(){ try { System.out.println(1/0); } catch (Exception e) { //e.printStackTrace();//显示到控制台 System.out.println(e.getMessage()); } finally{ System.out.println("是否发生异常都会执行"); } } // throws抛出 public void test2() throws ParseException{ new SimpleDateFormat().parse("2019/06/05"); } //捕获:try-catch-finally //try也可以单独和catch连用 //try也可以单独和finally连用 public void test3(){ //try{ //可能出现异常的代码块 // } // catch (Exception e) { // //捕获并处理异常 // //即使写了return,也会先执行finally的语句(执行顺序) // } //finally{ // 是否发生异常都会执行 // } try { System.out.println(1/0); } catch (ParseException e) { // 如果有异常才能捕获 e.printStackTrace();//将异常信息显示在控制台
// System.out.println(e.getMessage());获取异常信息
System.out.println("除数不能为0");
return;//不会影响finally的执行
System.out.println("---");//编译时会提示Unreachable code }finally{
System.out.println("不论是否发生异常。finally都会执行");
} } public static void main(String[] args) { //如果该方法抛出异常,在调用此方法时还要处理 //如果该方法已经捕获异常,在调用此方法时无需在处理 new demo6().test1(); // new demo6().test2(); new demo6().test3(); } }
3、自定义异常
自定义异常根据继承的父类不同分为两类
继承自Exception的自定义异常
继承自RuntimeException的自定义异常
继承自Exception的自定义异常为编译期异常必须要进行处理。
继承自RuntimeException的自定义异常为运行时异常不需要进行特别的处理。
package LESSON10; import java.util.Scanner; class AgeLT0Exception extends Exception { public AgeLT0Exception (String msg){ super(msg); } } class AgeGT150Exception extends Exception{ public AgeGT150Exception(String msg) { super(msg); } } public class exercise { public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入:"); int age=sc.nextInt(); if(age<0){ try { throw new AgeLT0Exception ("年龄太小"); } catch (AgeLT0Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(age>150){ try { throw new AgeGT150Exception("年龄太大"); } catch (AgeGT150Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
自动取款机例子异常处理
package LESSON10; public class Account { public long id; public int password; public String name; public double balance=2000; public Account(long id,String name){ this.id=id; this.name=name; } public void deposit(double money){ balance+=money; System.out.println("当前余额为:"+balance); } public void withdraw(double money) throws BalanceNotEnoughException{ if(money<=balance){ balance-=money; System.out.println("当前余额为:"+balance); } else{ // System.out.println("余额不足"); throw new BalanceNotEnoughException("没钱了");//如果为捕获异常时,取款大于余额时有对异常的处理,程序不会停止;抛出异常时会停止 } } }
package LESSON10; public class PasswordNotTrue extends Exception{ public PasswordNotTrue(String msg){ super(msg); } }
package LESSON10; import java.util.*; public class exercise3 { public static void main(String[] args) throws BalanceNotEnoughException { int num=3; Account acc=new Account(123456,"张三"); Scanner sc=new Scanner(System.in); System.out.println("欢迎来到自助银行"); while(true){ System.out.println("请输入密码"); int pwd=sc.nextInt(); if(pwd==123) { System.out.println(acc.name+"欢迎,您的账户为"+acc.id); while(true){ System.out.println("请选择:1存款 2取款 3查询余额 4退出"); int a=sc.nextInt(); if(a==1){ System.out.println("请输入存款金额"); double money=sc.nextDouble(); acc.deposit(money); } else if(a==2){ System.out.println("请输入取款金额"); double money=sc.nextDouble(); acc.withdraw(money); } else if(a==3){ System.out.println("余额为:"+acc.balance); } else if(a==4){ System.exit(0);//退出jvm } else{ System.out.println("输入错误"); break; } } } else{ num--; if(num==0){ // System.out.println("账户已冻结"); try { throw new PasswordNotTrue("账户已冻结"); } catch (PasswordNotTrue e) { // TODO Auto-generated catch block e.printStackTrace(); } break; } System.out.println("密码错误,您还有"+num+"次机会"); } } } }
package LESSON10; public class BalanceNotEnoughException extends Exception{ public BalanceNotEnoughException(String msg) { super(msg); } }