异常处理(try-catch)
错误的种类
一般来讲,程序出现错误的时候,大致情况有三种:
- 语法错误
- 运行时错误,指的是各程序运行的时候,出现的一些没有想到的问题,比如除数为0,比如数组下标越界等等
- 逻辑错误,运行结果和与其结果不一致,俗称bug
⭐Java中的异常处理机制主要用于处理运行时错误
异常的定义
运行时发生的错误,叫做异常,处理这些异常的代码叫做异常处理,一旦发生异常,程序将会中止在异常发生的地方,之后的代码都不会被运行- public static void main(String[] args) {
- // 这句输出会抛出异常
- System.out.println(1/0);
- // 这句输出就不会被执行
- System.out.println("tmp_text");
- }
复制代码 异常的处理方式
Java使用面向对象的方法来处理异常,在方法的执行过程中,如果出现了异常,该方法就会自动创建一个代表该异常的一个对象,将其交给运行时的系统,运行时系统自动查找对应的代码来处理这个异常,在这个过程中,生成异常,并且将其交给运行时系统的过程叫做抛出异常(throw),运行时系统,找到能处理该异常的对象的过程叫做捕获异常(catch)
异常类(Throwable类)
根据javac对异常处理的要求,把异常分为两类
- 非检查异常-运行时异常(RunTImeException):程序本身问题导致的异常,运行时异常并不一定需要做异常处理,不做异常处理,代码也可以通过编译
- 检查时异常(ChackedException):检查时异常,可能产生检查时异常的代码,不管是否产生了异常,都必须进行异常处理,负责无法通过编译,检查时异常大部分情况下和开发者无关,只和代码之外的环境有关
处理异常的方法(Try--Catch)
Try 负责存放可能会产生异常的代码,catch 负责捕捉异常
异常处理在很多的时候,只能保证哪怕发生了异常,代码整体也可以正常的运行,但是不能解决异常的问题,还是需要有开发者自己修改代码,从根源上解决问题- // 运行时异常
- // 除数为0异常是个典型的运行时异常,运行时异常并不一定需要做异常处理,不做异常处理,代码也可以通过编译
- public void test(){
- try{
- // 会产生除数为0的异常
- System.out.println(1/0);
- }catch (Exception e){
- // 打印异常相关的堆栈信息,但是并不是一定要写
- e.printStackTrace();
- }
- System.out.println("异常被处理了之后,程序依旧可以往下运行!");
- }
- // 检查时异常
- // 不管代码是否发生异常,都需要进行异常处理,负责无法通过编译,检查时异常大部分情况下和开发者无关,只和代码之外的环境有关
- public void test(){
- try {
- // 检查时异常,必须使用try——catch进行处理
- Class.forName("com.test");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- System.out.println("异常被处理了之后,程序依旧可以往下运行!");
- }
- // 如果有多条可能发生异常的语句,最好每一个语句单独处理,多条语句同时进行异常处理,会出现代码少运行的问题
复制代码 finally关键字
确保在异常发生的时候,所有的收尾工作可以正常的完成,无论是否发生异常,finally代码块中的语句都会执行
⭐如果在catch代码块中出现了return,那么也必须先执行finally中的代码之后,再return退出- // 发生异常时: try -> catch -> finally
- // 没有发生异常时:try -> finally
- public void test(int tmp) {
- try {
- System.out.println("test -> try()");
- tmp = 1 / tmp;
- } catch (ArithmeticException e) {
- System.out.println("test -> catch()");
- } finally {
- System.out.println("test -> finally()");
- }
- }
- // tmp = 1:
- // test -> try()
- // test -> finally()
- // tmp = 0:
- // test -> try()
- // test -> catch()
- // test -> finally()
复制代码 throw关键字
可以借助throw关键字,主动抛出一个指定类型的异常- public void test(){
- try {
- // 主动抛出一个空指针异常
- throw new NullPointerException();
- }catch (NullPointerException e){
- System.out.println("捕获了异常");
- }
- }
复制代码 throws关键字
如果某个方法不想处理异常,可以使用throws向上抛出异常,让上层的调用者进行异常处理- public class Test04 {
- // test01负责抛出异常
- public void test01(){
- throw new NullPointerException();
- }
- // test02运行test01时触发异常,但是并没有处理,使用throws向上抛出了此异常
- public void test02() throws NullPointerException{
- test01();
- }
- // test03处理test02向上抛出的异常
- public void test03(){
- try {
- test02();
- }catch (NullPointerException e){
- System.out.println("捕获了异常");
- }
- }
- }
复制代码 throw 和throws 的区别
- throw时语句抛出一个异常,throws是方法抛出一个异常
- throws可以单独使用,但是throw后面必须跟一个明确的异常对象
- throws出现方法的头,throw出现再方法体
- throws表现的是出现异常的一种可能性,并不代表以后一定会出现异常,但是throw一定会抛出异常
- 两种都是异常处理的消极方式,最终还是需要使用try_catch进行异常处理
常见异常类型
- RuntimeException:所有运行时异常的父类
- ArithmeticException:算数错误异常
- IllegalAccessError:方法接收到非法参数异常
- ArrayIndexOutOfBoundsException:数组下标越界异常
- NullPointerException:空指针异常
- ClassNotFoundException:找不到类异常
- IOException:IO流异常
- FileNotFoundException:找不到文件异常
- EOFException:数据流相关异常
- NoSuchMethodError:找不到方法异常
- NumberFormatException:数字转换异常
自定义异常
自定义异常类,必须是Throwable类的子类,我们需要在某一个固定场景下,通过throw去抛出这个异常- // 自定义异常 TestException
- public class TestException extends Throwable{
- public TestException(String tmp){
- super(tmp);
- }
- }
- // test中使用自定义异常
- public void test(String name){
- try {
- throw new TestException(name);
- } catch (TestException e){
- e.printStackTrace();
- }
- }
复制代码 集合
两大类集合
- Collection 单列集合:本身是一个接口
- Map 双列集合(以后再说)
Collection接口
该接口定义的是所有单列集合所具有的共性方法- public void test(){
- // 使用多态的方法新建ArrayList集合
- Collection c01 = new ArrayList();
- Collection c02 = new ArrayList();
- // 往集合里添加数据
- for (int i = 0; i < 5; i++) {
- c01.add("robot0" + i);
- }
- for (int i = 6; i < 10; i++) {
- c02.add("robot0" + i);
- }
- // 删除集合内元素
- c01.remove("robot01");
- // 判断集合是否为空
- System.out.println(c01.isEmpty());
- // 输出集合内元素个数
- System.out.println(c01.size());
- // 合并两个集合
- c01.addAll(c02);
- // 遍历集合
- for (Object o : c01) {
- System.out.print(o + "\t");
- }
- System.out.println();
- // 判断c01中是否含有c02中的所有元素
- System.out.println(c01.containsAll(c02));
- // 判断c01中是否有"robot03"这个元素
- System.out.println(c01.contains("robot03"));
- // 从c01中移除所有c02中的元素
- c01.removeAll(c02);
- // 重新遍历集合
- for (Object o : c01) {
- System.out.print(o + "\t");
- }
- }
复制代码 集合的泛型
泛型大部分情况下适用于集合,泛型的作用,在使用的时候去限制数据的类型范围- public class Dog {
- private String name;
- private String type;
- }
- public class Student {
- private int sno;
- private String name;
- }
- // 创建一个集合,这个集合只能存储dog类的对象的地址
- public void test(){
- List<Dog> dogList = new ArrayList<>();
- Dog dog01 = new Dog("001","Dog01");
- Dog dog02 = new Dog("002","Dog02");
- Dog dog03 = new Dog("003","Dog03");
- // 这个dogList只能存储Dog类型的对象,因此集合使用泛型,可以限制集合中存储的数据类型
- dogList.add(dog01);
- dogList.add(dog02);
- dogList.add(dog03);
- }
- // 创建一个集合,这个集合只能存储dog类和Student类的对象的地址
- // 扩展集合类型,需要使用接口的概念
- public class Student implements Animal{
- private int sno;
- private String name;
- }
- public class Dog implements Animal{
- private String name;
- private String type;
- }
- //两个类同时继承同一个接口类
- public void test(){
- List<Animal> animalList = new ArrayList<>();
- Dog dog01 = new Dog("001","Dog01");
- Dog dog02 = new Dog("002","Dog02");
- Dog dog03 = new Dog("003","Dog03");
- Student student01 = new Student(1001,"Robot01");
- // 这个dogList只能存储Dog类型的对象,因此集合使用泛型,可以限制集合中存储的数据类型
- animalList.add(dog01);
- animalList.add(dog02);
- animalList.add(dog03);
- animalList.add(student01);
- }
复制代码 List接口常用实现类
list接口相对于collection额外多了一些get,set方法
三个常用实现类:ArrayList(不保证线程安全,性能稍好),LinkedList(底层是链表),Vector(已经弃用)
List特点:- 1. 有序集合:存储元素的顺序和读取元素的顺序一致
- 1. 允许存储重复的元素
- 1. 有索引,可以使用普通的for循环进行遍历
复制代码- public void test(){
- List list01 = new ArrayList();
- // list添加元素
- for (int i = 0; i < 5; i++) {
- list01.add("robot0 " + i);
- }
- // 遍历list
- System.out.println(list01);
- // 指定位置改变
- list01.set(1,"ROBOT");
- System.out.println(list01);
- // 指定位置插入
- list01.add(5,"robot pro");
- System.out.println(list01);
- }
复制代码 List的遍历方式
[code]// 1. for循环遍历for(int i = 0 ; i |