什么是异常呢?
对于程序来说就是,程序执行过程中产生非正常的现象,比如异常退出。
那么Java异常呢就是Java提供的用来识别和处理异常的(机制)。
作为程序开发者,当然不希望自己的程序,遇到问题就中断或是有问题我也想知道是哪里出的问题,ok,这就是Java异常存在的意义。
进入正题:
正如你所知道的,Java的一切都是对象实现的,那异常当然也不例外。
首先上一张异常的结构图:
Throwable所有异常的父类
Error错误:
在代码中无法处理;这点一般是jvm出现了问题,很难遇到,遇到一般也解决不了 ?
Exception:异常
通过代码 可以解决的。这才是我们要关注的,异常分为
运行时异常 :在程序运行时才会发生检测到
非运行时异常:在编译期如果有错误就会报错,也可以称之为编译期异常
运行时异常: RuntimeException和 它的子类
在代码中可以不用处理,但是
出现异常会中断。
非运行时异常(受检):
Exception类 和 部分子类。
在源代码中 必须进行异常处理,
否则无法通过编译。
再放两张图 看下结构:
国际惯例,下面先上一个小Demo
public class TestException1 {
public void b() {
int x = 5;
int y = 0;
int z = x / y;
System.out.println(z);
}
public void a() {
b();
}
public static void main(String[] args) {
TestException1 t = new TestException1();
//就会报出异常,算数异常,并且终止程序,这个就是运行时异常
t.a();
}
}
再来一个,让我们看看异常都有什么:
package day12;
import java.lang.reflect.Field;
/**常见的异常*/
public class TestException2 {
public static void main(String[] args) throws Exception {
//1.ArithmeticException
// int x = 5 / 0;
//2.ArrayIndexOutOfBoundsException
// int [] arr = {1,2,3};
// arr[5] = 67;
//3.NullPointerException
// String s = null;
// System.out.println(s.equals("abc"));
//Objects类
// System.out.println(Objects.equals(s, "abc"));
// System.out.println(Objects.hashCode(s));
//4.InputMismatchException
// Scanner input = new Scanner(System.in);
// int n = input.nextInt();
//5.ClassCastException
// Object o = new String();
// Integer i = (Integer)o;
//6.NumberFormatException
// String str = "1332a";
// int n = Integer.parseInt(str);
// System.out.println(n);
//7.ClassNotFoundException
// ClassLoader.getSystemClassLoader().loadClass("day12.TestException12");
//8.IllegalArgumentException
//9.IllegalAccessException
Class c = Employee.class;
//获得了 name属性 IllegalArgumentException
Field f = c.getDeclaredField("name");
f.setAccessible(true);//
Object o = c.newInstance();
f.set(o, "张三");
System.out.println(f.get(o));
}
}
class Employee{
private String name;
}
那遇到异常有什么处理办法吗?
当然是有的,
try-catch-finally
try{
可能会引发异常的代码
}catch(异常类型 对象){
处理异常
}finally{
一定会执行的代码
}
但是有 一种情况不执行finally System.exit(); 退出虚拟机
管理 上Demo
package day12;
import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.concurrent.SynchronousQueue;
public class TestException3 {
public void f() {
Scanner input = new Scanner(System.in);
System.out.println("--输入两个数字;");
try {
int n1 = input.nextInt();
int n2 = input.nextInt();
int n3 = n1 / n2;
System.out.println(n3);
// return;
System.exit(0);
}catch(InputMismatchException e) {
// System.out.println("异常了");
// System.out.println(e);
//异常消息
// System.out.println(e.getMessage());
//堆栈轨迹信息
e.printStackTrace();
}catch(ArithmeticException e) {
System.out.println(e);
}catch(Exception e) {
e.printStackTrace();
}finally {
System.out.println("必须执行的代码");
}
}
public static void main(String[] args) {
new TestException3().f();//除法
System.out.println("其它代码执行⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯");
}
}
package day12;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Scanner;
public class TestException4 {
public static void main(String[] args) {
int [] arr = new int[5];
Scanner input = new Scanner(System.in);
System.out.println("赋值;");
try {
for(int i = 0; i < arr.length; i++) {
arr[i] = input.nextInt();
}
Arrays.stream(arr).forEach(System.out::println);
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("下标越界");
}catch(InputMismatchException e) {
System.out.println("赋值出错了");
}catch(Exception e) {
System.out.println(e.getMessage());
}finally {
System.out.println("程序运行出错");
}
}
}
还有一种用法 抛出异常 throws 用于 方法头部
throws
声明异常。
抛给 调用者。
调用者处理:
1.try-catch(更好)
2.throws
一般的话都是都是要处理异常 即 用try -catch 而不是 throws 那他为什么存在呢,因为简单啊!
package day12;
import java.util.Scanner;
/***/
public class TestException5 {
/*public void f() throws Exception{
Scanner input = new Scanner(System.in);
int x = input.nextInt();
int y = input.nextInt();
int z = x / y;
System.out.println(z);
}*/
public void f() throws RuntimeException{
Scanner input = new Scanner(System.in);
int x = input.nextInt();
int y = input.nextInt();
int z = x / y;
System.out.println(z);
}
public static void main(String[] args) {
/* try {
new TestException5().f();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
try {
new TestException5().f();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("其它代码^⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯");
}
}
那如果系统定义的异常类没有我想用的,我想自定义 可以吗?当然是可以的,
用throw 关键字 自己抛出异常 抛的是 非运行时异常,必须 throws,运行时异常,不用throws
上Demo
package day12;
class Person{
private int age;
public int getAge() {
return age;
}
/* public void setAge(int age) {
if(age >= 0 && age <= 150) {
this.age = age;
}else {
//抛异常对象
throw new RuntimeException("年龄必须在 0 - 150之间");
}
}*/
public void setAge(int age)throws AgeException {
if(age >= 0 && age <= 150) {
this.age = age;
}else {
//抛异常对象
// throw new Exception("年龄必须在 0 - 150之间");
throw new AgeException("年龄必须在 0 - 150之间");
}
}
}
class AgeException extends Exception{
/*AgeException(String str){
super(str);//调用父类构造传参
}*/
private String message;
AgeException(String message){
this.message = message;
}
@Override
public String getMessage() {
// TODO Auto-generated method stub
return "message:" + message;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "string:" + message;
}
@Override
public void printStackTrace() {
System.out.println("stack:" + message);
}
}
public class TestException6 {
public static void main(String[] args) {
Person zhangsan = new Person();
try {
zhangsan.setAge(222);
} catch (AgeException e) {
// e.printStackTrace();
// System.out.println(e);
System.out.println(e.getMessage());
}
}
}
这就是异常的各种用法,如有不正,请指出。