异常
一、异常
1、什么是异常
异常是应用程序在运行过程中出现的错误或者非正常的意外情况,即虚拟机的通常操作中可能遇到的异常,是一种常见的运行错误。
常见情况:数组下标越界、空指针的访问、试图读取不存在的文件、数学除零等
2、为什么用异常
运行时发生的错误如果没有异常处理机制,程序将会终止并使所有已分配资源的状态保持不变,这样会导致资源泄露。
异常处理机制由编译器强制执行
3、异常的分类
在Java语言中,异常
可以看作是一个类,异常类的根是Throwable。Throwable是类库java.lang包中的一个类,并派生出Exception类和Error类两个子类
3.1、异常类的结构
Throwable |____Error |____Exception |____RuntimeException |____其它Exception
Error:Java运行系统中的内部错误以及资源耗尽的情况。
Exception:RuntimeException及其子类(编程导致的异常)、其它Exception类
3.2、Error体系
Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形。
应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出)。
如果出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。
所以,在进行程序设计时,应该更关注Exception体系。
3.3、Exception体系
Exception
体系包括RuntimeException
体系和其他非RuntimeException
的体系 :
-
RuntimeException
:该体系包括错误的类型转换、数组越界访问和试图访问空指针等等。如果出现RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。
-
其他非
RuntimeException
(IOException等等):这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误
3.4、异常类的层次结构
二、异常处理
1、异常产生过程
Java中每种异常都是使用一个Java类来表示
异常的产生,大致经历以下几个阶段:
-
Java程序在执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统,这个过程称为抛出(throw)异常。
-
当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常。
-
如果Java运行时系统找不到可以捕获异常的方法,则运行时系统将终止,相应的Java程序也将退出
所以需要对异常进行处理,否则程序将立即终止,无法继续执行。
2、异常处理方式
对于异常有两种处理方法 :
-
捕获异常:通过try ... catch方法,catch子句中放置处理异常的语句。
-
向上抛异常:在方法名后面加上throws Exception..., 方法本身只是抛出异常,由函数调用者来捕获异常。
3、try…catch
3.1、基本结构:
try{ 监控代码 }catch(异常类型){ 处理语句 }
-
catch后面小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型。
-
catch可以写多个,从上到下,必须遵守从小到大。(也可在try下再写一个try{}catch{})
-
可以这样书写:
catch(FileNotFoundException | ArithmeticException | NullpointerException e) { … }
-
建议catch的时候,精确的一个一个处理,有利于程序的调试
4、finally 块
finally语句的主要作用是在try或catch转到其他部分前做的一些
善后
工作。比如:关闭打开的文件,释放链接、内存等系统资源。有时需要清理代码,但程序已经停止运行,使用finally 块可使程序不管发生什么异常都将执行
4.1、finally 块作用
-
finally是异常处理语句结构的一部分,表示无论什么情况都要执行的模块。
-
finally语句的执行是一种无条件的操作,无论在哪种异常下都会执行,即使try或catch模块中有continue、return、break等关键字,或者是有throw语句,程序都会执行finally 语句。
-
每个try语句至少有一个catch子句或finally子句
4.2、try、catch 和 finally 块的执行流程
5、throws关键字
throws总是出现在一个函数头中,用来标明该成员函数可能抛出的各种异常。对大多数Exception子类来说,Java 编译器会强迫你声明在一个成员函数中抛出的异常的类型
6、throw语句
throw
关键字通常用在方法体中,并且抛出一个异常对象。
-
程序在执行到
throw
语句时立即停止,它后面的语句都不执行。 -
通过
throw
抛出异常后,如果想在上一级代码中来捕获并处理异常,则需要在抛出异常的方法中使用throws
关键字在方法声明中指明要抛出的异常; -
如果要捕捉
throw
抛出的异常,则必须使用try—catch
语句
本例子接合自定义异常展示
7、自定义异常
JavaAPI提供的内置异常不一定总能捕获程序中发生的所有错误。有时会需要创建用户自定义异常
7.1、格式
public class XXXExcepiton extends Exception | RuntimeException{ 提供无参数的构造方法 或 提供一个有参数的构造方法,可自动生成 }
注意: 1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类 2.自定义异常类,必须的继承Exception或者RuntimeException 3.继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try...catch 4.继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理)
7.2、自定义异常MyException
public class MyException extends Exception { private static final long serialVersionUID = 1L; public MyException() { } public MyException(String message) { super(message);// 把参数传递给Throwable的带String参数的构造方法 } }
集合
一、集合
Java中的集合(collection)和数学上直观的集(set)的概念是相同的。集是一个唯一项组,也就是说组中没有重复项。
-
集内只包含每项的一个实例
-
集可以是有限的,也可以是无限的
1、为什么用集合
-
不知道存放对象的个数
-
与数组相比更加实用灵活
-
更加面向对象
2、体系结构
2.1、架构图
2.2、Collection接口
Collection 接口用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。Collection 在前面的大图也可以看出,它是List和Set 的父类,并且它本身也是一个接口,它定义了作为集合所应该拥有的一些方法。
-
集合必须只有对象,集合中的元素不能是基本数据类型。
-
Collection接口支持如添加和除去等基本操作。设法除去一个元素时,如果这个元素存在,除去的仅仅是集合中此元素的一个实例
方法名 | 描述 |
---|---|
add(E e) | 确保此 collection 包含指定的元素(可选操作) |
clear() | 移除此 collection 中的所有元素(可选操作) |
contains(Object o) | 如果此集合包含指定的元素,则返回 true |
isEmpty() | 如果此集合不包含元素,则返回 true |
iterator() | 返回此集合中的元素的迭代器 |
remove(Object o) | 从该集合中删除指定元素的单个实例(如果存在)(可选操作) |
size() | 返回此集合中的元素数。 |
toArray() | 返回一个包含此集合中所有元素的数组 |
2.3、Set 接口
Set 接口继承 Collection,但不允许重复,使用自己内部的一个排列机制
2.4、List 接口
List 接口继承 Collection,允许重复,以元素安插的次序来放置元素,不会重新排列
2.5、Map接口
Map接口是一组成对的键-值对象,即所持有的是key-value 形式。Map中不能有重复的key。拥有自己的内部排列机制。 关键字决定了对象在映射中的存储位置,检索对象时必须提供相应的关键字,就像在字典中查单词一样
二、List接口
1、概念
java.util.List接口继承自Collection接口,在List集合中允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素,另外List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致
2、List 的分类
List 可以分为以下几类:
-
ArrayList
ArrayList 是一种基于数组实现的 List,可以动态地增加和缩减数组的大小。ArrayList 支持快速随机访问和插入操作,但是在删除和插入操作时需要移动数组中的元素,所以效率比较低。ArrayList 是线程不安全的,不适用于多线程环境。
-
LinkedList
LinkedList 是一种基于链表实现的 List,可以快速插入和删除元素,但是随机访问元素的效率比较低。LinkedList 是线程不安全的,不适用于多线程环境。
-
Vector
Vector 是一种与 ArrayList 相似的 List,支持快速随机访问和插入操作,并且支持同步操作,适用于多线程环境。Vector 的效率比 ArrayList 低,不推荐在单线程环境中使用
3、ArrayList
ArrayList是List 接口的大小可变数组的实现。允许包括 null 在内的所有元素。每个 ArrayList 实例都有一个容量。该容量是用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长
3.1、类结构
3.2、常用方法
方法 | 说明 |
---|---|
void add(int index, Object element): | 在指定位置index上添加元素element |
boolean addAll(int index, Collection c): | 将集合c的所有元素添加到指定位置index |
Object get(int index): | 返回List中指定位置的元素 |
int indexOf(Object o): | 返回第一个出现元素o的位置,否则返回-1 |
int lastIndexOf(Object o) : | 返回最后一个出现元素o的位置,否则返回-1 |
Object remove(int index) | 删除指定位置上的元素 |
Object set(int index, Object element) | 用元素element取代位置index上的元素,并且返回旧的元素 |
4、泛型
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
List<String> list = new ArrayList<String>(); 或List<String> list = new ArrayList<>(); "<>"里的就是泛型,不然默认为Object型,什么都能放入,调用时容易出错 有泛型,一加入不同类型直接报错
5、迭代器
迭代器是一种设计模式,它是一个对象,它可以遍历并选择集合中的对象,而开发人员不需要了解该集合的底层结构
Java中的Iterator功能比较简单,只能单向移动:
-
使用方法iterator()要求容器返回一个Iterator。
-
第一次调用Iterator的next()方法时,它返回序列的第一个元素。
-
使用next()获得序列中的下一个元素。
-
使用hasNext()检查序列中是否还有元素。
-
使用remove()将迭代器所指向的集合删除元素。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素