定义:异常就是有异于常态,和正常情况不一样,有错误出现。在java中,将程序执行过程中的不正常的情况称之为异常,开发过程中的语法错误和逻辑错误不是异常,发生异常时java会阻止当前方法或作用域的情况。
异常的体系结构
从程序执行的过程来看编译时异常和运行时异常
指针指向的对象为空(null)
package com.broky.exception; public class NullPointerEx { public static void main(String[] args) { int[] arr = null; System.out.println(arr[3]); /*Exception in thread "main" java.lang.NullPointerException: Cannot load from int array because "arr" is null at com.broky.exception.NullPointerEx.main(NullPointerEx.java:6)*/ } }
package com.broky.exception; public class XIndexOutOfBoundEx { public static void main(String[] args) { int[] arr = new int[3]; System.out.println(arr[3]); /*Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at com.broky.exception.XIndexOutOfBoundEx.main(XIndexOutOfBoundEx.java:6)*/ String str = "abc"; System.out.println(str.charAt(3)); /*Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 3 at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:48) at java.base/java.lang.String.charAt(String.java:711) at com.broky.exception.XIndexOutOfBoundEx.main(XIndexOutOfBoundEx.java:11)*/ } }
package com.broky.exception; public class ClassCastEx { public static void main(String[] args) { Object obj = new Double(1); String str = (String)obj; /*Exception in thread "main" java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.String (java.lang.Double and java.lang.String are in module java.base of loader 'bootstrap') at com.broky.exception.ClassCastEx.main(ClassCastEx.java:7)*/ } }
package com.broky.exception; public class NumberFormatException { public static void main(String[] args) { String str = "abc"; int a = Integer.parseInt(str); /*Exception in thread "main" java.lang.NumberFormatException: For input string: "abc" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) at java.base/java.lang.Integer.parseInt(Integer.java:660) at java.base/java.lang.Integer.parseInt(Integer.java:778) at com.broky.exception.NumberMismatchEx.main(NumberMismatchEx.java:6)*/ } }
package com.broky.exception; import java.util.Scanner; public class InputMismatchEx { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int num = scan.nextInt(); System.out.println(num); /*asd Exception in thread "main" java.util.InputMismatchException at java.base/java.util.Scanner.throwFor(Scanner.java:939) at java.base/java.util.Scanner.next(Scanner.java:1594) at java.base/java.util.Scanner.nextInt(Scanner.java:2258) at java.base/java.util.Scanner.nextInt(Scanner.java:2212) at com.broky.exception.InputMismatchEx.main(InputMismatchEx.java:8)*/ } }
package com.broky.exception; public class ArithmeticEx { public static void main(String[] args) { int a = 10; int b = 0; int c = a / b; /*Exception in thread "main" java.lang.ArithmeticException: / by zero at com.broky.exception.ArithmeticEx.main(ArithmeticEx.java:7)*/ } }
这个产生的异常对象会与catch的异常类型相匹配,匹配成功后就被 catch 捕获,然后运行catch{}中的代码, 一般catch中的代码为处理异常的代码, 比如返回异常的信息和返回异常的详细信息等. 一旦异常处理完成,就会跳出当前的try-catch结构
无论有没有发生异常finally中的代码都会最后被执行
package com.broky.exception.demo02; public class TryCatchFinally { public static void main(String[] args) { String str = "abc"; try { int i = Integer.parseInt(str); } catch (NumberFormatException e) { e.printStackTrace(); } catch (Exception e) { System.out.println(e.getMessage()); } finally { System.out.println("运行完毕"); } } }
throws 一般用于方法中可能存在异常时, 需要将异常情况向方法之上的层级抛出, 由抛出方法的上一级来解决这个问题, 如果方法的上一级无法解决的会就会再将异常向上抛出, 最终会抛给main方法. 这样一来main方法中调用了这个方法的时候,就需要解决这个可能出现的异常.
当然main方法也可以不解决异常, 将异常往上抛出给java虚拟机, 如果java虚拟机也无法解决的话,那么java虚拟机就over了
throws + 异常类型
写在方法的声明处.指明此方法执行时,可能会抛出的异常类型.
一旦方法体执行时,出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出。
异常代码的后续的代码,就不再执行!
体会:tyr-catch-fianlly:真正的将异常给处理掉了。throws的方式只是将异常抛给了方法的调用者,并没有真正将异常处理掉。
注意: 将异常向上抛出也算是一种处理异常的方法
package com.broky.exception; import java.io.FileNotFoundException; public class ThrowsEx { public void setAge2(int age) throws FileNotFoundException { if (age < 0) { throw new FileNotFoundException("输入的年龄小于0"); } } public void TestsetAge2() throws FileNotFoundException { setAge2(2); } public static void main(String[] args) { try { ThrowsEx.throwsExTest(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
下面代码中,main方法中向display方法中传入了SuperClass的子类对象.那么到display方法中调用s.method调用的就是SpuerClass的子类SubClass重写的method方法, 如果这个方法抛出的异常范围大于父类SuperClass所抛出的异常的话,那么在display方法中对异常的catch处理就会catch不到这个异常.
package com.broky.exception; import java.io.FileNotFoundException; import java.io.IOException; public class OverrideTest { public void display(SuperClass s) { try { s.method(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { OverrideTest overrideTest = new OverrideTest(); overrideTest.display(new SubClass()); } } class SuperClass { public void method() throws IOException { System.out.println("super"); } } class SubClass extends SuperClass { public void method() throws FileNotFoundException { System.out.println("sub"); } }
手动抛出的异常有两种, 分别为运行时异常和编译时异常.
抛出运行时异常时, 可以不用处理抛出的这个异常.
抛出编译时异常时, 必须要处理抛出的这个异常.
详细解析请看下面的代码
package com.broky.exception; /*Demo 手动抛出异常 自己throw(制造一个异常抛出) */ import java.io.FileNotFoundException; public class ThrowEx { // 手动抛出运行时异常 public void setAge(int age) { if (age < 0) { throw new NullPointerException("输入的年龄小于0"); } } /* 此方法手动抛出了运行时异常 运行时异常可以不用处理 */ // 手动抛出编译时异常 public void setAge2(int age) throws FileNotFoundException { if (age < 0) { throw new FileNotFoundException("输入的年龄小于0"); } } /* 此方法手动抛出的了编译时异常 编译时异常需要被处理 这里采用了 throws 这个异常, 也就是说方法并没有处理这个异常, 而是将异常抛给了调用者 这样一来调用了这个方法的人就必须要处理这个异常才可以. 注意: 在这里并不用自己使用 try catch 处理这个异常 自己在方法里抛出异常, 方法再自己处理没有任何作用. 所以方法中的异常需要抛给调用者去处理. */ public static void main(String[] args) { ThrowEx throwEx = new ThrowEx(); throwEx.setAge(-5); } }
package com.broky.exception; public class MyException extends RuntimeException{ static final long serialVersionUID = -1234719074324978L; public MyException(){ } public MyException(String message){ super(message); } public static void main(String[] args) { throw new MyException("自定义运行时异常"); /*Exception in thread "main" com.broky.exception.MyException: 自定义运行时异常 at com.broky.exception.MyException.main(MyException.java:15)*/ } }