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

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

本文是我们名为“ 高级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类(例如, OutOfMemoryError或StackOverflowError )。 这些异常通常表示致命的执行失败,导致无法立即从此类错误情况中恢复,从而导致程序立即终止。

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/337436.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++红黑树模拟实现map和set

点击蓝字关注我们一、红黑树及其节点的设计对于底层都是红黑树的map和set来说,他们之间存在的最大的区别就是:对于set是K模型的容器,而map是KV模型的容器。为了更好的灵活兼容实现map和set,就需要在红黑树以及树节点上进行特别的设…

c语言连接mysql_聊聊数据库MySQL、SqlServer、Oracle的区别,哪个更适合你?

一、MySQL优点:体积小、速度快、总体拥有成本低,开源;支持多种操作系统;是开源数据库,提供的接口支持多种语言连接操作 ;MySQL的核心程序采用完全的多线程编程。线程是轻量级的进程,它可以灵活地…

Python3解题:二叉树路径总和问题

Python3解题:二叉树路径总和问题原题 https://leetcode-cn.com/problems/path-sum-ii/ 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff…

绩效工作流_流绩效–您的想法

绩效工作流上周,我介绍了一些有关Java 8流性能的基准测试结果。 你们和gal足够有兴趣留下一些想法,还有哪些可以介绍。 这就是我所做的,这里是结果。 总览 最后一篇文章的序言也适用于此。 阅读它,以找出所有数字为何撒谎&#…

C语言访问MCU寄存器的两种方式

点击蓝字关注我们单片机的特殊功能寄存器SFR,是SRAM地址已经确定的SRAM单元,在C语言环境下对其访问归纳起来有两种方法。1、采用标准C的强制类型转换和指针来实现采用标准C的强制转换和指针的概念来实现访问MCU的寄存器,例如:#define DDRB (*…

python中return true的用法_Return True/False何时使用它而不是Return

类比:函数是一个准备好执行任务并给出答案的可克隆助手。任务由函数的参数定义(括号内的内容)。让我们重写这些名称以赋予它们语义意义(即说明我们期望的名称)。在def isXGreaterThanY(..... 在这里,任务的…

08_优先队列

08_优先队列 一、优先队列最大优先队列最大优先队列API设计 最小优先队列最小优先队列API设计最小优先队列代码实现 索引优先队列索引优先队列实现思路索引优先队列API设计索引优先队列代码实现 一、优先队列 :::info 普通的队列是一种先进先出的数据结构,元素在队…

Python3实现红黑树[下篇]

Python3实现红黑树[下篇]我写的红黑树的上篇在这里:https://blog.csdn.net/qq_18138105/article/details/105190887 这是我近期看的文章 https://www.cnblogs.com/gcheeze/p/11186806.html 我看了很多关于红黑树删除的文章和博客,介绍得是相当相当的复…

C语言内存泄露很严重,如何应对?

点击蓝字关注我们1. 前言最近部门不同产品接连出现内存泄漏导致的网上问题,具体表现为单板在现网运行数月以后,因为内存耗尽而导致单板复位现象。**一方面,内存泄漏问题属于低级错误,此类问题遗漏到现网,影响很坏&…

通用编程_通用编程准则

通用编程本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的旅程! 在这里查看 ! 目…

python发送邮件outlook_通过Python发送Outlook电子邮件?

I am using Outlook 2003. What is the best way to send email (through Outlook 2003) using Python? 解决方案 For a solution that uses outlook see TheoretiCALs answer below. Otherwise, use the smtplib that comes with python. Note that this will require your e…

Python3实现快速排序 通俗易懂

Python3实现快速排序快速排序 是一种交换排序,属于分治算法。 思路: 对于要排序的元素集合,指定集合的第一个元素为基准点,通过一系列的扫描和交换(见下面的代码),让基准点左边的元素比基准点小,让基准点右…

C++队列queue用法详解(超详细)

点击蓝字关注我们一、定义queue是一种容器转换器模板&#xff0c;调用#include< queue>即可使用队列类。二、queue初始化queue<Type, Container> (<数据类型&#xff0c;容器类型>&#xff09;初始化时必须要有数据类型&#xff0c;容器可省略&#xff0c;省…

redis nosql_Redis教程:NoSQL键值存储

redis nosql课程大纲 Redis是使用ANSI C编写的&#xff0c;具有可选持久性的开源&#xff0c;网络化&#xff0c;内存中键值数据存储。根据DB-Engines.com的月度排名&#xff0c;Redis是最受欢迎的键值存储。 其名称意为“远程词典服务器”。 Redis是BSD许可的&#xff0c;并且…

python随机抽取人名_python实现艾宾浩斯背单词功能,实现自动提取单词、邮件发送,再也不用担心背单词啦...

&#xfeff;已经完成了利用python爬虫实现定时QQ邮箱推送英文文章&#xff0c;辅助学习英语的项目&#xff0c;索性就一口气利用python多做一些自动化辅助英语学习的项目&#xff0c;对自己的编程能力和英文水评也有一定的帮助&#xff0c;于是在两天的努力下&#xff0c;我完…

用不到125行C语言代码就可以编写一个简单的16位虚拟机?

点击蓝字关注我们一位国外的软件工程师分享了这么一篇博文&#xff1a;Writing a simple 16 bit VM in less than 125 lines of C&#xff08;用不到 125 行 C 语言编写一个简单的 16 位虚拟机&#xff09;。博文地址&#xff1a;https://www.andreinc.net/2021/12/01/writing-…

用一个程序生成另一个程序_还有另一个报告生成器?

用一个程序生成另一个程序如果您具有业务应用程序开发的经验&#xff0c;那么很可能会遇到要求该应用程序具有灵活的报告机制的需求。 我工作的公司主要专注于开发业务解决方案&#xff0c;而报告是必不可少的&#xff0c;实际上&#xff0c;它必须包含我们开发的所有企业系统的…

CocosCreator1.x实现水流动的效果

CocosCreator1.x实现水流动的效果Cocos Creator版本&#xff1a;1.10.2 运行结果&#xff1a;(H5和原生都支持) 场景: 脚本&#xff1a; HelloWorld.js&#xff1a; let shader require(shader);cc.Class({extends: cc.Component,properties: {water: cc.Node,waterNorm…

python爬虫xpath教程_使用 Xpath 进行爬虫开发

使用 Xpath 进行爬虫开发 Xpath( XML Path Language, XML路径语言)&#xff0c;是一种在 XML 数据中查找信息的语言&#xff0c;现在&#xff0c;我们也可以使用它在 HTML 中查找需要的信息。 既然谈到 Xpath 是一门语言&#xff0c;当然它就会有自己的一些特定的语法。我们这里…

java使用泛型后消除泛型_如何以及何时使用泛型

java使用泛型后消除泛型本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题&#xff0c;包括对象创建&#xff0c;并发&#xff0c;序列化&#xff0c;反射等。 它将指导您完成Java掌握的旅程&#xff01; 在这里查看 &a…