热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《Java编程思想》异常总结

概述说起异常,我就想起了Bug,也就是常说的信春哥,无Bug,什么是Bug呢?我理解的Bug就是没有按照自己原

概述

说起异常,我就想起了Bug,也就是常说的信春哥,无Bug,什么是Bug呢?我理解的Bug就是没有按照自己原先假想的逻辑去执行,这其中包括了两个方面,一方面是代码语法问题,一方面是逻辑问题,就比如正常逻辑买了东西要付款,但是买家买了东西却没有付款,直接拿东西走了,这是逻辑问题,或者是本来数组存储3个元素,你却存了4个,这时候也出现了Bug,程序报错了,这种Bug就是异常。
异常也是Java类的一种,用new创建对象,他们的结构是这样的:

  • Throwable

    • error

    • Exception

恩,就是这样,异常分为错误和异常,感觉有点绕口,但就是这样,像error这种错误是在编译期间就会报出来的,如果你使用的是IDE,所以我们只需要关注Exception异常就可以了。

获取异常和处理异常

获取和处理异常可能就是异常的全部,我们的一个原则就是:

  • 发生异常就得让程序员知道

获取异常

怎么获取异常呢?Java给出了try关键字用来解决,我们只需要将可能出现异常的代码放在try中就可以了,就像这样:

try{...}

java给出了尽量优雅的解决方案来处理异常,它不希望处理异常的代码和本身的业务代码有过多的混合,获取到异常就该处理异常,这时候就应该这样写了:

try{...}catch(Type1 type1){...}catch(Type2 type2){...}

  • catch中的type代表了在try中可能出现的异常类型

catch如何匹配异常?

  • 按顺序从第一个到最后一个,如果发现异常匹配,就停止匹配,和switch模式不一样

  • 基类包含子类异常,如果第一个是Exception,那么后面的都不用匹配了

那么catch中怎么处理这个异常呢?

  • 不作处理(会出现“吞食”)

  • 打印到控制台

  • 写入日志

  • 继续向上抛

在try块中抛出异常,我们在catch中会匹配到相应的异常类型,这时候我们就会拿到对应的异常对象的引用,我们调用throwalbe的方法用于处理:

public class ExceptionMethods {public static void main(String[] args) {try {throw new Exception("My Exception");} catch (Exception e) {System.out.println("Caught Exception");System.out.println(e.getMessage());System.out.println(e.getLocalizedMessage());System.out.println(e);System.out.println(e.toString());e.printStackTrace();e.printStackTrace(System.out);}}
}

  • 我们一般使用e.printStackTrace();打出异常栈信息即可

  • 或者是写入Log,使用logger.error

  • 每个人处理处理异常的方式可能不尽相同

我们除了可以使用try来捕获异常,我们也可以将这个异常抛出去,我们可以把异常比作现在这种制度,地球村出了点问题,村长衡量了一下,觉得这事情自己处理不了,就交给乡长了,这种把问题交给上层或者是Java编程思想中说的跳出当前环境,交给一个更大的环境去处理,这也是Java异常处理的一种思路。

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

其实异常最重要的就是异常的名称,现在Java正在扩充异常的种类,但是很多异常可能不是我们想要的,那么我们就可以自定义异常:

class SystemErrException extends Exception{}

这就是一个异常类,我们继承了Exception,这个SysteErrException就可以用于我们处理异常的时候了,当然我们可以给他加点参数:

class SystemErrException extends Exception{public SystemErrException(){ }public SystemErrException (String message){super(message);}
}

或者是这样:

class SystemErrException extends Exception{private int i;public SystemErrException(){ }public SystemErrException (String message){super(message);}public SystemErrException (String message, int i){super(message);this.i = i;}
}

  • 这只不过是多加了几个参数,但是这些一般是没什么必要的。

throws

说到这,就得说另一个关键字throws,看清楚,不是throw,而是throws,这可能也是面试新手的时候会问的一个问题,throws是异常中的一个申明,在IO学习中会非常常见,它是一个声明,编译器检查到说你这段代码可能会发生什么异常,你要声明一下,这时候你就要在方法上声明:

public void inputFile() throws IOException{....
}

finally

finally用处就和他的意思相符,表示最终的含义,也就是finally里面的代码一定会得到执行:
案例一

public class FinallyException {static int count = 0;public static void main(String[] args) {while (true){try {if (count++ == 0){throw new ThreeException();}System.out.println("no Exception");}catch (ThreeException e){System.out.println("ThreeException");}finally {System.out.println("in finally cause");if(count == 2)break;}}}
}class ThreeException extends Exception{}

执行结果:

ThreeException
in finally cause
no Exception
in finally cause

案例二:return案例

public class MultipleReturns {public static void f(int i){System.out.println("start.......");try {System.out.println("1");if(i &#61;&#61; 1)return;System.out.println("2");if (i &#61;&#61; 2)return;System.out.println("3");if(i &#61;&#61; 3)return;System.out.println("else");return;}finally {System.out.println("end");}}public static void main(String[] args) {for (int i &#61; 1; i<4; i&#43;&#43;){f(i);}}
}

执行结果&#xff1a;

start.......
1
end
start.......
1
2
end
start.......
1
2
3
end

最佳实践

我们可能遇到这种情况&#xff0c;打开一个文件&#xff0c;读取文件&#xff0c;关闭文件&#xff0c;正常逻辑是这样的&#xff0c;但是这样会有几个问题&#xff1a;

  • 在打开文件的过程中出现异常&#xff0c;但是还要关闭文件

就像这样&#xff1a;

try{A a &#61; new A();...}catch(){...}finally{a.close();}

  • A在创建过程中会出现异常&#xff0c;但是还是会执行a的方法&#xff0c;比如关闭文件

所以我们应该这么做&#xff1a;

try{A a &#61; new A();try{...}finally{a.close();}}catch(){...}

异常栈

一般报错都会报一大堆错误&#xff0c;大家无从看起&#xff0c;其实异常报错也是有规律的&#xff0c;这就是栈结构&#xff0c;先进后出&#xff0c;举个栗子&#xff1a;

public class WhoCalled {static void f() {try {throw new Exception();} catch (Exception e) {for (StackTraceElement ste : e.getStackTrace()){System.out.println(ste.getMethodName());}}}static void g(){f();}static void h(){g();}public static void main(String[] args) {f();System.out.println("---------------------------");g();System.out.println("---------------------------");h();System.out.println("---------------------------");}
}

运行结果&#xff1a;

f
main
---------------------------
f
g
main
---------------------------
f
g
h
main
---------------------------

可以看到异常信息都是从内到外的&#xff0c;按我的理解查看异常的时候要从第一条异常信息看起&#xff0c;因为那是异常发生的源头。

总结

异常总的来说还是很重要的&#xff0c;也是保障程序健壮性很重要的一栏&#xff0c;并且可以达到立竿见影的效果&#xff0c;这里只是基本总结了异常的一些常见问题&#xff0c;很多还得在自己运用的过程中去探索。



推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
author-avatar
情人節快樂1991的名单
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有