Java 异常
1 Exception的基本概念。
异常是Java中的一个对象,并定义一个基类java.lang.Throwable作为所有异常的超类。 Throwable类有两个直接子类: java.long. Error和java.long.Exception。Exception又有一个特殊的子类java.long.RuntimeException。
对于Error和Exception,很好区别这两个概念。Error是指程序在运行时发生了无法处理的错误,比如内存溢出等。发生错误时程序无法继续运行,Java虚拟机一般选择线程终止来处理错误。Exception是指发生了程序本身可以处理的错误。在java代码中指明Exception发生时如何处理。
RuntimeExceptio是Exception的一个子类。继承RuntimeException的异常我们通常叫做“非检查异常(Unchecked Exception)”,非继承RuntimeException的异常叫做“检查异常(Checked Exception)”。检查异常和非检查异常的区别在于:java编译器对检查异常有一定的要求,不符合要求将不能通过编译。一是如果函数要抛出检查异常,必须在函数声明部分用throws关键字指明要抛出的异常。二是如果代码调用的函数声明了可能抛出检查异常,调用点代码使用try/catch块去捕获该检查异常,如果不想捕获,也可以在调用代码的函数声明部重新声明要抛出该检查异常。而对于非检查异常和Error编译器不做检查。
必须在函数声明部分指明要抛出的检查异常
public class ClassA {
public void metohA() throws ExceptionA {
// ...
throw new ExceptionA();
}
}
捕获函数抛出的检查异常
public class ClassB {
public void metohB(){
try{
//...
ClassA classA= new ClassA();
classA.metohA();//metohA()抛出检查异常
//.....
}catch (ExceptionA ex) {
// ...
}
}
}
重新声明抛出异常
public class ClassB throws ExceptionA {
public void metohB(){
//...
ClassA classA= new ClassA();
classA.metohA();//metohA()声明了抛出检查异常。
//.....
}
}
}
Java API的设计者们建议尽可能的使用检查异常,以好借助编译器的检查来写出健壮的软件。但是这种做法也带来了一定的副作用。因为一些异常即使捕获也是无法处理的,比如对IOException。当发生对IOException时,大部分程序是无法处理的,但是你又不的不处理这个异常。处理这些异常给本来简单的代码带来了一定的晦涩,即使捕获该异常也不能进行处理,但是不加以捕获又可能更糟糕,因为编译器要求你的方法必须要处理这些异常。这样你的实施细则就不得不暴露在外了,而通常好的面向对象的设计都是要隐藏细节的。一些Java界的知名人物开始质疑Java的“检察的异常”的模型是否是一个失败的试验。对于是否是失败的试验,在我们对java异常做充分的了解后,自己会有一个合理的评判。
2 异常的设计原理。
什么时候我们应该抛出一个异常。或者我们应该如何设计一个异常。这取决于你的程序的业务逻辑。而不是在编码阶段才考虑程序中需要设计那些异常,是设计成检查异常还是非检查异常。异常来源于你的业务逻辑。
我们举例来说明如何设计异常。假设我们要做一个统一的登录系统,我们要设计一个登录检查类CheckingLogin。在这个类里,存在着用户的用户名、密码等信息。我们要判断一个用户是否能够登录系统。CheckingLogin类里check的方法会接受两个字符串userName和password为参数。正常的处理流程是用户和密码正确,用户可以登录。但是有两种特殊的情况,一是用户不存在,二是用户存在但密码错误。这三种情况都是正常的业务流程,check方法要处理这三种情况。
在设计中很自然的为上述两种意外情况设计两个异常一个是NoUserException(用户不存在异常),一个是PasswordErrorException(密码错误异常)。这两种异常在正常的操作中都会发生。调用者必须处理这些异常。为了使调用者不能忽略这些异常,很显然我们把这两种异常设计为检查异常,并反应在方法签名里。
检查异常看成是业务逻辑的一部分。是可以预期的,在正常操作过程中是可能发生的。在检查异常发生时,是可以指定对应的特殊流程进行处理。
还是上面的例子,在检查用户名称和密码的过程当中,我们可能需要访问数据库获得用户的信息,增加一个方访问数据库的方法getUser()。但是在访问数据库的过程当中,可能发生数据库忘记启动或连接数据库的网络中断的情况。当发现这种情况时,getUser()方法本身是无法处理的,调用者也无法处理。很自然应在这种情况发生时抛出一个非检查异常DataAccessException(数据访问异常)。
检查异常通常表示有故障发生,这种故障是无法预期的。只能通过人为或其他方式处理故障。设计检查异常的目的应该是记录故障信息,供解决故障时参考。
从上面的例子可以看出,检查异常通常表示一个特殊的处理流程。是可以预计和处理的。检查异常的主要作用是告诉调用者处理这种特殊流程。非检查异常通常表示发生了不该发生的故障,是无法预期的。非检查异常的作用是把故障信息记录下来,为解决故障的人提供信息。
3 对非检查异常的处理。
非检查异常对程序当中可能发生的故障的最好表达方式。非检查异常的主要作用是记录下故障信息。使用非检查异常处理故障,可以使上游的调用方法不需要为异常添加处理代码,从而减少了混乱。
对于非检查异常,一般不需要捕获和处理。捕获非检查异常不会是程序更加健壮,只是使程序晦涩难懂,干扰理解业务逻辑。那么非检查异常何时才捕获和处理?只需要最后设置一个非检查异常处理中心,在这里处理所有的非检查异常。在设计你的异常处理框架时,你应该让所有的非检查异常最后都能到达一个处理中心来进行处理,而不是在各个调用的地方。这样使编码更加简单并达到记录故障的目的。
在一个Strut2的应用里,故障处理中心可能是配置的一个异常拦截器,拦截RuntimeException和他的子类。在Spring MVC里,你可以继承SimpleMappingExceptionResolver类,并配置成处理RuntimeException和它的子类,来构建非检查异常处理中心。
4 对检查异常的处理。
检查异常标示特殊的处理流程。发生一个检查异常时,就发生了一个特殊的处理流程。当然我们也可以不用异常来表示特殊的处理流程。就上面系统登录的例子来说,我们可以让check方法返回true或false来表示是否验证通过,但是这样做丢失了一些信息,上层调用者不知道是因为用户不存在还是密码错误导致检查失败。或者我们可以返回一个字符串或数字来表示返回的信息,但是这样的话,我们就进入了错误代码检查的世界,而这正式Java异常模式所着力避免的。所以,使用异常可以使我们的方法返回更多和更加准确的信息。
因为返回一个异常就表示发生了一种特殊流程,所以要给不同的特殊流程定义不同的异常。好让上层调用者知道发生了什么。 对检查异常来说,记录下检查异常并没有太大的作用。只要上层捕获并处理异常,检查异常的目的就达到了,并不需要记录下来。
因为检查异常必须由调用者处理,会给编写代码带来额外的负担。如果一个检查异常调用者不能处理,可以把该异常继续抛出,将处理权交给更上层的调用者。如果能确定这个检查异常没有能够处理的可能,这时候把检查异常转换为非检查异常是一个不错的选择。以减轻上层调用者的负担。比如在SpringDAO中,Spring提供了一种方便的方法,把特定于某种技术的异常,如SQLException, 转化为自己的非检查异常。而不再需要在DAO中编写讨厌的样板式的catch/throw代码块和异常声明。
分享到:
相关推荐
Java学习心得体会 在编程的世界里,Java是一种广泛应用的高级编程语言,以其“一次编写,到处运行”的特性赢得了全球开发者的青睐。这篇心得体会旨在分享我在学习Java过程中的关键知识点,希望能为初学者提供一些...
【Java实训心得体会】 Java实训是将理论知识转化为实践能力的重要环节。通过实训,我们深入了解了Java这门面向对象编程语言的特性和应用。在实训过程中,我们主要学习了以下几个核心知识点: 1. **基础概念**:...
在本项目中,"JAVA语言模拟ATM取款机体会" 是一个实践性质的学习任务,旨在帮助学习者通过编程理解ATM(自动取款机)的工作原理,掌握Java编程技能。ATM机模拟通常涉及用户交互、账户管理、交易处理等核心功能。以下...
Java异常处理 - **Exception**: Java中的异常分为两大类:**checked exception** 和 **unchecked exception**。前者需要在方法声明中抛出或捕获,后者则不需要。 - **IllegalStateException**: 当方法调用处于不...
【JAVA课程设计报告心得体会——计算器、文本编辑器】 在JAVA课程设计中,我参与了计算器与文本编辑器的开发,这是一次深入理解和实践JAVA编程的宝贵经历。这两个项目不仅涵盖了JAVA的基础语法,还涉及到了面向对象...
Java编程体会主要涵盖以下几个关键知识点: 1. **内部类**: - **内部类向上转型**:内部类可以被声明为父类或接口的类型,这使得内部类的实例可以被当作其父类或接口的实例来使用,隐藏其实现细节。 - **局部...
- **异常处理**: Java 提供了强大的异常处理机制,通过try-catch-finally语句块可以有效地处理程序运行时可能出现的异常情况。 #### 3. 高级特性学习 - **集合框架**: 包括List、Set、Map等接口及其具体实现类,...
总的来说,Java体会总集涵盖了从基础到高级的各个方面,包括但不限于语法、异常处理、集合框架、多线程、I/O、反射、注解和模块系统。通过不断学习和实践,开发者可以深入理解Java语言的精髓,提高编程技巧,并能够...
Java学习心得体会 Java作为一种强大的面向对象的编程语言,其学习过程并非一蹴而就,而是需要逐步积累和深入理解。从“2022年java学习心得体会”文档中可以看出,作者通过自己的学习经历,分享了关于Java学习的一些...
【Java认知实习心得体会】 Java是一种广泛应用的面向对象的编程语言,以其卓越的通用性、高效性、平台移植性和安全性著称。它不仅能在个人计算机、数据中心、嵌入式设备及互联网上运行,还拥有全球最大的开发者社区...
首先,对于Java实习,通常会涉及到的知识点可能包括Java基础语法、面向对象编程、Java集合框架、异常处理、输入输出流(I/O)以及Java的图形用户界面(GUI)编程等。 1. Java基础语法:在实习过程中,首先需要掌握...
### Java实习心得体会与技能提升 #### 一、Java实习的重要性 对于计算机专业的学生而言,Java实习不仅是学习过程中不可或缺的一部分,更是对未来职业生涯有着重要奠基作用的关键环节。通过实习,不仅可以加深对...
Java编程概念和技巧包括Java的基本语法、对象oriented编程、异常处理、多线程编程、网络编程、数据库编程等。 3. 实践能力和独立思考能力 通过实践,作者提高了自己的实践能力和独立思考能力。实践能力包括编码、...
【Java实习心得体会】 Java实习是将理论知识转化为实践能力的重要环节。通过实习,我们能够深入理解Java编程语言的精髓,掌握编程概念与技巧。在实习过程中,我从基础开始,逐步强化了Java语言编程能力,这包括对...
死亡状态则是线程的生命周期结束,可能是因为线程任务执行完毕或因异常情况退出。 在Java中,创建线程有几种常见的方式。第一种是通过继承Thread类并重写run方法来定义新的线程类。当创建此类的对象时,实际上就...
学习 Java 的心得体会 学习 Java 需要具备良好的心态和习惯,以下是学习 Java 的心得体会: 一、充分利用 MSDN MSDN 是 Microsoft 当前提供的有关编程信息的最全面的资源,包含微软最新的技术数据库,加上易学...
- 应考虑错误处理,如无效的用户输入、除以零等异常情况,通过异常处理机制进行捕获和处理。 8. **可扩展性**: - 计算器设计应考虑可扩展性,便于添加新的功能或改进现有功能,如添加更多复杂的数学运算。 9. *...
进一步,实习生掌握了Java的面向对象编程特性,如抽象、多态、继承和封装,并了解了Java异常处理、常用类(如String、StringBuffer)以及集合框架(如Set、List、Map)。 【数据库连接与Oracle知识】 在数据库方面...