欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-26 16:39:41
目录1.异常的基本概念2.异常的分类2.1异常的层次结构2.2异常的分类2.2.1编译时异常2.2.2运行时异常2.2.3异常的处理方法2.3try、catch和finally2.3.1深入try...catch2.3.2 finally关键字2.3.2.1 finally的使用2.3.2.2 finally面试题2.4getMessage和printStackTrace2.4.1getMEssage()2.4.2printStackTrace()3.如何自定义异常4.异常在实际开发中的作用5.方法覆盖与异...



1.异常的基本概念

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

2.异常的分类

2.1异常的层次结构

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

2.2异常的分类

JavaSE异常处理(异常分类、异常实际作用)
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

相关标签: JavaSE java异常