一天一个Java基础——通过异常处理错误

《Thinking in Java》上对这章的讲解不少,可见重要性,学习和总结一些主要的记录下来。

一、创建自定义异常


 1 package Exception;
 2
 3 class SimpleException extends Exception{}
 4
 5 public class InheritingException{
 6
 7     public void f() throws SimpleException {
 8         System.out.println("Throw SimpleException from f()");
 9         throw new SimpleException();
10     }
11
12     public static void main(String[] args) {
13         InheritingException sed = new InheritingException();
14         try {
15             sed.f();
16         } catch (SimpleException e) {
17             e.printStackTrace();
18         }
19     }
20
21 }
1 输出:
2 Throw SimpleException from f()
3 Exception.SimpleException
4     at Exception.InheritingException.f(InheritingException.java:10)
5     at Exception.InheritingException.main(InheritingException.java:19)

  throw与throws的区别与详情

  编译器创建了默认构造器,它将自动调用基类的默认构造器。

  对异常来说,最重要的部分就是类名,其它也没用,可以增加一个带参的构造方法。

  比如NullPointerException:

 1 public
 2 class NullPointerException extends RuntimeException {
 3     private static final long serialVersionUID = 5162710183389028792L;
 4
 5     /**
 6      * Constructs a {@code NullPointerException} with no detail message.
 7      */
 8     public NullPointerException() {
 9         super();
10     }
11
12     /**
13      * Constructs a {@code NullPointerException} with the specified
14      * detail message.
15      *
16      * @param   s   the detail message.
17      */
18     public NullPointerException(String s) {
19         super(s);
20     }
21 }

二、捕获异常



  1)try块

    如果在方法内部抛出了异常(或者在方法内部调用的其他方法抛出了异常),这个方法将在抛出异常的过程中结束。

    要是不希望方法就此结束,可以在方法内设置一个特殊的块来捕获异常。

try{
  //exceptions
}

  2)异常处理程序

    异常处理程序紧跟在try块之后,以关键字catch表示:

try{
  //exceptions
} catch(Type1 id1) {
  //Type1
} catch(Type2 id2) {
  //Type2
}

    当异常被抛出时,异常处理机制将负责搜寻参数与异常类型相匹配的第一个处理程序。然后进入catch子句执行,此时认为异常得到了处理。

    注意,只有匹配的catch子句才能得到执行,这与switch语句不同。

  3)栈轨迹

    printStackTrace()方法所提供的信息可以通过getStackTrace()方法来直接访问,这个方法将返回一个由栈轨迹中的元素所构成的数组,其中每一个元素都表示

  栈中的一帧。元素0是栈顶元素,并且是调用序列中的最后一个方法调用。数组中最后一个元素和栈底是调用序列中的第一个方法调用。

 1 public class WhoCalled {
 2     static void f() {
 3         try {
 4             throw new Exception();
 5         } catch (Exception e) {
 6             for(StackTraceElement ste : e.getStackTrace()) {
 7                 System.out.println("line: " + ste.getLineNumber() + " method: " + ste.getMethodName());
 8             }
 9         }
10     }
11     static void g() {f();}
12     static void h() {g();}
13     public static void main(String[] args) {f();g();h();}
14 }

三、Java标准异常



  Throwable这个Java类被用来表示任何可以作为异常被抛出的类。

  Throwable对象可分为两种类型:

    • Error用来表示编译时和系统错误。
    • Exception是可以被抛出的基本类型,程序员关心的基类型通常是Exception。

四、RuntimeException


if(t == null) {
  throw new NullPointerException();
}

  如果对Null引用进行调用,Java会自动抛出NullPointerException异常,所以上述代码是多余的,它属于Java的标准运行时检测的一部分:

1 public class NeverCaught {
2     static void f() {
3         throw new RuntimeException();
4     }
5     static void g() {f();}
6     public static void main(String[] args) {
7         g();
8     }
9 }
1 输出:
2 Exception in thread "main" java.lang.RuntimeException
3     at Exception.NeverCaught.f(NeverCaught.java:6)
4     at Exception.NeverCaught.g(NeverCaught.java:10)
5     at Exception.NeverCaught.main(NeverCaught.java:14)

  从输出可以发现,RuntimeException是一个特例,对于这种异常类型,编译器不需要异常说明,其输出被报告给了System.err。

  如果RuntimeException没有被捕获而直达main(),那么在程序退出前将调用异常的printStackTrace()方法。

  *注意:

    只能在代码中忽略RuntimeException(及其子类)类型的异常,其它异常类型的处理都是由编译器强制实施的。

  1)常见的五种RuntimeException

 1 NullPointerException - 空指针引用异常
 2 ClassCastException - 类型强制转换异常
 3 IllegalArgumentException - 传递非法参数异常
 4 ArithmeticException - 算术运算异常
 5 ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
 6 IndexOutOfBoundsException - 下标越界异常
 7 NegativeArraySizeException - 创建一个大小为负数的数组错误异常
 8 NumberFormatException - 数字格式异常
 9 SecurityException - 安全异常
10 UnsupportedOperationException - 不支持的操作异常

六、使用finally进行清理


 1 class ThreeException extends Exception {}
 2 public class FinallyWorks {
 3     static int count = 0;
 4     public static void main(String[] args) {
 5         while(true) {
 6             try {
 7                 if(count++ == 0) {
 8                     throw new ThreeException();
 9                 }
10                 System.out.println("No exception");
11             } catch (ThreeException e) {
12                 System.out.println("ThreeException");
13             } finally {
14                 System.out.println("In finally clause");
15                 if(count == 2)
16                     break;
17             }
18         }
19     }
20 }

  这个程序给了我们一些思路(确实。。),如果把try块放在循环里,就建立了一个“程序继续执行之前必须要到达”的条件。

  还可以加入一个static类型的计数器或者别的装置,使循环在放弃之前能够尝试一定的次数。这将使程序的健壮性更上一个台阶(好叼的样子)。

  1)finally用来做什么

    当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句。

  2)在return中使用finally

    因为finally子句总是会执行的,所以在一个方法中,可以从多个点返回,并且可以保证重要的清理工作仍旧会执行:

 1 class ThreeException extends Exception {}
 2 public class FinallyWorks {
 3     static int count = 0;
 4     public static void main(String[] args) {
 5         while(true) {
 6             try {
 7                 if(count++ == 0) {
 8                     throw new ThreeException();
 9                 }
10                 System.out.println("No exception");
11                 return;
12             } catch (ThreeException e) {
13                 System.out.println("ThreeException");
14             } finally {
15                 System.out.println("In finally clause");
16                 if(count == 3)
17                     break;
18             }
19         }
20     }
21 }

  第一次循环,首先执行第7行,符合条件,抛出异常,执行catch块,最后执行finally清理,不符合第16行判断,继续循环

  第二次循环,不符合第7行判断,抛出异常,并return,但依旧执行finally清理,不符合第16行判断,但try块中已经执行return,所以程序结束,输出:

ThreeException
In finally clause
No exception
In finally clause

  3)Java异常的缺憾:异常丢失

1 public class ExceptionSilencer {
2     public static void main(String[] args) {
3         try {
4             throw new RuntimeException();
5         } finally {
6             return;
7         }
8     }
9 }

    发现输出为空

时间: 2024-10-07 06:13:47

一天一个Java基础——通过异常处理错误的相关文章

一个Java基础练习

com聚合是包容的一种特例,目的是最大化的实现功能模块话,降低组件间的耦合性. 第一步: 通过ATL创建com外部组件TestOutCom.dll,在其内部创建接口包装类CCMyOuterCom,并实现其对应的接口ICMyOuterCom,注意默认选择"聚合"(这点很重要,后面我们会详细解说) 在"聚合"选项中: 勾选"是",则按照默认生成支持聚合的包装类 勾选"否",则包装类头文件CMyOuterCom.h,在公开接口列表字

一天一个Java基础——泛型

这学期的新课——设计模式,由我仰慕已久的老师传授,可惜思维过快,第一节就被老师挑中上去敲代码,自此在心里烙下了阴影,都是Java基础欠下的债 这学期的新课——算法设计与分析,虽老师不爱与同学互动式的讲课,但老师讲的挺好,不过由于数据结构欠缺课听的有点烧脑,都是数据结构欠下的债 这学期的新课——英语口语,虽外教老师风骚逗趣浪荡不羁爱自由,但我辈词汇量欠缺,表明淡定说yeah,但心中一万匹草泥马策马奔腾,都是英语欠下的债 1.泛型类 实体类(容器类),经常重用的类,下面是一个没有用泛型的实体类: 1

java基础篇---异常处理

认识异常 异常时导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,造成不必要的损失,所以在程序的设计中必须考虑各种异常的发生,并正确的做好相应的处理,这样才能保证程序的正常执行,在java使用一种称为异常处理的错误捕获机制处理. 为了能在程序中处理异常情况,必须研究程序中可能会出现的错误和问题 用户输入错误() 设备错误 物理限制(磁盘满了,) 代码错误(程序方法有可能无法正常执行) 处理异常 异常处理的简单格式 如果在try语句块中的任何代码抛出一个在catc

Java基础之异常处理(五)

运行期出现的错误,非编译错误,观察错误的名称和行号最重要. Java异常是Java提供的用于处理程序中错误的一种机制.所谓错误是指程序运行的过程中发生的一些异常事件(如:除0溢出,数组下表越界,所要读取的文件不存在). 为什么需要处理异常? 当异常发生时,会阻断程序运行,且可能无法获知被阻断的原因或者产生不可预见的结果.设计良好的程序应该在异常发生时提供处理这些错误的方法. 异常处理过程: 定义过程-声明异常:声明该方法有可能抛出的异常,throws 异常类名. 定义过程-抛出异常:设置条件判断

JAVA基础之异常处理

java的异常处理机制可以使程序中的异常处理代码与正常业务代码分离,保证程序代码更加优雅,并可以提高程序的健壮性. 在try{} catch(){} 异常处理机制中,try发生的异常对象会被提交到java的运行环境,叫做抛出异常,运行环境会寻找处理该异常的catch块,如果找到,则称为捕获异常,若没有找到合适的catch,则运行时环境终止,程序也将终止 Error和Exception: java把所有的非正常情况分为两种类型,Error(错误)和Exception(异常),他们都继承Throwa

Java基础(四)-异常处理机制及其设计

本篇主要是记录自己所理解的Java异常处理机制(基于jdk1.7)以及怎么去处理和设计异常.还记得当初学习Java异常这块的时候都没怎么注意它的用途,以为就是简单的处理下异常,我避免程序出现这样错误就行了(当初真的很懵懂很天真).当踏入社会工作后才知道一个好的异常处理框架是有多重要,比方说当你的项目投入使用的时候,当程序出错如何快速的定位到问题的根源(出了什么错,在哪出的错,为什么出错),这就跟你的异常处理的好坏有关了(当然离不开你的日志处理).在有效使用异常的情况下,异常类型会回答报的什么错,

Java基础教程——异常处理详解

异常处理 好程序的特性 可重用性 可维护性 可扩展性 鲁棒性 |--|--Robust的音译 |--|--健壮.强壮之意 |--|--指在异常和危险情况下系统依然能运行,不崩溃 Java中,写下如下代码: public class TestException { public static void main(String[] args) { int a = 10 / 0; System.out.println("-END-"); } } 代码运行到"10 / 0"

【BigData】Java基础_异常处理

概念 在我们写程序的时候,当遇到异常,整个程序就中断了,导致程序奔溃,这就会影响用户体验度,为了让程序在运行的的过程中不出现这种问题,当程序报错时候,我们把这种错误先自行处理了,让程序保持正常运行. 例如:一个求商的程序,除数是用户输入,那么用户输入的除数可能是千奇百怪的,可能是数字,也可能是字符,还可能是0,如果输入字符或者0,那么就报错了,这时候程序就中断了,无法继续执行后面的内容,所以就得异常处理了. 注意:异常处理有2种方法 (1)使用try-catch结构来捕获异常 (2)下层方法可以

一天一个Java基础——数组

一天一个变成了几天一个,最近接受的新东西太多.太快,有好多需要blog的但没有时间,这些基础知识应该是要深挖并好好研究的,不应该每次都草草了事,只看个皮毛. 数组: JVM将数组存储在一个称为堆(heap)的内存区域中,堆用于动态内存分配,在堆中内存块可以按随意的顺序分配和释放 1.int[] a; ——表示声明一个数组(也可写为 int a[];) 声明一个数组变量时并不在内存中给数组分配任何空间,只是创建一个对数组的引用的存储位置 如果变量不包含对数组的引用,那么这个变量的值为null 通过