只针对异常的情况才使用异常

本文是我们名为“ 高级Java ”的学院课程的一部分。

本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的旅程! 在这里查看 !

目录

1.简介 2.异常以及何时使用它们 3.已检查和未检查的异常 4.使用尝试资源 5.异常和lambda 6.标准Java异常 7.定义自己的例外 8.记录例外 9.异常和记录 10.下一步是什么 11.下载源代码

1.简介

Java中的异常是在程序流中发出异常(或异常)情况信号的重要工具,可能会阻止其进一步发展。 从本质上讲,那些特殊情况可能是致命的(程序无法再运行,应该终止)或可恢复(程序可能会继续运行,尽管某些功能可能不可用)。

在本教程的这一部分中,我们将逐步介绍在Java中使用异常的典型场景,讨论已检查和未检查的异常,并探讨一些极端情况和有用的习惯用法。

2.异常以及何时使用它们

简而言之,异常是某种事件(或信号),它们在程序执行期间发生并中断常规执行流程。 导致引入异常的想法是对过去使用的错误代码和状态检查技术的替代。 从那时起,异常被广泛接受为处理包括Java在内的许多编程语言中的错误情况的标准方法。

只有一个与异常处理相关的重要规则(不仅在Java中):永远不要忽略它们! 每个异常都应至少记录一次(请参阅Exceptions和logging ),但永远不要忽略。 尽管如此,在某些罕见的情况下,可以安全地忽略异常,因为实际上可以做很多事情(请参阅示例中的使用try-with-resources部分)。

另外,在本教程的第6部分“ 如何有效地编写方法”中 ,我们讨论了参数验证和健全性检查。 异常是这些实践的关键部分:每种公共方法都应在进行任何实际工作之前验证所有必需的前提条件,如果某些前提条件未得到满足,则提出适当的例外条件。

3.已检查和未检查的异常

Java语言中的异常管理与其他编程语言不同。 这主要是因为Java中有两类异常: 选中的异常和未选中的异常。 有趣的是,这两个类在某种程度上是人为的,是由Java语言规则及其编译器强加的(但是JVM对它们没有影响)。

根据经验,未经检查的异常用于表示与程序逻辑和所做假设有关的错误条件(无效参数,空指针,不支持的操作,等等)。 任何未经检查的异常都是RuntimeException的子类,这就是Java编译器如何理解特定异常属于未经检查的异常的类。

未经检查的异常不需要被调用方捕获,也不需要作为方法签名的一部分列出(使用throws关键字)。 NullPointerException是未经检查的异常的最著名的成员,这是Java标准库中的声明:

public class NullPointerException extends RuntimeException {public NullPointerException() {super();}public NullPointerException(String s) {super(s);}
}

因此,检查的异常表示程序无法直接控制的区域(如内存,网络,文件系统等)中的无效条件。 任何检查到的异常都是Exception的子类。 与未检查的异常相反,已检查的异常必须被调用者捕获,或者被列为方法签名的一部分(使用throws关键字)。 IOException可能是检查异常中最知名的一种:

public class IOException extends Exception {public IOException() {super();}public IOException(String message) {super(message);}public IOException(String message, Throwable cause) {super(message, cause);}public IOException(Throwable cause) {super(cause);}
}

在当时,将已检查和未检查的异常分开听起来是个好主意,但是多年来,事实证明,它引入了更多样板代码,而不是解决实际问题的漂亮代码模式。 Java生态系统中出现的典型(不幸的是非常麻烦)模式是将未检查的异常隐藏(或包装)在未检查的异常中,例如:

try {// Some I/O operation here
} catch( final IOException ex ) {throw new RuntimeException( "I/O operation failed", ex );
}

这不是最好的选择,但是如果精心设计自己的异常层次结构,可能会减少开发人员需要编写的样板代码数量。

值得一提的是,Java中还有另一类异常扩展了Error类(例如, OutOfMemoryErrorStackOverflowError )。 这些异常通常表示致命的执行失败,导致无法立即从此类错误情况中恢复,从而导致程序立即终止。

4.使用尝试资源

抛出的任何异常都会导致一些所谓的堆栈展开和程序执行流程的更改。 结果是与未封闭的本机资源(例如文件句柄和网络套接字)有关的可能的资源泄漏。 Java中行为良好的典型I / O操作(直到版本7)需要使用强制性的finally块来执行清理,并且通常看起来像这样:

public void readFile( final File file ) {InputStream in = null;try {in = new FileInputStream( file );// Some implementation here} catch( IOException ex ) {// Some implementation here} finally {if( in != null ) {try {in.close();} catch( final IOException ex ) {/* do nothing */}}}
}

尽管如此, finally块看起来确实很丑陋(不幸的是,此处无法做太多事情,因为在输入流上调用close方法也可能导致IOException异常),无论尝试关闭输入流(并释放背后的操作系统资源)发生了什么情况它)将被执行。 在“ 异常以及何时使用它们 ”一节中,我们强调了一个事实,即永远都不应忽略异常,但是,用close方法抛出的异常可以说是从该规则中排除的一个例外。

幸运的是,自Java 7以来,该语言引入了一种名为try-with-resources的新结构,该结构大大简化了整体资源管理。 这是上面使用try-with-resources重写的代码片段:

public void readFile( final File file ) {try( InputStream in = new FileInputStream( file ) ) {// Some implementation here} catch( final IOException ex ) {// Some implementation here}
}

为了在try-with-resources块中使用,资源唯一需要拥有的就是接口AutoCloseable 。 在后台Java编译器将此构造扩展为更复杂的结构,但对开发人员而言,代码看起来非常易读和简洁。 请在适当的地方使用此非常方便的技术。

5.异常和lambda

在本教程的第3部分如何设计类和接口中 ,我们已经讨论了Java 8的最新和最出色的功能,特别是lambda函数。 但是,我们尚未深入研究许多实际用例,并且例外是其中之一。

毫无疑问,未检查的异常可以按预期工作,但是Java的lambda函数语法不允许指定可能抛出的已检查的异常(除非这些异常由@FunctionalInterface本身定义)。 以下代码段将不会以编译错误“未处理的异常类型IOException”进行编译(可能会在第03行引发):

public void readFile() {run( () -> {Files.readAllBytes( new File( "some.txt" ).toPath() );} );}public void run( final Runnable runnable ) {runnable.run();}

现在唯一的解决方案是在lambda函数体内捕获IOException异常,然后重新抛出适当的RuntimeException异常(不要忘记将原始异常作为原因传递),例如:

public void readFile() {run( () -> {try {Files.readAllBytes( new File( "some.txt" ).toPath() );} catch( final IOException ex ) {throw new RuntimeException( "Error reading file", ex );}} );
}

声明了许多功能接口,可以从其实现中引发任何异常,但是如果没有(如Runnable),则将检查的异常包装(或捕获)为非检查的异常是唯一的方法。

6.标准Java异常

Java标准库提供了大量有关异常的类,这些异常类被指定为覆盖程序执行期间发生的大多数通用错误。 下表列出了使用最广泛的应用程序,请在定义自己的应用程序之前加以考虑。

例外类别 目的
NullPointerException 在需要对象的情况下尝试使用null
IllegalArgumentException 方法已传递了非法或不适当的参数。
IllegalStateException 方法已在非法或不适当的时间被调用。
IndexOutOfBoundsException 某种索引(例如数组,字符串或向量)的索引超出范围。
UnsupportedOperationException 不支持请求的操作。
ArrayIndexOutOfBoundsException 已使用非法索引访问了数组。
ClassCastException 代码已尝试将对象强制转换为不是实例的子类。
EnumConstantNotPresentException 试图访问一个enum的名称和常量enum类型包含具有指定名称的常量( enums一直在本教程中, 部分5 如何以及何时使用枚举和注解 )。
NumberFormatException 尝试将字符串转换为数字类型之一,但是该字符串没有适当的格式。
StringIndexOutOfBoundsException 索引为负或大于字符串的大小。
IOException 发生了某种I / O异常。 此类是由失败或中断的I / O操作产生的异常的一般类别。

表1 –标准Java异常

7.定义自己的例外

Java语言使定义自己的异常类非常容易。 精心设计的异常层次结构允许实施详细的细粒度错误条件管理和报告。 与往常一样,找到合适的平衡非常重要:太多的异常类会使开发复杂化,并浪费大量的代码来捕获异常或将其传播到堆栈中。

强烈建议所有用户定义的异常都应继承自RuntimeException类,并且应属于未经检查的异常类(但是,规则中始终存在排除项)。 例如,让我们定义异常以进行身份​​验证拨号:

public class NotAuthenticatedException extends RuntimeException {private static final long serialVersionUID = 2079235381336055509L;public NotAuthenticatedException() {super();}public NotAuthenticatedException( final String message ) {super( message );}public NotAuthenticatedException( final String message, final Throwable cause ) {super( message, cause );}
}

此异常的目的是在信号插入过程中发出有关不存在或无效的用户凭据的信号,例如:

public void signin( final String username, final String password ) {if( !exists( username, password ) ) {throw new NotAuthenticatedException("User / Password combination is not recognized" );}
}

将信息性消息与异常一起传递始终是一个好主意,因为它有助于对生产系统进行故障排除。 同样,如果异常是由于另一个特殊情况导致的,则应使用cause构造函数参数保留初始异常。 这将有助于找出问题的真正根源。

8.记录例外

在本教程的第6部分如何有效地编写方法中 ,我们介绍了Java方法的正确文档。 在本节中,我们将花费更多时间讨论如何使异常成为文档的一部分。

如果方法作为其实现的一部分可能会引发检查的异常,则它必须成为方法签名的一部分(使用throws声明)。 Java文档工具分别具有@throws标记,用于描述这些异常。 例如:

/*** Reads file from the file system.* @throws IOException if an I/O error occurs.*/
public void readFile() throws IOException {// Some implementation here
}

相反,正如我们从Checked和unchecked异常一节中所知道的那样,未经检查的异常通常不声明为方法签名的一部分。 但是,记录它们仍然是一个非常好的主意,因此方法的调用者将意识到可能引发的异常(使用相同的@throws标记)。 例如:

/*** Parses the string representation of some concept.* @param str String to parse* @throws IllegalArgumentException if the specified string cannot be parsed properly* @throws NullPointerException if the specified string is null*/
public void parse( final String str ) {// Some implementation here
}

请始终记录您的方法可能引发的异常。 它将帮助其他开发人员从一开始就实施适当的异常处理和恢复(后备)逻辑,从而避免他们对生产系统中的问题进行故障排除。

9.异常和记录

日志记录( http://en.wikipedia.org/wiki/Logfile )是或多或少复杂的Java应用程序,库或框架的重要组成部分。 它是应用程序中发生的重要事件的日志,异常是此流程的关键部分。 在本教程的后面,我们可能会介绍Java标准库提供的日志子系统,但是请记住,以后应该正确记录和分析异常,以便发现应用程序中的问题并解决关键问题。

10.下一步是什么

在本教程的这一部分中,我们介绍了异常,这是Java语言的一个非常重要的功能。 我们已经看到异常是Java中错误管理的基础。 异常使处理和发信号通知错误情况非常容易,并且与错误代码,标志和状态相反,一旦发生,则不能忽略异常。 在下一部分中,我们将讨论一个非常热门和复杂的主题:Java中的并发和多线程编程。

11.下载源代码

这是关于如何以及何时使用异常的课程。 您可以在此处下载源代码: advanced-java-part-8

翻译自: https://www.javacodegeeks.com/2015/09/how-and-when-to-use-exceptions.html

只针对异常的情况才使用异常

只针对异常的情况才使用异常_如何以及何时使用异常相关推荐

  1. java中三种可能导致异常的情况_JAVA基础知识点之异常

    一.JAVA异常 异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描 ...

  2. Linux数据链路tcp失败,TCP连接中的异常断开情况处理

    1.TCP连接中可能出现的异常断开情况 假设存在这样一种情况:在两个不同的主机Machine1.Machine2系统上分别运行两个应用程序Application1.Application2,在Appl ...

  3. Python无法加载vc产生的DLL - 一种异常的情况

    Python无法加载vc产生的DLL - 一种异常的情况 本地调试时候一切正常,发布给客户就出现如下错误:无法导入DLL. 最后查明原因是:VC编译dll的设定差异导致. 有问题的设置: 改变后的设置 ...

  4. java中三种可能导致异常的情况_Java常见异常种类及产生原因

    JAVA异常共分为下列几种 Error JAVA环境编译错误 Runtime Exception 运行处异常 Exception 标准Java库方法异常 throw 用户自定义异常 异常分为两类 Er ...

  5. 使用SWig出现调用异常的情况

    未经处理的异常:  System.TypeInitializationException: "Win32Project1PINVOKE"的 类型初始值设定项引发异常. ---> ...

  6. java异常_聊聊Java中的异常及处理

    前言 在编程中异常报错是不可避免的.特别是在学习某个语言初期,看到异常报错就抓耳挠腮,常常开玩笑说编程1分钟,改bug1小时.今天就让我们来看看什么是异常和怎么合理的处理异常吧! 异常与error介绍 ...

  7. java解决异常_聊聊Java中的异常及处理

    在编程中异常报错是不可避免的.特别是在学习某个语言初期,看到异常报错就抓耳挠腮,常常开玩笑说编程1分钟,改bug1小时.今天就让我们来看看什么是异常和怎么合理的处理异常吧! 异常与error介绍 下面 ...

  8. java 异常处理发生异常_处理Java中的异常

    java 异常处理发生异常 每个程序员都希望编写一个完美的程序. 也就是说,程序运行时没有任何障碍. 好吧,如果希望是马,乞g就会骑. 除了程序员的所有愿望之外,有时还会发生无法预料的情况. 在Jav ...

  9. 《异常检测——从经典算法到深度学习》5 Opprentice——异常检测经典算法最终篇

    <异常检测--从经典算法到深度学习> 0 概论 1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法 3 基于One-Class SVM的异常检测算法 4 基于高斯概率密度异常检测 ...

最新文章

  1. PyTorch迎来5岁生日,创始人带领大一实习生开发:没想到会这么成功
  2. 格式化硬盘 FAT32 和NTFS 什么区别?
  3. niginx查看服务器日志信息,nginx 远程日志服务器
  4. TortoiseSVN与VisualSVN Server搭建SVN版本控制系统
  5. c语言switch写值班表,如何用asp编写按周轮换的值班表?例,1月份的值班领导有4位,怎样写可以让4位领导的名字自动到时间显示...
  6. C语言学习之用选择法对10个整数排序
  7. Cloud for Customer元数据的加载
  8. python中pandas安装视频教程_详解Python中pandas的安装操作说明(傻瓜版)
  9. 使用MinGW编译Psycopg2
  10. iview table增加一行减少一行_PQ入门函数:Table.ReplaceValue
  11. 建议设计日常多逛,多学习的网站
  12. 解决新电脑的系统安装问题:针对BIOS的UEFI模式
  13. 如何为服务器安装mysql数据库文件,如何为服务器安装mysql数据库
  14. thinkphp5 return 返回空_杨丞琳演唱会意外踩空,从两层楼高的舞台掉落,李荣浩心疼发文...
  15. java 数组计算隐藏电话号码
  16. 关于解决Windows server系统用户无法远程的问题
  17. Router+Redux学习总结
  18. transform三大属性之scale(缩放)
  19. 最小生成树Prim算法Java版
  20. C盘莫名其妙就满了怎么办?

热门文章

  1. jzoj6805-NOIP2020.9.26模拟speike【扫描线】
  2. P4819-[中山市选]杀人游戏【tarjan】
  3. 【dfs】GCD与LCM(jzoj 1608)
  4. SpringCloud Gateway配置自定义路由404坑
  5. 从 0 开始手写一个 Spring MVC 框架,向高手进阶
  6. 这些代码优化的方法,你都用过吗
  7. vue非编译的模块化写法
  8. mysq和mysqli关系
  9. mybatis+spring报错PropertyAccessException 1
  10. 重写(override / overwrite)