一、异常?
java系统中将java.lang.Throwable类作为异常的最根类
[java.lang.Throwable是所有异常或错误的顶级类,可以处理任何异常]
* java.lang.Throwable
* |-----java.lang.Error:一般不编写针对性的代码进行处理。
* |-----java.lang.Exception:可以进行异常的处理
* |------编译时异常(checked)
* |-----IOException
* |-----FileNotFoundException
* |-----ClassNotFoundException
* |------运行时异常(unchecked,RuntimeException)
* |-----NullPointerException
* |-----ArrayIndexOutOfBoundsException
* |-----ClassCastException
* |-----NumberFormatException
* |-----InputMismatchException
* |-----ArithmeticException
二、异常分类
Throwable是所有异常或错误的顶级类,可以处理任何异常.
因为处理范围过大,操作不方便,Java提供两个子类:Exception和Error
异常分为: Exception(可以治疗) 和 Error(不治之症)
1. Error:
通常指 java系统出现的错误,与java程序无关. 无法使用代码进行维护或修改错误.
2. Exception:
通常指 java程序出现的错误,可以使用代码进行修改或维护.[通常值学习/研究 Exception.]
Exception的分类: [根据 编译时 是否检查 含有XX异常分类]
须查异常[非运行时异常]: 指 java文件编译为class文件时, 需要检查的异常.
不须查异常[运行时异常]: 指 java文件编译为class文件时, 不需要检查的异常.
3. 哪些异常属于须查异常,哪些异常属于不须查异常?
Exception及其子类[不含RuntimeException]都属于须查异常[非运行时异常]
RuntimeException及子类属于不须查异常也就是运行时异常
4. 常见的须查异常(编译时异常):
语法错误 路径错误 等等
5. 常见的不须查异常(运行时异常):
数组下标越界:java.lang.ArrayIndexOutOfBoundsException,Java程序试图访问不存在的索引对应的元素.
被除数为0: java.lang.ArithmeticException: / by zero,在计算机中,被除数不能为0.
空指针:java.lang.NullPointerException,Java程序试图去访问不存在的对象的属性或方法,因此报错.
三、异常处理
使用try-catch-finally处理编译时异常,使得程序在编译时就不报错,但是运行是仍然可能报错
开发中由于运行时异常常见,通常不针对运行时异常try-catch-finally处理,而针对编译时异常,一定要考虑异常的处理
throws的方式知识将异常抛给了方法的调用者,并没有真正的将异常处理
1. 第一种: [积极处理]
try{
存放可能发生异常的代码,try代码块将自动捕捉异常
}catch(异常类型 参数){
与发生的异常进行匹配,匹配上后将执行此处代码
}catch(异常类型 参数){
与发生的异常进行匹配,匹配上后将执行此处代码
}finally{
作为程序最后执行的代码,一定会执行,即使try和catch里面有return或异常
}
说明:
- try,catch,finally代码块不能单独使用,必须混合. 常见组合方式:try,catch,finally 或 try catch 或 try finally
- try代码块必须含有,catch代码可以含有N个.finally代码块可以含有0或1个,且必须放在try和catch的后面.
原理:
- java程序执行try代码块中的代码,如果发生异常,将被try代码块捕获,
- try代码块捕获异常后, 将于之后的catch代码块进行异常类型匹配,如果匹配上异常类型,将执行执行此处的catch代码块,不再向下继续匹配.
- try代码块捕获异常后,与所有的catch代码块的异常类型都不匹配,该异常将交给java系统处理[直接结束程序的执行]无论程序是否发生异常,异常是否处理成功,都将执行finally代码块[通常用于执行关键性的代码: 关闭资源等等,降低程序的损失
注意: 当有多个catch代码块时,将处理范围大的异常放在后面.
try中的异常对象匹配到某一个catch时,就会进入到catch中进行异常的处理,一旦处理完成,就退出当前的try-catch结构(在没有写finally的时候),继续执行其后的代码
常用的处理方式:
都是打印错误信息,方式不同
public void test1() {
String str = "abc";
try {
int num = Integer.parseInt(str);
}catch(Exception e) {
// 1. System.out.println(e.getMessage());
// 2. e.printStackTrace();
}
}
快捷操作
2. 第二种: [消极处理]
格式:
权限.... 方法名(参数类型 参数名,参数类型 参数名,...) throws 异常类型,...{
方法体
}
原理:
- 当前方法体中将异常抛出到方法调用处,在方法调用的地方必须处理当前异常.
- 方法调用处可以处理该异常,也可以继续向方法外抛出异常.[如果main函数中也没有处理该异常,该异常将抛给Java系统,Java系统将以"粗暴的方式"处理,直接结束程序的执行]
- 异常后面的代码就不会再执行了
方法重写的规则之一:
类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
import java.io.FileNotFoundException;
import java.io.IOException;
public class OverrideTest {
public static void main(String[] args) {
OverrideTest test = new OverrideTest();
test.display(new SubClass());
}
public void display(SuperClass s){
try {
s.method();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SuperClass{
public void method() throws IOException{
}
}
class SubClass extends SuperClass{
public void method()throws FileNotFoundException{
}
}
3. 开发中如何选择使用try-catch-finally 还是使用throws?
-
如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,意味着如果子类重写的方法中有异常,必须使用try-catch-finally方式处理。
-
执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
四、手动抛出异常
throw
public class StudentTest {
public static void main(String[] args) {
try {
Student s = new Student();
s.regist(-1001);
System.out.println(s);
} catch (Exception e) {
// e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
class Student{
private int id;
public void regist(int id) throws Exception {
if(id > 0){
this.id = id;
}else{
// System.out.println("您输入的数据非法!");
//手动抛出异常对象,运行时异常,可以不用try-catch
// throw new RuntimeException("您输入的数据非法!");
// 必须进行try-catch
throw new Exception("您输入的数据非法!");
//错误的
// throw new String("不能输入负数");
}
}
@Override
public String toString() {
return "Student [id=" + id + "]";
}
}
五、 自定义异常
如何自定义异常类?
- 继承于现有的异常结构:RuntimeException 、Exception
- 提供全局常量:serialVersionUID
- 提供重载的构造器
public class MyException extends Exception{
static final long serialVersionUID = -7034897193246939L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
此时使用自己定义的异常类
package com.atguigu.java2;
public class StudentTest {
public static void main(String[] args) {
try {
Student s = new Student();
s.regist(-1001);
System.out.println(s);
} catch (Exception e) {
// e.printStackTrace();
System.out.println(e.getMessage());
}
}
}
class Student{
private int id;
public void regist(int id) throws Exception {
if(id > 0){
this.id = id;
}else{
throw new MyException("不能输入负数");
}
}
@Override
public String toString() {
return "Student [id=" + id + "]";
}
}
六、问题
进入A----用A方法----制造异常----进入方法B-----调用B
1. 请解释Error和Exception的区别?
- Error:指的是JVM错误,这个时候的程序并没有执行,无法处理;
- Exception:指的是程序之中出现的错误信息,可以进行异常处理,主要关心Exception。
2. 请解释java之中的异常处理流程
- 如果程序之中产生了异常,那么会自动的由JVM根据异常的类型,实例化一个指定异常类的对象;
- 如果这个时候程序之中没有任何的异常处理操作,则这个异常类的实例化对象将交给JVM进行处理,而JVM的默认处理方式就是进行异常信息的输出,而后中断程序执行
- 如果程序之中存在了异常处理,则会由try语句捕获产生的异常类对象
- 与try之后的每一个catch进行匹配,如果匹配成功,则使用指定的catch进行处理,如果没有匹配成功,则向后面的catch继续匹配,如果没有任何的catch匹配成功,则这个时候将交给JVM执行默认处理
- 不管是否有异常都会执行finally程序,如果此时没有异常,执行完finally,则会继续执行程序之中的其他代码,如果此时有异常没有能够处理(没有一个catch可以满足),那么也会执行finally,但是执行完finally之后,将默认交给JVM进行异常的信息输出,并且程序中断
3. 请解释一下RuntimeException和Exception的区别?请列举出几个常见的RuntimeException
七、总结
throw 和 throws区别:
throw 表示抛出一个异常类的对象,生成异常对象的过程。声明在方法体内。
throws 属于异常处理的一种方式,声明在方法的声明处。