JavaSE进阶 第八章 异常处理

1.异常的基本概念

什么是异常:程序执行过程中的不正常情况
异常的作用:增强程序的健壮性
异常在java中以类的形式存在,每一个异常类都可以创建异常对象

2.异常的分类

2.1异常的层次结构

可以使用UML图来描述异常的继承结构
UML是一种统一建模语言,图标式语言,可在面向对象的编程语言中使用,用来描述类与类之间的关系,程序的执行流程,对象的状态等。Java软件开发中,软件设计师、系统分析师、架构师设计类,java软件开发人员必须能够看懂
常用软件:Rational Rose、startUML…
Object下有Throwable
Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)
在这里插入图片描述

2.2异常的分类

在这里插入图片描述
Exception下有两个分支:
(1)Exception的直接子类:编译时异常(受检异常、受控异常、CheckedException)
(2)RuntimeException:运行是异常(未受检异常、未受控异常、UncheckedException)

2.2.1编译时异常

要求程序员在编写阶段必须预先对这些异常预先进行处理,如果不处理编译器会报错
编译时异常一般发生的概率你较高

2.2.2运行时异常

在编写阶段程序员可以预先处理,也可以不管
运行时异常一般发生的概率比较低

2.2.3异常的处理方法
  • 在方法声明的位置上,使用throws关键字(调用者会接收异常)
  • 使用try…catch语句进行异常的捕获(调用者并不知道异常发生并被解决了)
    注意:在java中异常发生后如果一直上抛,会抛给main方法,main方法抛给JVM,JVM只能终止程序的执行
public static void main(String[] args) throws ClassNotFoundException { //不建议在主方法上继续上抛
	doSome();
}
public static void main(String[] args){
	try{
		doSome();
	}catch (ClassNotFoundException e){
		e.printStackTrace();
		//e引用保存的内存地址是那个new出来的异常对象的内存地址
	}
}

注意:

  • 异常没有捕捉,而采取上抛的方式,异常发生后,该方法的后续代码不会执行
  • try语句块中的,某一行出现异常,该行后面的代码不会执行
  • try…catch捕捉异常后,后续代码可以执行
  • 编译时异常和运行时异常都发生在运行阶段,因为只有程序再运行阶段才可以new对象
    (异常的发生就是在new对象)
  • 如何选择上抛还是捕获:如果希望调用者来处理,选择throws上抛

2.3try、catch和finally

2.3.1深入try…catch
  • catch后面的小括号中的类型可以是具体的异常类型,也可以是异常类型的父类
  • catch可以写多个,建议精确的一个一个处理,这样有利于程序的调试
  • catch写多个是,从上到下,必须遵守异常类从小到大的关系
try{
	FileInputStream fis = new FileInputStream("D:\\scripts\\IdeaProjects")
	fis.read();
}catch(FileNotFoundException e){
	System.out.println("文件不存在");
}catch(IOException e){
	e.printStackTrace();
}

JDK8新特性

try{
}catch(FileNotFoundException | IOException e){
	e.printStackTrace();
}
2.3.2 finally关键字

通常在finally语句块中完成资源的释放、关闭
finally中的代码比较有保障,是“一定”会执行的
即使try语句块中的代码出现异常,finally中的代码也会正常执行

2.3.2.1 finally的使用

try不能单独使用,try、finally可以联合使用:以下代码先执行try…再执行finally…最后执行return(方法结束)

try{
	System.out.println("try...");
	return;
}finally{
	System.out.println("finally...");
}
public class ExceptionTest{
	public static void main(String[] args){
		FileInputStream fis = null;//声明位置放在try外面,这样在finally中才能使用
		try{
			FileInputStream fis = new FileInputInputStream("D:\\stripts")

			String s = null
			s.toString();

			//fis.close();流用完需要关闭,即使程序异常也需要关闭。但这里执行不到关闭流			
		}catch(FileNotFoundException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}finally{
			//流的关闭放在这里比较保险
			if(fis != null){
			try{
				fis.close();
			}catch(IOException e){
				e.printStackTrace();
			}
		}
	}
}
try{
	System.out.println("try...");
	System.exit(0); //退出JVM后,finally语句中的代码将不再执行
}finally{
	System.out.println("finally...");
}
2.3.2.2 finally面试题
public class ExceptionTest{
	public static void main(String[] args){
		int result = m();
		System.out.println(result); //100
	}

	public static int m();
	int i = 100;
	try{
		return i;
	}finally{
		i++;
	}
}

通过反编译工具:DJ Java Decompiler

public static int m(){
	int i =100;
	int j = i;
	i++;
	return j;
}

Java语法规则结论:

  • 方法体中的代码必须遵循自上而下的顺序依次逐行执行
  • return语句一旦执行,整个方法必须结束

2.4getMessage和printStackTrace

try{
}catch(FileNotFoundException e){
	//打印异常堆栈追踪信息。实际开发中,建议使用这个
	e.printStackTrace();
	//获取异常简单的描述信息	
	String msg = e.getMassage();
}
System.out.println("HelloWorld");//捕获异常后,程序不耽误执行,服务器不会遇到异常而宕机
2.4.1getMEssage()
public class ExceptionTest(){
	public static void main(String[] args){
		NullPointerException e = new NullPointerException("空指针异常");
		String msg = e.getMessage();
		System.out.println(msg);//空指针异常
		//这里只是new了异常对象,并没有将异常对象抛出,JVM会认为只是一个普通的java对象

		e.printStackTrace();
	}
}
2.4.2printStackTrace()

如何查看异常的追踪信息,从而快速调试程序呢?
异常堆栈追踪信息从上往下一行一行的看,SUN写的代码不需要检查,问题出在自己编写的代码上
java后台打印异常堆栈追踪信息的时候,采用了异步线程的方式打印

3.如何自定义异常

SUN提供的JDK内置异常在实际开发中不够用,可以自定义异常类
步骤:

  • 编写一个类继承Exception或者RuntimeException
  • 提供两个构造方法,一个无参数的,一个带有String参数的
public class MyException extends Exception{//编译时异常
	public MyException{
	}
	public MyException(String s){
		super(s);
	}
} 
//public class MyException extends RunTimeException{}//运行时异常
public class ExceptionTest{
	public static void main(String[] args){
	//创建异常对象,灵位手动抛出
		MyException e = new MyException("芜湖~~");
		e.printStackTrace();//打印异常堆栈信息
		Striong msg = e.getMessage();//获取简单异常信息
		System.out.println(msg);
	}
}

4.异常在实际开发中的作用

重点:自定义异常类,在程序中使用

4.1数组模拟压栈弹栈

public class MyStackOperationException extends Exception{
	public MyStackOperationException{
	
	}
	public MyStackOperationException(String s){
		super(s);
	}
} 
public class MyStack {
    private Object[] elements;
    private int index;

    public MyStack() {
        this.elements =new Object[10];
        this.index = -1;
    }

   public void push(Object obj) throws MyStackOperationException{
	if(index >=elements.length-1){
		throw new MyStackOperationException("压栈失败,栈已满!")
	}
	 index++;
        elements[index]=obj;
        System.out.println("压栈"+obj+"成功,栈帧指向"+index);
    }

    public void pop() throws MyStackOperationException{
        if(index<0){
           throw new MyStackOperationException("栈已空!")
        }
        System.out.println("弹栈"+elements[index]+"元素成功");
        index--;
        System.out.println("栈帧指向"+index);
    }

    public Object[] getElements() {
        return elements;
    }

    public void setElements(Object[] elements) {
        this.elements = elements;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
}
public class MyStackTest {
    public static void main(String[] args) {
        MyStack stack = new MyStack();
       // 压栈
        try {
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            stack.push(new Object());
            // 这里栈满了
            stack.push(new Object());
        } catch (MyStackOperationException e) {
            // 输出异常的简单信息。
            System.out.println(e.getMessage());
        }

        // 弹栈
        try {
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            stack.pop();
            // 弹栈失败
            stack.pop();
        } catch (MyStackOperationException e) {
            System.out.println(e.getMessage());
        }
	}
}

4.2用户注册

public class IllegalNameException extends Exception {
    public IllegalNameException() {
    }
    public IllegalNameException(String message) {
        super(message);
    }
}
public class UserService {
    /**
     * 用户注册
     * @param username 用户名
     * @param password 密码
     * @throws IllegalNameException 无效
     */
    public void register(String username, String password) throws IllegalNameException {
        if (null == username || username.length() < 6 || username.length() > 14) {
            throw new IllegalNameException("用户名不合法");
        }
        System.out.println("注册成功,欢迎"+username);
    }
}
public class Tset {
    public static void main(String[] args) {
        UserService userService = new UserService();
        try {
            userService.register("日天家的猫猫","1234578");
        } catch (IllegalNameException e) {
            System.out.println(e.getMessage());
        }
    }
}

5.方法覆盖与异常

重写之后的方法不能比重写之前的方法抛出更多的异常,可以更少
实际开发中方法覆盖时一般不做修改,直接复制

6.总结异常中的关键字

  • try
  • catch
  • fianlly
  • throws 在方法声明的位置上使用,表示上报异常信息给调用者
  • throw 手动抛出异常

7.final、fianlly与finalize的区别

final 关键字

  • fianl修饰的类无法继承
  • final修饰的方法无法覆盖
  • fianl修饰的变量无法重新复制

finally 关键字

  • 与try一起联合使用
  • finally语句块中的代码时不需执行的

finalize 标识符

  • 是一个Object类中的方法名
  • 有垃圾回收器GC负责调用

传送门

上一篇:JavaSE进阶 第七章 常用类 (七) 枚举类型
下一篇:JavaSE进阶 第九章 泛型

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值