第七章: 异常

1.异常概述
在我们日常生活中,有时会出现各种各样的异常,例如:职工小王开车去上班,在正常情况下,小王会准时到达单位。但是天有不测风云,在小王去上班时,可能会遇到一些异常情况,比如小王的车子出了故障,小王只能改为步行.

异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。

异常发生在程序运行期间,它影响了正常的程序执行流程

Java通过API中Throwable类的众多子类描述了各种不同的异常。Java中的异常都是对象,都是Throwable子类的实例。

每种异常类型都代表了一个错误的情况。
例如:
java.lang.ArrayIndexoutofBoundsException类,表示数组的下标在使用中超过了边界
java.lang.ClassCastException类,表示类型转换出现了错误

2.Error和Exception
在Java中,所有的异常都有一个共同的父类Throwable,该类有两个重要的子类:Exception和Error,二者都是Java异常处理的重要子类,各自都包含大量子类。
它们都是java.lang下的类
java.lang.Throwable
java.lang.Error
java.lang.Exception

Error,这个是程序中发生的错误,是程序无法处理的,表示运行应用程序中较严重问题。而且很多错误与代码编写者执行的操作无关,而是表示代码运行时JVM出现了问题。例如,Java虚拟机运行错误(VirtualMachineError),当JVM中内存不足时,将出现 OutOfMemoryError。这些error发生时,JVM一般会选择线程终止。
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应时
如Java虚拟机运行错误(VirtualMachineError)、类定义错误(NoClassDefFoundError)等。这些错误一般是不可查询的,因为它们在应用程序的控制和处理能力之外。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况,因为这是超出程序处理能力的。

Exception,这个是程序中发生的异常,是程序本身可以处理的,并且处理完之后程序本身还可以继续往下执行。
我们进行抛出或捕获的异常就是这个Exception类型及其子类型。

3.异常的抛出和捕获
异常的抛出:
在类中编写方法的时候,这个方法中将来被执行的代码如果有可能出现异常情况,那么就"可以"在方法的参数列表后声明该方法中可能会抛出的异常类型.
例如:
public class Test{
public void run()throws IOException,SQLException{
//..
}
}
1)如果有多个异常类型要抛出,那么需要使用逗号隔开.
2)所声明抛出的异常是该方法执行后"可能"会出现异常类型
3)异常抛给了方法的调用者,谁调用的这个方法谁就负责处理这些异常

异常的捕获
当我们调用了一个方法,该方法在声明的时候抛出了异常,那么我们作为方法的调用者就必须去处理这些被抛出的异常。
例如:
Class类中的forName方法的声明
public static Class<?> forName(String className)throws ClassNotFoundException

说明该方法在执行的时候有可能抛出ClassNotFoundException类型的异常,表示要加载的类找不到。
我们调用这个方法的时候,就需要对这个抛出的异常进行处理。

第一种方式是继续把这些异常抛出去
例如:
public static void main(String[] args)throws ClassNotFoundException{
Class.forName("test....");
}

在main方法中调用forName方法时候,我们并没有直接处理这个抛出的异常,而是继续把该异常往上抛出,抛给main方法的调用者。

第二种方式是使用try-catch语句块把抛出的异常进行捕获
例如:
public static void main(String[] args) {
try {
Class.forName("test...");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

1)try-catch是尝试着去捕获这些代码抛的异常,如果try语句块中的代码没有抛出异常,那么try-catch是没有任何作用的
2)如果try语句块中的代码抛出了异常,并且抛出的异常还是catch语句要处理的异常或其子类型异常,那么这时就会执行catch语句块中的代码,进行异常出现后的处理。
3)异常对象e常用的方法
e.printStackTrace()
引用出堆栈中出现的异常跟踪信息
e.getMessage()
返回异常的详细字符串信息(如果有的话)
4)不管方法声明中抛出了什么类型的异常,我们一般都是可以再catch中使用Exception类型进行捕获到的,因为Exception是所有异常的父类型。
例如:
try {
Class.forName("test...");
....
..
} catch (Exception e) {
e.printStackTrace();
}

5)如果代码中抛出了多种异常,也可以使用多个catch来分别捕获.当然也可以只使用一个最大的异常Exception
例如:
try {
Class c = Class.forName("test..");
c.getMethod("go");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}

4.抛出和捕获对程序的影响
1)如果程序中的某行代码的执行抛出了异常,并且这个异常一种都没有被try-catch处理,那么这个异常最终会抛给JVM,JVM输出异常信息后就自动停止了
例如:
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("hello");
Class.forName("test..");
System.out.println("world");
//....其他代码
}

最终的结果是代码在调用forName方法抛出异常后,JVM处理后就停止了.并没有往下继续执行代码

2)如果使用try-catch语句去处理代码中抛出的异常,那么catch语句块处理完之后,代码还会在catch语句块下面继续执行
例如:
public static void main(String[] args){
System.out.println("hello");
try {
Class.forName("test..");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("world");
//....其他代码
}
最终的结果是catch语句执行完后,代码继续往下正常执行。

3)try-catch语句块虽然能处理完异常后继续让代码往下执行,但是在某些时候也会改变代码的执行流程(默认是从上往下顺序执行)
例如:
public static void main(String[] args){
System.out.println("hello");
try {
Class.forName("test..");
System.out.println("world");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//....其他代码
}

最终的结果是catch语句执行完后,代码执行下面的其他代码,但是上面打印world的语句就跳过去了。

5.finally语句块
由于异常处理有时候会改变程序的正常流程,这会使得某些不管在任何情况下都必须执行的步骤被忽略,从而影响程序的健壮性。

小王开了一家店,在店里上班的正常流程为:打开店门、工作8个小时、关门。异常流程为:小王在工作时突然犯病,因而提前下班
例如:
public void work() {
try {
开门();
工作8个小时();
关门();
} catch(Exception e) {
去医院();
}
}

小王在工作时突然犯病,那么流程会跳转到catch代码块,这意味着关门的操作不会被执行,这样的流程显然是不安全的,必须确保关门的操作在任何情况下都会被执行.

finally代码块能保证特定的操作总是会被执行,它的形式如下:
public void work() {
try {
开门();
工作8个小时();
} catch(Exception e) {
去医院()
} finally {
关门();
}
}

注:即使方法中执行了return语句,finally最后也是会被执行的。

6.编译异常和运行时异常
1)Exception有一个特殊的子类:RuntimeException
2)RuntimeException类型及其子类型都是属于运行时异常
3)其他类型的异常只要不是继承了RuntimeException类的,都属于编译异常
4)编译异常又称checked异常,运行时异常又称unchecked异常
因为编译器在编译期间如果遇到了checked异常,那么是一定会提示我们,让我们去处理的。但是如果遇到了unchecked异常,编译器是不做任何事情的。

常见的运行时异常:unchecked
java.lang.ArithmeticException
算术异常
java.lang.NullPointerException
空指针引用
java.lang.ArrayIndexoutofBoundsException
数组越界
java.lang.ClassCastException
强制类型转换异常
java.lang.NumberFormatException
数据格式异常
java.lang.NegativeArraySizeException
数组长度为负数异常

常见的编译异常:checked
编译器提示你需要处理的都为编译异常
java.lang.ClassNotFoundException
java.lang.DataFormatException
java.lang.NoSuchMethodException
java.io.IOException
java.sql.SQLException

7.自定义异常
在需要的情况下,可以通过扩展Exception类或RuntimeException类来创建自定义的异常(一般是扩展Exception类)。异常类包含了和异常相关的信息,这有助于负责捕获异常的catch代码块,正确地分析并处理异常

例如:我们任务在系统中用户要登录的账号和密码不匹配就是一种异常情况,但是JDK中并没有定义这种异常,所以我们可以进行自定义。
例如: 只需继承Exception即可.一般还会加入和父类中匹配的构造器
public class UserPasswordException extends Exception{

public UserPasswordException() {
super();
}

public UserPasswordException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}

public UserPasswordException(String message, Throwable cause) {
super(message, cause);
}

public UserPasswordException(String message) {
super(message);
}

public UserPasswordException(Throwable cause) {
super(cause);
}

}

例如:
注:异常是可以在代码中主动抛出的
public void login(String password)throws UserPasswordException{

if("123".equals(password)){
throw new UserPasswordException("密码错误");
}

}

将来login方法的调用者负责处理这个异常

8.断言
1)断言使用
在JDK1.4中,Java语言引入一个新的关键字: assert 该关键字有两种形式:
assert 条件

以及

assert 条件:值或表达式

这两种形式都会对条件进行评估,如果结果为false则抛出AssertionError。
在第二种形式中,值或表达式的值会传入AssertionError的
构造器并转成一个消息字符串,成为要显示的错误信息

例如:
要断言x不是负数,只需要使用如下简单的语句:
assert x >= 0;

或者你可以将x的值传递给AssertionError对象,从而可以在报错时候显示:

assert x >= 0 : x;

或者
assert x >= 0 : "x的值不符合条件:x="+x;

2. 断言内容代码编译

因为assert在JDK1.4中是一个新的关键字,因此在使用时需要告诉编译器你编译所使用jdk的版本号。

javac -source 1.4 MyClass.java

在jdk的后续版本中,对断言的支持成为默认特性(JDK5.0以上使用时就不需要这个编译了,因为默认就支持的)。

3. 断言内容代码执行

默认情况下,断言是关闭的。要通过-enableassertions或者-ea选项来运行程序以打开断言:

java -enableassertions com.briup.ch07.Xxxx
java -ea com.briup.ch07.Xxxx

打开或关闭断言功能,决定了代码在执行时是否会跳过那些和断言相关的代码.因此断言并不会降低程序运行速度。

注意:使用eclipse运行代码的时候也是可以传参数的(包括俩种参数)

例如:
java -xx com.briup.ch07.Test yy
xx是给JVM传的参数 yy是给Test类的main方法传的参数

java_day07_异常的更多相关文章

  1. alias导致virtualenv异常的分析和解法

    title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...

  2. ASP.NET Core应用的错误处理[2]:DeveloperExceptionPageMiddleware中间件如何呈现“开发者异常页面”

    在<ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式>中,我们通过几个简单的实例演示了如何呈现一个错误页面,这些错误页面的呈现分别由三个对应的中间件来完成,接下来我们将 ...

  3. 记一次tomcat线程创建异常调优:unable to create new native thread

    测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常: HTTP Status 500 - Handler processing failed; nested exception is ...

  4. 使用JSONObject.fromObject的时候出现“There is a cycle in the hierarchy”异常 的解决办法

    在使用JSONObject.fromObject的时候,出现“There is a cycle in the hierarchy”异常.   意思是出现了死循环,也就是Model之间有循环包含关系: ...

  5. SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论

    异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#signalR 后台创建了一个DntHub的集线器 前台在调用的时候出现了问题(经检查是代理对象 ...

  6. [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?

    你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...

  7. [C#] C# 知识回顾 - 学会处理异常

    学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...

  8. [C#] C# 知识回顾 - 学会使用异常

    学会使用异常 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”. 异常通常由错误的代码引发,并由能够更正错误的代码进行 catch. 异常可由 .NET 的 CLR ...

  9. [C#] C# 知识回顾 - 异常介绍

    异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...

随机推荐

  1. Elasticsearch聚合问题

    在测试Elasticsearch聚合的时候报了一个错误.具体如下: GET /megacorp/employee/_search { "aggs": { "all_int ...

  2. AcitveReocrd事件和关联操作

    ActiveRecord预定义的事件,都在 yiidbBaseActiveRecord 中进行了明确:   abstract class BaseActiveRecord extends Model ...

  3. Linux 查看 MySQL的版本信息

    Linux 查看 MySQL的版本信息 如何查看某台 Linux 主机上的 安装的 MySQL版本信息? 使用如下命令,查看 MySQL的版本信息: mysql -V 或者 mysql --versi ...

  4. Java数组(3):创建测试数据

    有时我们需要使用数组批量创建测试数据,接下来通过以下4点来举例. (1) 使用Arrays.fill()填充数据 (2) 使用Random类中JDK1.8提供的新方法用来生成随机数 (3) 一个随机数 ...

  5. python3速查参考- python基础 4 -> 元组 + 字典 + 字符串 的学习

    元组 元组:特点就是内容不可变,算只读的列表,可以被查询,不能被修改 a = 2, print(a) print(type(a)) b = ('a','b','c') print(b[1]) 运行结果 ...

  6. Jmeter接口测试 1=> 接口测试介绍

    第一节 接口测试概念 什么是接口测试概念:接口测试是测试系统组件间接口的一种测试.接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点. 测试的重点是要检查数据的交换,传递和控制管理过 ...

  7. 【ARM-Linux开发】Linux的SOCKET编程详解

    Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...

  8. JavaScript校验身份证,包含省份、长度、出生年月日、校验位的检测、性别、年龄

    一.代码如下 let vcity = {11: '北京', 12: '天津', 13: '河北', 14: '山西', 15: '内蒙古', 21: '辽宁', 22: '吉林', 23: '黑龙江 ...

  9. Eclipse中 coverage as 测试代码覆盖率

    eclipse 版本: Version: 2019-06 (4.12.0)Build id: 20190614-1200 绿色:代码被执行过黄色:代码部分被执行过红色:代码没有被执行过 引用: htt ...

  10. SpringBoot2.x集成WebSocket

    WebSocket 不做过多得介绍,这里有篇比较全面得文章      Spring Boot系列十六 WebSocket简介和spring boot集成简单消息代理 我这里是精简版,只挑出核心代码记录 ...