掌握:一个图(分类)、五个关键字(try catch finally throws throw)

一、概念

定义:

异常指的是运行期出现的错误(如除0溢出,空指针,数组/字符串下标越界,所要读取的文件不存在),它中断了正在执行的程序的正常指令流。

良好的程序应该在异常发生时提供处理方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果。

补充知识:c和c++中不检查数组越界??如果程序员也没有自己处理数组越界,会存在缓冲区溢出的漏洞,这可能被黑客利用来更改保存现场时的程序地址,运行黑客程序。

二、异常的分类

  Throwable是异常的根类。其中,Error类是系统错误(虚拟机错误),我们处理不了的异常;Exception是所有异常类的父类,我们能够处理的,可以catch。Exception中的RuntimeException(也就是uncheckException)是经常出现的错误(如a/b,数组越界等),这种错误系统可以自动检测并处理,可以catch,也可以不catch;其他错误(如IO错误等)必须catch(常见的是JDK中的类方法中写了throws的Exception)。

例1:public static int parseInt(String s,int radix)throws NumberFormatException

  所抛出的异常NumberFormatException属于RuntimeException。但是如果程序中不用try-catch处理,虽然可以运行,但是抛出异常后面的语句则无法运行了。

  如果用try-catch处理,则抛出异常后,程序依然可以向下运行。

public class Test{
public static void main(String args[]){
try{
String str = "lili";
System.out.println(str+"年龄是:");
int age = Integer.parseInt("20L");
System.out.println(age);
}catch(Exception e){
//System.out.println(e.getMessage());
System.out.println(e.toString());
//e.printStackTrace();
}
System.out.println("program over"); //不使用try-catch则不输出本句话
}
}

输出:

lili年龄是:
java.lang.NumberFormatException: For input string: "20L"
program over

例2:对于不是RuntimeException的异常。必须写try-catch或用throws向上抛出。否则无法通过编译。如IOException。

三、异常的处理方法

  Java程序执行过程中,如果出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息并将被提交给Java运行时系统,这个过程成为抛出(throw)异常;当Java运行时系统接收到异常对象时,会寻找能够处理这一异常的代码(try-catch),并把当前异常对象交给其处理,这一过程成为捕获(catch)异常;如果没有catch,那么系统自己按照默认方式处理(printStackTrace()方法,打印错误的堆栈信息)。

  某个方法抛出异常,既可以在当前方法中try-catch捕获后处理;也可以用throws将异常继续向上抛出,由方法调用者来处理。

1、在当前方法中捕获后处理

  异常产生后,如果不做任何处理,程序就会终止,不再执行下面语句。异常捕获结构由try,catch,finally三部分组成。

注意:执行完catch代码块后,继续执行catch代码块后面的的语句,但不会执行try中发生异常语句之后的语句。由此可见,这样就不会因为一个异常影响整个程序的执行。

注意:catch中一定要做出相应处理,哪怕是打印信息也行!多个catch语句时,注意先捕获子类异常再捕获基类异常。

(1)异常处理中3个常用函数:

getMessage()            //错误的性质

toString()                 //异常的类型和性质

printStackTrace()      //输出异常的类型、性质、栈层次、出现在程序中的位置

(2)finally语句

  完整的异常处理语句一定要包含finally,finally是总会执行的语句。除非以下四种特殊情况发生,finally才不会执行:

(1)在finally语句块中发生了异常

(2)在前面代码中用了System.exit()退出程序

(3)程序所在的线程死亡

(4)关闭CPU

注意:前面的代码中就算有return语句,finally还是会执行!

2、在方法中抛出异常(将异常继续向上抛出)

  若某个方法可能发生异常,但不想在当前方法中处理这个异常,那么可以使用throws关键字声明方法抛出异常。

(1)throws应用于声明方法时,用来指定方法可能抛出的异常,多个异常用逗号分隔。

  只用throws将异常向上抛出后,如果不想在上一级处理则可以继续抛出,但是最终要有能够处理该异常的代码。

注意:Error,RuntimeException及它们的子类,可以不用throws抛出。但运行时会被系统抛出。

注意:main方法中throws抛出异常非常不好!

(2)异常对象的产生途径有两种:JVM自动生成的和throw手动生成的。也就是说:throw并不是必须的,它一般用于抛出用户自定义异常。

  throw用于方法体中,抛出一个异常对象。throw通常用来抛出用户自定义异常。程序执行到throw时立即终止,它后面的语句都不再执行。

  通过throw抛出异常后,如果想在上一级捕获处理,则需要在抛出异常的方法中使用throws声明;如果要捕获throw抛出的异常,则必须使用try-catch。(必须catch处理的异常)

四、用户自定义的异常

  自定义异常,只需要继承Exception类即可。使用自定义异常类,分一下几步:

(1)通过继承Exception类或RuntimeException类创建自定义异常类

(2)在方法中通过throw抛出异常对象

(3)如果在当前抛出异常的方法中处理异常,可以使用try-catch

(4)否则在方法声明处使用throws向上抛出,在出现异常方法的调用者中使用try-catch

public class Test{
static int quotient(int x,int y) throws MyException{
if(y<0){
throw new MyException("除数不能为负");
}
return x/y;
}
public static void main(String args[]){
try{
int result = quotient(3,-1);
}catch(MyException e){
System.out.println(e.getMessage());
}catch(ArithmeticException e){
System.out.println("除数不能为0");
}catch(Exception e){
System.out.println("其他错误");
}
}
}
class MyException extends Exception{
String message;
public MyException(String s){
message = s;
}
public String getMessage(){//重写getMessage()方法
return message;
}
}

输出:

除数不能为负

五、重写与异常

class A{
protected void fun(int a,int b) throws IOException{
}
} class B extends A{
public void fun(int a,int b) throws FileNotFoundException{
}
}

总结:关于java中方法重写(override)的要求:
     1、子类中的方法与父类中的方法有相同的返回类型(例如:一个是int,一个是float,则编译出错)
     2、子类中的方法与父类中的方法有相同的方法名称
     3、子类中的方法与父类中的方法有相同的参数列表
     4、子类中的方法的访问级别不能低于父类中该方法的访问级别(举例:父类方法的级别是protected,那么子类重写该方法,其级别必须是protected或者public,一定和父类的访问级别相同或者更宽,否则编译无法通过)
     5、子类中方法抛出的异常范围不能大于父类中方法抛出的异常的范围。

  即重写方法需要抛出与原方法所抛出异常类型一致的异常(相同的异常或子类的异常)或不抛出异常。不能抛出新异常!如果父类不抛异常,子类不能抛异常!

如:原来抛出IOException,重写后抛出FileNotFoundException,但不能抛出Exception(编译出错!)。

个人理解:后两条是为了保证程序的可扩展性。例如一个方法之前没有被重写,现在在其子类中重写该方法:如果子类中的访问权限低于父类,就有可能造成上层调用者无法访问该重写方法的情况;再如如果一个方法重写后抛出的异常是之前父类方法中不包括的类型,那么可能造成调用者无法处理该异常的情况。

JAVA笔记13-异常处理Exception的更多相关文章

  1. java 异常和异常处理Exception

    Java Exception: 1.Error 2.Runtime Exception 运行时异常3.Exception 4.throw 用户自定义异常 异常类分两大类型:Error类代表了编译和系统 ...

  2. Thinking in Java——笔记(13)

    Strings Immutable Strings Objects of the String class are immutable. Every method in the class that ...

  3. Java笔记13:统计文件中每个字符出现的次数

    一.代码实现 import java.io.*; import java.util.*; /** 功能:统计文件中每个字符出现的次数 思路: 1.定义字符读取(缓冲)流 2.循环读取文件里的字符,用一 ...

  4. java笔记13之成员变量与局部变量

    成员变量和局部变量的区别 1在类中的位置不同 局部变量:类的方法体内 成员变量:类的方法之外 2内存的不同位置 局部变量:在栈内存中 成员位置:在堆内存 3生命周期不同 局部变量:随着方法的调用而存在 ...

  5. java异常处理Exception

    我看别人的面经中有一道题目就问到了Exception,即java的异常处理的,我曾经也学了java的异常处理,可是我查了下,看了别人的博客关于写的exception异常处理.我发现,自己学的不坚固,仅 ...

  6. JAVA自学笔记13

    JAVA自学笔记13 1.StringBuffer类 1)线程安全的可变字符序列 线程安全(即同步) 2)StringBuffer与String的区别:一个可变一个不可变 3)构造方法: ①publi ...

  7. Java 学习笔记(11)——异常处理

    异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error:如果你用System.ou ...

  8. java笔记整理

    Java 笔记整理 包含内容     Unix Java 基础, 数据库(Oracle jdbc Hibernate pl/sql), web, JSP, Struts, Ajax Spring, E ...

  9. Java笔记(二十六)……IO流上 字节流与字符流

    概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为:字节流和字符流 流按流向不同分为:输入流和输出流 IO流常用基类 ...

  10. Core Java笔记

    前言 一·基础知识 二·定义,关键字和类型 三·表达式和控制流 四·数组 五·对象和类 六·高级语言特性 七·异常 八·图形用户接口 九·AWT(Abstract Window Toolkit) 事件 ...

随机推荐

  1. gradle自动刷新

    1.gradle每次更新build.gradle都要刷新一下才能下载依赖 这样显得不太方便. 2.可以在Preferences修改配置来达到自动刷新的目的 如图所示,直接勾选即可,自动同步项目

  2. cocos2dx[3.2](11) 新事件分发机制

    在2.x中处理事件需要用到委托代理(delegate),相信学过2.x的触摸事件的同学,都知道创建和移除的流程十分繁琐. 而在3.x中由于加入了C++11的特性,而对事件的分发机制通过事件分发器Eve ...

  3. python 迭代器(第二次总结)

    迭代器 1.先明白迭代器是什么意思 迭代:不断的取值的(器)工具 迭代器:就是一个重复的过程,每一次重复都是基于上一次的结果而来的. (单纯的重复不是迭代) 2.为什么要有迭代器 不依赖索引取值的方法 ...

  4. vue--生命周期演示

    vue实例的生命周期:https://cn.vuejs.org/v2/guide/instance.html#%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA-Vue-%E5% ...

  5. Elasticsearch-索引新数据(创建索引、添加数据)

    ES-索引新数据 0.通过mapping映射新建索引 CURL -XPOST 'localhost:9200/test/index?pretty' -d '{ "mappings" ...

  6. Python 把较长的一行代码分成多行的技巧

    概述:在写代码过程中,经常遇到一行代码很长的情况.为了让代码显得整齐干净,就需要把一行代码分成多行来写,Python中有三种小技巧可以实现该功能:        1.用反斜杠\链接多行代码 示例:   ...

  7. 编辑器IDE之VSCode

    很多时候面临换项目组,公司内部换等等,需要清除之前的权限,电脑更换等... 确实很烦人,所以记录也是给自己下次更加快速方便的使用 插件安装 个人常用的一些插件,发现好用的会更新 插件名 功能 vsco ...

  8. RabbitMQ入门教程(十一):消息属性Properties

    原文:RabbitMQ入门教程(十一):消息属性Properties 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://b ...

  9. 2019-11-29-dotnet-获取指定进程的输入命令行

    title author date CreateTime categories dotnet 获取指定进程的输入命令行 lindexi 2019-11-29 08:35:11 +0800 2019-0 ...

  10. 安装最新版本的kubernets(+安装插件dashboard)

    一.安装docker // 安装系统工具: sudo yum install -y yum-utils device-mapper-persistent-data lvm2 // 添加docker y ...