一、异常的概述与异常体系结构
有点类似于bug。将程序执行当中发生的不正常情况称为“异常”。语法错误和逻辑错误不是异常
分两类 :
Error:Java虚拟机无法解决的情况。
Exception:其他因编程错误或偶然的外在因素导致的一致性问题,可以使用针对性代码进行处理。又可以分为编译时异常和运行时异常。
例如:
1.空指针访问
2.试图读取不存在的文件
3.网络连接中断
4.数组角标越界
体系结构:
编译时异常:执行javac.exe命名时,可能出现的异常
运行时异常:执行java.exe命名时,出现的异常(可以不用处理)
二、常见异常
三、异常处理机制一:tyr-catch-finally
自己解决
一、 异常处理:抓抛模型
过程一:“抛”,程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常类的对象。并将此对象抛出。一旦抛出对象以后,其后的代码就不再执行。
关于异常对象的产生:1.系统自动生成的异常对象
2.手动的生成一个异常对象,并抛出(throw)
过程二:“抓”,可以理解为异常的处理方式:1.try-catch-finally 2.throws
二、try-catch-finally的使用
try{
//可能出现异常的代码
}catch(异常类型1 变量名1){
//处理异常的方式1
}catch(异常类型2 变量名2){
//处理异常的方式2
}catch(异常类型3 变量名3){
//处理异常的方式3
}
…
finally{
//一点会执行的代码
}
说明:
1.finally是可选的
2.使用try将可能出现异常代码包装起来,在执行过程中,一旦出现异常。就会生成一个对应的异常类的对象,根据此对象的类型
去catch中进行匹配
3.一旦try中的异常对象匹配到某个catch时,就进入catch中进行异常处理,一旦完成就跳出try-catch结构(在没有写finally的情况下)
就继续执行其后的代码
4.catch中的异常类型无父子关系,谁在上无所谓。有父子关系子类要在上面否则报错
5.常用的异常对象处理的方式:1.String getMessage(); 返回的是字符串 2.printStackTrace();
6.在rry结构中声明的变量,不能在外调用了
7.try-catch-finally结构也可以相互嵌套
体会1:使用try-catch-finally处理编译时异常,使得程序在编译时就不能报错但是运行时仍可能报错
相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现
体会2:开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。
针对于编译时异常,我们说一定要考虑异常的处理。
try-catch-finally中的finally的使用:
1.finally是可选得
2.finally中声明得是一定会被执行得代码,即使catch中还有异常
3.像数据库连接、输入输出流、网络编程Socket等资源,JVM是不能自动得回收得,我们需要手动的进行资源的
释放,此时的资源释放,就需要声明在finally当中
public class FinallyTest {
public void test1(){
try {
int a = 10;
int b = 0;
System.out.println(a/b);
}catch (ArithmeticException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}finally {
}
}
public void test2(){
FileInputStream fis = null;
try {
File file = new File("haloo.txt");
fis = new FileInputStream(file);
int data = fis.read();
while(data != -1){
System.out.println((char) data);
data = fis.read();
}
// fis.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
public static void main(String[] args) {
FinallyTest finallyTest = new FinallyTest();
finallyTest.test2();
}
}
四、异常处理机制二:throws
自己搞不定,抛给其他的来处理,向上抛。
异常处理的方式二:throws+异常类型
1.thows+异常类型 写在方法的声明处,指明方法执行时可能会抛出异常类型
一旦当方法体执行出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws对象时就会抛出
如何异常后续的代码不再执行。
2.try-catch-finally真正的将异常处理掉了
throws的方式只是将异常抛给了方法的调用者,并没有将异常处理掉
3.开发中如何选择try-catch-finally 还是使用throws?
3.1 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,其子类有
异常必须使用try-catch-finally的方式处理。
3.2 执行的方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的。建议使用throws的方式处理
而执行的方法a中建议使用try-catch-finally的方式处理
public class ExceptionTest2 {
public static void main(String[] args) {
try {
method2();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
method3();
}
public static void method3(){
try {
method2();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
public static void method2() throws FileNotFoundException,IOException {
method1();
}
public static void method1() throws FileNotFoundException, IOException {
File file = new File("haloo.txt");
FileInputStream fis = new FileInputStream(file);
int data = fis.read();
while(data != -1) {
System.out.println((char) data);
data = fis.read();
}
fis.close();
}
}
五、手动抛出异常:throw
输入错误的时候不要再打印错误。而是throw异常。
public class Students {
public static void main(String[] args) {
try {
Student student = new Student();
student.regist(-1001);
}catch (Exception e){
e.printStackTrace();
}
}
}
class Student{
private int id;
public void regist(int id) throws Exception{
if (id>0){
this.id = id;
}else {
// System.out.println("你输入的数据非法!");
// throw new RuntimeException("你的输入异常"); //运行时异常可以不处理
throw new Exception("你的输入异常");
}
}
}
六、用户自定义异常类
/*
如何自定义异常类?
1.继承与现有的异常结构,RuntimeException(不用考虑处理),Exception
2.提供全局常量 serialVersionUID
3.提供重载的构造器
*/
public class MyException extends RuntimeException{
static final long serialVersionUID = -7034897190745766939L; //序列化
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
七、练习
public class EcmDef {
public static void main(String[] args) {
// int i = Integer.parseInt(args[0]);
//int j = Integer.parseInt(args[1]); //也可能出现异常,属于运行时异常
try {
int i = Integer.parseInt(args[0]);
int j = Integer.parseInt(args[1]); //也可能出现异常,属于运行时异常
int result = ecm(i,j);
System.out.println(result);
}catch (NumberFormatException e){
System.out.println("数据类型不一致");
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("缺少命令行参数");
}catch (ArithmeticException e){
System.out.println("除0");
}catch (EcDef e){
System.out.println("自定义异常负数");
}
}
public static int ecm(int i,int j) throws EcDef{
if(i<0 ||j<0 ){
throw new EcDef("分子或分母为负数");
}
return i/j;
}
}
public class EcDef extends Exception{
static final long serialVersionUID = -3387516993124229948L;
public EcDef(){
}
public EcDef(String messege){
super(messege);
}
}
八、面试题
一)、类似的
1.final、finally、finalize三者的区别
2.throws和throw的区别
throw 表示抛出一个异常类的对象,生成异常对象的过程。声明在方法体内
throws 属于异常处理的一种方式,声明在方法的声明处。