总的来说就是先把没有异常的代码先写好,然后在容易出现异常的代码部分进行加工,加入异常处理机制
Java异常机制用到的几个关键字:try、catch、finally、throw、throws。
try { //可能出现异常的代码 } catch (Exception e) { //异常处理的相关代码,如:getMessage()、printStackTrace() } finally { //无论是否异常,都需执行的代码结构,常用于释放资源 }
就是多态 自动向上转型,转型后父类引用指向的子类对象只能调用和父类相同的方法并且会覆盖父类方法
import java.io.IOException; import java.sql.SQLException; public class TestOverrideExceptionMethod { public static void main(String[] args) { Super sup = new Sub();// 父类引用指向子类对象 多态 自动向上转型 try { sup.method();// 在编译期间,调用的父类中声明的方法是有异常的,需要处理 } catch (Exception e) { e.printStackTrace();// 处理方案之1:打印堆栈跟踪信息 } } } // 带有异常的方法覆盖 // 1.父类中方法声明了异常。子类重写后可声明也可不声明 // 2.父类中方法没有声明异常,则子类也不可以声明异常。 // 3.父类中方法声明了异常,子类可以声明的异常与其相等或是其子类 // 4.子类可以声明比父类更多的异常。必须小于其父类声明的异常(子类) class Super { public void method() throws Exception { System.out.println("method in Super"); } } class Sub extends Super { public void method() throws ClassNotFoundException, RuntimeException, IOException, SQLException { System.out.println("method in Sub"); } } // 带有异常的接口方法也是与父类方法覆盖的原理相同,这里我就不再一一重复了 interface Printable { public void print() throws Exception; } class MyClass implements Printable { public void print() throws ClassNotFoundException, RuntimeException { } }
import java.util.InputMismatchException; public class TestDefinedException { public static void main(String[] args) { Student stu = new Student(); try { stu.setAge(250);//是可能出现异常的代码 }catch(Exception e) { System.err.println(e.getMessage());//只获得报错的原因即可 //这个程序没有这行代码是没法输出红色的异常原因的!!! } try { stu.setSex("未知");//受查异常,编译期间就报错,需要处理 }catch(SexMismatchException se) {//根据方法声明的异常,捕获相应的类型 System.err.println(se.getMessage()); }catch(Exception e ) { e.printStackTrace(); } } } //自定义异常必须要加上异常类继承Eception //受查异常(是在编译期间,就必须处理的异常! 需要声明出去) class SexMismatchException extends Exception{ public SexMismatchException() {} public SexMismatchException(String message) { super(message); } } //运行时异常 class AgeInputException extends RuntimeException{ public AgeInputException() {}//支持创建无异常原因信息的异常对象 public AgeInputException(String message) {//提供有参构造方法,支持编写异常原因信息 super(message);//调用父类的有参构造方法,为message属性赋值。 } } //在应用场景下,可以根据自身的需要,自定义异常。 class Student{ private int age;//年龄 private String sex;//性别 男 女 public void setSex(String sex) throws SexMismatchException { //告知调用者,使用该方法,会存在异常。必须处理.声明的异常类型最好与抛出的异常类型一致 if(sex.equals("男") || sex.equals("女")) { this.sex = sex; }else { //在用户输入一个性别后!就做好提醒!性别的输入可能不准确! 受查异常。 throw new SexMismatchException("性别输入的值为:“男”或者“女”"); } } public String getSex() { return this.sex; } public int getAge() { return this.age; } public void setAge(int age){ if(age > 0 && age < 123) { this.age = age; }else { throw new AgeInputException("年龄的赋值应该在0岁到123岁之间"); //抛运行时异常的父类。 不合理。现存的定义好的异常,没有符合现在程序的场景 } } }
自定义的异常应该总是包含如下的构造函数:
throw和throws的区别?
throw和throws都是在异常处理中使用的关键字,区别如下:
throws抛出异常
一个方法可能会出现异常但是没法处理异常,可以在方法声明处用throws子句来声明抛出异常。该方法并不会对这些异常进行处理,而是调用此方法的方法会进行异常处理.
throws抛出异常的规则:
最基本的throw用法
public class TestException { public static void main(String[] args) { int a = 6; int b = 0; try { if (b == 0) { throw new ArithmeticException(); //"除数为0"等ArithmeticException,是RuntimException的子类。而运行时异常将由运行时系统自动抛出,不需要使用throw语句,这里把throw new ArithmeticException()去掉也是不影响运行结果的。 } System.out.println("a/b的值是:" + a / b); } catch (ArithmeticException e) { System.out.println("程序出现异常,变量b不能为0。"); } System.out.println("程序正常结束。"); } }
throw都是在try语句模块内完成的,哪怕有时候try语句后面只引用了一个方法,但是在这个方法里面还是throw。
throws抛出异常,方法的调用者必须处理该异常,就是必须try catch处理这个异常,或者继续throws继续往上抛,并且throws并不确定到底是个什么异常;throw抛出异常,会明确告诉你这个地方是什么异常,程序到这终止了,调用该方法的地方报错,不继续向后执行。