当前位置: 移动技术网 > IT编程>开发语言>Java > JavaSE异常处理(异常分类、异常实际作用)

JavaSE异常处理(异常分类、异常实际作用)

2020年08月10日  | 移动技术网IT编程  | 我要评论



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负责调用

本文地址:https://blog.csdn.net/RTyinying/article/details/107896903

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网