java异常与错误处理基本知识

异常与错误:
异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它。Java中使用异常类来表示异常,不同的异常类代表了不同的异常。但是在Java中所有的异常都有一个基类,叫做Exception。
错误:它指的是一个合理的应用程序不能截获的严重的问题。大多数都是反常的情况。错误是VM的一个故障(虽然它可以是任何系统级的服务)。所以,错误是很难处理的,一般的开发人员(当然不是你)是无法处理这些错误的,比如内存溢出。 和异常一样,在Java中用错误类来表示错误,不同的错误类代表了不同的错误。 但是在Java中所有的错误都有一个基类,叫做Error。
综上,我们可以知道异常和错误最本质的区别就是异常能被开发人员处理而错误时系统本来自带的,一般无法处理也不需要我们程序员来处理。
1.一个异常是在一个程序执行过程中出现的一个事件,它中断了正常指令的运行
2.错误,偏离了可接受的代码行为的一个动作或实例
异常的结构分类:
1、运行时异常(未检查异常)
2、编译时异常(已检查异常)
运行异常即是RuntimeException;其余的全部为编译异常
在Java中异常Exception和错误Error有个共同的父类Throwable。
Error  Exception
runtimeException几个子类
1、 java.lang.ArrayIndexOutOfBoundsException
数组索引越界异常。当对数组的索引值为负数或大于等于数组大小时抛出。
2、java.lang.ArithmeticException
算术条件异常。譬如:整数除零等。
3、java.lang.NullPointerException
空指针异常。当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的
属性、计算null对象的长度、使用throw语句抛出null等等
4、java.lang.ClassNotFoundException
找不到类异常。当应用试图根据字符串形式的类名构造类,而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出
该异常。
对异常的处理:
try{}catch{}
try{}catch{}finally{}无论有无异常finally代码块都会被执行
try{}finally{}也是可以组合使用的但是catch{}finally{}不可以
注意:在继承关系中,子类覆盖父类的方法,抛出异常的范围不能比父类更宽泛

异常的使用
在异常的使用这一部分主要是演示代码,都是我们平常写代码的过程中会遇到的(当然只是一小部分),抛砖引玉吗!

例1. 这个例子主要通过两个方法对比来演示一下有了异常以后代码的执行流程。


代码如下:

public static void testException1() {
int[] ints = new int[] { 1, 2, 3, 4 };
System.out.println("异常出现前");
try {
System.out.println(ints[4]);
System.out.println("我还有幸执行到吗");// 发生异常以后,后面的代码不能被执行
} catch (IndexOutOfBoundsException e) {
System.out.println("数组越界错误");
}
System.out.println("异常出现后");
}
/*output:

异常出现前
数组越界错误
常出现后
*/
 代码如下 复制代码
public static void testException2() {
int[] ints = new int[] { 1, 2, 3, 4 };
System.out.println("异常出现前");
System.out.println(ints[4]);
System.out.println("我还有幸执行到吗");// 发生异常以后,他后面的代码不能被执行
}

首先指出例子中的不足之处,IndexOutofBoundsException是一个非受检异常,所以不用try...catch...显示捕捉,但是我的目的是对同一个异常用不同的处理方式,看它会有什么不同的而结果(这里也就只能用它将就一下了)。异常出现时第一个方法只是跳出了try块,但是它后面的代码会照样执行的。但是第二种就不一样了直接跳出了方法,比较强硬。从第一个方法中我们看到,try...catch...是一种"事务性"的保障,它的目的是保证程序在异常的情况下运行完毕,同时它还会告知程序员程序中出错的详细信息(这种详细信息有时要依赖于程序员设计)。
例2. 重新抛出异常


代码如下:

public class Rethrow {
public static void readFile(String file) throws FileNotFoundException {
try {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
System.err.println("不知道如何处理该异常或者根本不想处理它,但是不做处理又不合适,这是重新抛出异常交给上一级处理");
//重新抛出异常
throw e;
}
}

public static void printFile(String file) {
try {
readFile(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
printFile("D:/file");
}
}

异常的本意是好的,让我们试图修复程序,但是现实中我们修复的几率很小,我们很多时候就是用它来记录出错的信息。如果你厌倦了不停的处理异常,重新抛出异常对你来说可能是一个很好的解脱。原封不动的把这个异常抛给上一级,抛给调用这个方法的人,让他来费脑筋吧。这样看来,java异常(当然指的是受检异常)又给我们平添很多麻烦,尽管它的出发点是好的。

例3. 异常链的使用及异常丢失


代码如下:

ExceptionA,ExceptionB,ExceptionC
public class ExceptionA extends Exception {
public ExceptionA(String str) {
super();
}
}

public class ExceptionB extends ExceptionA {

public ExceptionB(String str) {
super(str);
}
}

public class ExceptionC extends ExceptionA {
public ExceptionC(String str) {
super(str);
}
}

异常丢失的情况:


代码如下:

public class NeverCaught {
static void f() throws ExceptionB{
throw new ExceptionB("exception b");
}

static void g() throws ExceptionC {
try {
f();
} catch (ExceptionB e) {
ExceptionC c = new ExceptionC("exception a");
throw c;
}
}

public static void main(String[] args) {
try {
g();
} catch (ExceptionC e) {
e.printStackTrace();
}
}

}
/*
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:19)
*/

为什么只是打印出来了ExceptionC而没有打印出ExceptionB呢?这个还是自己分析一下吧!
上面的情况相当于少了一种异常,这在我们排错的过程中非常的不利。那我们遇到上面的情况应该怎么办呢?这就是异常链的用武之地:保存异常信息,在抛出另外一个异常的同时不丢失原来的异常。


代码如下:

public class NeverCaught {
static void f() throws ExceptionB{
throw new ExceptionB("exception b");
}

static void g() throws ExceptionC {
try {
f();
} catch (ExceptionB e) {
ExceptionC c = new ExceptionC("exception a");
//异常连
c.initCause(e);
throw c;
}
}

public static void main(String[] args) {
try {
g();
} catch (ExceptionC e) {
e.printStackTrace();
}
}

}
/*
exception.ExceptionC
at exception.NeverCaught.g(NeverCaught.java:12)
at exception.NeverCaught.main(NeverCaught.java:21)
Caused by: exception.ExceptionB
at exception.NeverCaught.f(NeverCaught.java:5)
at exception.NeverCaught.g(NeverCaught.java:10)
... 1 more
*/

这个异常链的特性是所有异常均具备的,因为这个initCause()方法是从Throwable继承的。
例4. 清理工作
清理工作对于我们来说是必不可少的,因为如果一些消耗资源的操作,比如IO,JDBC。如果我们用完以后没有及时正确的关闭,那后果会很严重,这意味着内存泄露。异常的出现要求我们必须设计一种机制不论什么情况下,资源都能及时正确的清理。这就是finally。


代码如下:

public void readFile(String file) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
// do some other work
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

例子非常的简单,是一个读取文件的例子。这样的例子在JDBC操作中也非常的常见。(所以,我觉得对于资源的及时正确清理是一个程序员的基本素质之一。)
Try...finally结构也是保证资源正确关闭的一个手段。如果你不清楚代码执行过程中会发生什么异常情况会导致资源不能得到清理,那么你就用try对这段"可疑"代码进行包装,然后在finally中进行资源的清理。举一个例子:


代码如下:

public void readFile() {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// do some other work

//close reader
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

我们注意一下这个方法和上一个方法的区别,下一个人可能习惯更好一点,及早的关闭reader。但是往往事与愿违,因为在reader.close()以前异常随时可能发生,这样的代码结构不能预防任何异常的出现。因为程序会在异常出现的地方跳出,后面的代码不能执行(这在上面应经用实例证明过)。这时我们就可以用try...finally来改造:


代码如下:

public void readFile() {
BufferedReader reader = null;
try {
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// do some other work

// close reader
} finally {
reader.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

及早的关闭资源是一种良好的行为,因为时间越长你忘记关闭的可能性越大。这样在配合上try...finally就保证万无一失了(不要嫌麻烦,java就是这么中规中矩)。
再说一种情况,假如我想在构造方法中打开一个文件或者创建一个JDBC连接,因为我们要在其他的方法中使用这个资源,所以不能在构造方法中及早的将这个资源关闭。那我们是不是就没辙了呢?答案是否定的。看一下下面的例子:


代码如下:

public class ResourceInConstructor {
BufferedReader reader = null;
public ResourceInConstructor() {
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream("")));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

public void readFile() {
try {
while(reader.readLine()!=null) {
//do some work
}
} catch (IOException e) {
e.printStackTrace();
}
}

public void dispose() {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

这一部分讲的多了一点,但是异常确实是看起来容易用起来难的东西呀,java中还是有好多的东西需要深挖的

(0)

相关推荐

  • java 集合并发操作出现的异常ConcurrentModificationException

    如Java中的容器Map: for(Person person : pList){ if(person.getGender()==Gender.MALE){ pList.remove(person); //不能在遍历期间进行 remove这个操作 } } Map在遍历时候通常 现获得其键值的集合Set,然后用迭代器Iterator来对Map进行遍历. 注意在遍历的过程中,只能对Map中的元素进行相应的处理,不能把Map元素增加或者把Map元素减少,也就是说,不能改变Map的size大小,就会出现

  • Java中异常处理之try和catch代码块的使用

    Java try和catch的使用 尽管由Java运行时系统提供的默认异常处理程序对于调试是很有用的,但通常你希望自己处理异常.这样做有两个好处.第一,它允许你修正错误.第二,它防止程序自动终止.大多数用户对于在程序终止运行和在无论何时错误发生都会打印堆栈轨迹感到很烦恼(至少可以这么说).幸运的是,这很容易避免. 为防止和处理一个运行时错误,只需要把你所要监控的代码放进一个try块就可以了.紧跟着try块的,包括一个说明你希望捕获的错误类型的catch子句.完成这个任务很简单,下面的程序包含一个

  • 详解Java异常处理中throw与throws关键字的用法区别

    抛出异常 抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常.下面它们之间的异同. 系统自动抛异常 当程序语句出现一些逻辑错误.主义错误或类型转换错误时,系统会自动抛出异常.如: public static void main(String[] args) { int a = 5, b =0; System.out.println(5/b); //function(); } 系统会自动抛出ArithmeticException异常: Exception in threa

  • 浅谈java中异常抛出后代码是否会继续执行

    问题 今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢? public void add(int index, E element){ if(size >= elements.length) { throw new RuntimeException("顺序表已满,无法添加"); //return; //需要吗? } .... } 为了回答这个问题,我编写了几段代码测试了一下,结果如下: //代码1 public

  • 全面了解Java中对于异常的捕捉方法

    1. try-catch语句 在Java中,异常通过try-catch语句捕获.其一般语法形式为: try { // 可能会发生异常的程序代码 } catch (Type1 id1){ // 捕获并处置try抛出的异常类型Type1 } catch (Type2 id2){ //捕获并处置try抛出的异常类型Type2 } 关键词try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域.Java方法在运行过程中出现异常,则创建异常对象.将异常抛出监控区域之 外,由Java运行时系统试图寻

  • java 抛出异常处理的方法

    java 抛出异常处理的方法 为了避免调用的人不知道有异常,才抛出异常的,所以是谁掉用的久在哪里处理.说的对吗 对. 1.throws关键字通常被应用在声明方法时,用来指定可能抛出的异常.多个异常可以使用逗号隔开.当在主函数中调用该方法时,如果发生异常,就会将异常抛给指定异常对象. 如下面例子所示: public class Shoot { 创建类 static void pop() throws NegativeArraySizeException { //定义方法并抛出NegativeArr

  • 深入探讨JAVA中的异常与错误处理

    异常与错误: 异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception. 错误: 它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务).

  • Java中避免空指针异常的方法

    没人会喜欢空指针异常!有什么方法可以避免它们吗?或许吧.. 本文将讨论到以下几种技术 1.Optional类型(Java 8中新引入的) 2.Objects类(Java 7中原有的) Java 8中的Optional类 它是什么? 1.Java 8中新引入的类型 2.它是作为某个指定类型的对象的包装器或者用于那些不存在对象(null)的场景 简单来说,它是处理空值的一个更好的替代品(警告:乍一看可能并没有那么明显) 基本用法 它是一种类型(一个类)--那么,怎么才能创建一个这个类型的实例? 使用

  • java异常与错误处理基本知识

    异常与错误:异常: 在Java中程序的错误主要是语法错误和语义错误,一个程序在编译和运行时出现的错误我们统一称之为异常,它是VM(虚拟机)通知你的一种方式,通过这种方式,VM让你知道,你(开发人员)已经犯了个错误,现在有一个机会来修改它.Java中使用异常类来表示异常,不同的异常类代表了不同的异常.但是在Java中所有的异常都有一个基类,叫做Exception.错误:它指的是一个合理的应用程序不能截获的严重的问题.大多数都是反常的情况.错误是VM的一个故障(虽然它可以是任何系统级的服务).所以,

  • java异常和错误类总结(必看篇)

    java异常和错误类总结 最近由于考试和以前的面试经常会遇到java当中异常类的继承层次的问题,弄得非常头大,因为java的异常实在是有点多,很难记下来,今天正好查了一些资料整理下来,希望对自己和大家有点帮助.最开始的时候习惯用笔记本(手写的纸质的本子)记笔记,后来发现查阅的时候不是很方便,而且速度比较慢.后来改用notepad开始记,感觉效果挺棒,简单易用,没有花哨的东西.但是也有它的缺点,比如版式的整理,不能加入一些图片(往往图片特别是一些大纲是非常好的记忆学习方法)等等,于是尝试用mark

  • Java异常基础知识解析

    Java程序运行的非正常现象叫做运行错误,根据其性质可分为两类:错误(Error)和异常(Exception); 他们有一个共同的父类(也是所有异常的顶级父类):Throwable. 异常类结构 Error Error(错误)由JVM生成并抛弃不做处理:此类错误通常与代码和执行的操作无关,是虚拟机中出现了比较严重的问题,程序本身无法解决(常见的错误有死循环.内存泄漏等). 一个常见的错误为Java虚拟机错误(VirtualMachineError),当JVM不再有继续执行操作所需的内存资源时,将

  • Java 异常的知识整理

    Java 异常 1.继承关系 2.Error 程序运行时发生的无法被处理的错误,一旦发生,JVM终止执行. 3.Exception Exception是程序编译与运行时出现的一种错误,一旦出现,JVM将告知程序员处理. 分为两种: 运行时异常:在运行时发生,RuntimeException类及子类.编译时不需要处理,发生在运行阶段.常见的有NullPointerException\StringIndexOutOfBounds \ClassCastException  \ArrayIndexOut

  • 解析Java中所有错误和异常的父类java.lang.Throwable

    在java语言中,错误类的基类是java.lang.Error,异常类的基类是java.lang.Exception. 1)相同点:java.lang.Error和java.lang.Exception都是java.lang.Throwable的子类,因此java.lang.Error和java.lang.Exception自身及其子类都可以作为throw的使用对象,如:throw new MyError();和throw new MyException();其中,MyError类是java.l

  • Java异常学习之自定义异常详解

    前言 哎呀,妈呀,又出异常了!俗话说:"代码虐我千百遍,我待代码如初恋". 小Alan最近一直在忙着工作,已经很久没有写写东西来加深自己的理解了,今天来跟大家聊聊Java异常.Java异常的体系什么的,理论知识啥的我就懒得去BB太多了,是个搞Java开发的都知道,只是可能理解的不深,这个大家可以自己多看看资料,我就简单的说说. 什么是异常? 我不知道大家都是怎么去理解的,我的理解很简单,那就是不正常的情况,比如我现在是个男的,但是我却有着女人所独有的东西,在我看来这尼玛肯定是种异常,简

  • java异常(Exception)处理机制详解

    一. 异常的定义 在<Java编程思想>中这样定义 异常:阻止当前方法或作用域继续执行的问题.虽然java中有异常处理机制,但是要明确一点,决不应该用"正常"的态度来看待异常.绝对一点说异常就是某种意义上的错误,就是问题,它可能会导致程序失败.之所以java要提出异常处理机制,就是要告诉开发人员,你的程序出现了不正常的情况,请注意. 记得当初学习java的时候,异常总是搞不太清楚,不知道这个异常是什么意思,为什么会有这个机制?但是随着知识的积累逐渐也对异常有一点感觉了.举一

  • java.lang.NoClassDefFoundError错误解决办法

    java.lang.NoClassDefFoundError错误解决办法 前言 在日常Java开发中,我们经常碰到java.lang.NoClassDefFoundError这样的错误,需要花费很多时间去找错误的原因,具体是哪个类不见了?类明明还在,为什么找不到?而且我们很容易把java.lang.NoClassDefFoundError和java.lang.ClassNotfoundException这两个错误搞混,事实上这两个错误是完全不同的.我们往往花费时间去不断尝试一些其他的方法去解决这

  • 一文给你通俗易懂的讲解Java异常

    什么是异常? 最简单的,看一个代码示例: public static void main(String[] args) { int a = 1; int b = 0; System.out.println(a / b); } 这段代码有什么问题?简单,除数不能为0对吧,我们打印输出: 显而易见,程序出问题了,不能正常执行了,这里出现了一些爆红的信息,这些就是异常提示,这就是Java中提供的异常机制,当你的程序存在问题的情况下,会给你打印输出一些信息,这个就叫做异常信息. 字面意思上去理解,所谓"

随机推荐