异常与错误
在Java中有一个定义好的规则Throwable(可以抛出的)
Error错误
通常是一些物理性的,JVM虚拟机本身出现的问题,程序指令是处理不了的
Exception
通常是一种人为规定的不正常的现象,通常是规定的程序指令产生看一些不符合规范的事情
Throwable
Error(错误) Exception(异常)
(1)StackOverflowError RuntimeException(运行时异常) IOException
(2)OutOfMemoryError
一、异常的分支体系:
运行时异常(非检查异常)
Error和RuntimeException都算作运行时异常,javac编译的时候不会提示和发现的,在程序编写的时候不要求必须处理,我们可以添加处理手段(try throws)
1.InputMismatchException 输入不匹配
Scanner input = new Scanner(System.in); int value = input.nextInt();//应输入int类型,若输出其他类型则出现此异常
2.NumberFormatException 数字格式化
int a = Integer.parseInt("123.00");//123.00不是int类型的 System.out.println(a);
3.NegativeArraySizeException 数组长度负数
int [] a = new int[-2];
4.ArrayIndexOutOfBoundsException 数组索引越界
int [] a = new int[5]; System.out.println(a[7]);
5.NullPointerException 空指针异常
int [] a = null; System.out.println(a[2]);
int [][] array = new int[2][];
System.out.println(array[1][0]);
6.ArthmeticException 数字异常
System.out.println(1.0/0);//输出Infinity System.out.println(1/0);//异常
7.ClassCastException 造型异常
Person p = new Teacher(); Student s = (Student)p; //强制向下造型
8.StringIndexOutOfBoundsException 字符串越界
String a = "abcd"; System.out.println(a.charAt(5));//超过字符串长度
9.IndexOutOfBoundsException 集合越界
ArrayList list = new ArrayList(); list.add(1); list.add(2); System.out.println(list.get(5));//IndexOutOfBoundsException
10.ILLegalArgumentException 非法参数异常
ArrayList list = new ArrayList(-1);
编译时异常(检查异常)
除了Error和RuntimeException以外其他的异常
javac编译的时候(小红线下标的),强制要求我们必须为这样的异常做处理(try或者throws)
因为这样的异常在程序运行过程中极有可能产生问题,异常产生后后续的所有执行就停止了
1.InterruptException
//Thread.sleep(5000);//如果只写此行代码 则会出现编译异常 //正确写法 try{ Thread.sleep(5000); }catch(Exception e){ }
二、添加处理异常的手段
1.try{}catch(){}[ finally{} ]
1.try不能单独的出现
2.后面必须添加catch或finally
3.catch有一组括号 () 目的是为了捕获某一种异常
4.catch可以有很多个存在
捕获的异常之间没有任何的继承关系
捕获的异常需要从小到大进行捕获
public static void main(String[] args) { System.out.println("代码开始执行"); try { int[] array = new int[2]; System.out.println(array[3]);//索引越界,直接捕获 System.out.println("try代码执行完毕");//此行不执行 } catch (NegativeArraySizeException e) {//小的 System.out.println("捕获到了数组长度异常");//应该是索引越界,所以这个不会捕获 } catch (Exception e){ //若放在其他异常之前 ,则只执行这个异常捕获,其他异常不捕获 System.out.println("父类捕获到了其他异常"); }finally{ //总会执行 System.out.println("finally执行了"); } System.out.println("--end--"); } 输出结果: 代码开始执行 父类捕获到了其他异常 finally执行了 --end--
5.finally不是必须存在的
若存在finally结构 则必须执行
public class TestThrowable { public static void main(String[] args) { System.out.println("代码开始执行"); try { int[] array = new int[2]; System.out.println(array[3]);//索引越界,直接捕获 System.out.println(array[-1]); System.out.println("try代码执行完毕");//此行不执行 } catch (ArrayIndexOutOfBoundsException e) {//小的 System.out.println("捕获到了数组索引越界异常"); } catch (NegativeArraySizeException e) {//小的 System.out.println("捕获到了数组长度异常"); } catch (Exception e){ //最大的异常 , 若放在其他异常之前 ,则只执行这个异常捕获,其他异常不捕获 System.out.println("父类捕获"); }finally{ //总会执行 System.out.println("finally执行了"); } System.out.println("--end--"); } } 执行结果: 代码开始执行 捕获到了数组索引越界异常 finally执行了 --end--
引申一个小问题: final finally finalize区别:
final 特征修饰符 修饰变量 属性 方法 类
修饰变量 基本类型 值不能改变 引用类型 地址不能改变(如果变量没有初值 给一次机会赋值)
修饰属性 特点与修饰变量类似 (要求必须给属性赋初始值 否则编译报错)
修饰方法 不能被子类重写
修饰类 不能被其他的子类继承
finally 处理异常手段的一部分
try{}catch(){}后面的一个部分
这个部分可有可无 如果有只能含有一份 且必须执行
finalize 是Object类中的一个protected方法
对象没有任何引用指向的时候 -- 会被GC回收
当对象回收的时候 默认调用finalize方法
若想要看到对象回收的效果 可以重写 public void finalize(){}
6.处理异常放在方法内部 可能还会有小问题
如果在方法内部含有返回值
不管返回值return关键字在哪里 finally一定会执行完毕
返回值的具体结果 看情况
public String testException(){ System.out.println("代码开始执行"); try { int[] array = new int[2]; System.out.println(array[3]);//索引越界,直接捕获 return "try代码执行完毕返回"; //如果无异常 则执行此行return } catch (ArrayIndexOutOfBoundsException e) {//小的 System.out.println("捕获到了数组索引越界异常"); } finally{ //无论return放在那 , finally也会执行 System.out.println("finally执行了"); } return "--end--"; } public static void main(String[] args) { TestThrowable testThrowable = new TestThrowable(); String value = testThrowable.testException(); System.out.println(value); } 输出结果: 代码开始执行 捕获到了数组索引越界异常 finally执行了 --end--
2.throws抛出
1.异常只能在方法上抛出 属性是不能处理异常的
2.方法 构造
3.方法可以抛出不止一个异常 通过,隔开
4.抛出的异常与多个catch类似 要么没关系 要么先抛出小异常
public String test() throws NullPointerException,ArrayIndexOutOfBoundsException{ String string =null; string.length(); return "返回值"; } public static void main(String[] args) { TestThrowable testThrowable = new TestThrowable(); try { testThrowable.test();//谁调用方法 抛给谁 }catch (Exception e){ System.out.println("捕获到了异常"); } } 输出结果: 捕获到了异常
三、 我们也可以自己创建异常----自定义异常
1.自己描述一个异常的类
2.让我们自己的类继承
如果继承是RuntimeException---->运行时异常(不需要必须添加处理手段)
如果继承是Exception-------------->编译时异常(必须添加处理手段)
3.创建一个当前自定义异常类的对象
通过throw关键字 主动产生异常
4.当我们设计描述的方法(事情) 之前没有相关的异常能描述我的问题Box
这个时候才会利用自定义异常来描述
public class TestThrowable { //来设计一个方法 测试自定义异常的使用 public void testMyException(){ System.out.println("测试自定义异常的方法执行啦"); if(3>2){//若满足某个条件 throw new MyException(); } } public static void main(String[] args) { TestThrowable testThrowable = new TestThrowable(); testThrowable.testMyException(); } } public class MyException extends RuntimeException{ }
public class TestThrowable { //来设计一个方法 测试自定义异常的使用 public void testMyException() throws MyException{ System.out.println("测试自定义异常的方法执行啦"); if(3>2){//若满足某个条件 throw new MyException("说明一下异常的具体问题"); } } public static void main(String[] args) { TestThrowable testThrowable = new TestThrowable(); try { testThrowable.testMyException(); }catch (Exception e){ e.printStackTrace(); } } } public class MyException extends Exception{ public MyException(){} public MyException(String msg){ super(msg); } } 输出结果: 测试自定义异常的方法执行啦 test_throwable.MyException: 说明一下异常的具体问题