学习笔记——异常&&双链表

一、学习重点

二、学习内容

Question1:

try...catch..finally执行顺序:
finally永远是在最后执行的
public static int test1(){
        int i = 10;
        try {
            i++;
            System.out.println("try:" + i);
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
        }finally {
            i = 100;
            System.out.println("finally:" + i);
        }
        return i;
    }

    public static int test2(){
        int i = 10;
        try {
            i++;
//            System.out.println("try:" + i);
            throw new Exception();
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
        }finally {
            i = 100;
            System.out.println("finally:" + i);
        }
        return i;
    }
    // try---finally---return
    public static int test3(){
        int i = 10;
        try {
            i++;
            System.out.println("try:" + i);
            return i;
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
            return i;
        }finally {
            i = 100;
            System.out.println("finally:" + i);
        }
    }
    // try...finally...return
    public static int test4(){
        int i = 10;
        try {
            i++;
            System.out.println("try:" + i);
            return i;
        }catch (Exception e){
            i--;
            System.out.println("catch:" + i);
            return i;
        }finally {
            i = 100;
            System.out.println("finally:" + i);
            return i;
        }
    }

    public static void main(String[] args) {
//        System.out.println(test1());
//        System.out.println(test2());
//        System.out.println(test3());
        System.out.println(test4());
    }

双链表:

class Node {
    // 数据本身
    Integer data;
    // 上一个结点的地址
    Node prev;
    // 下一个结点的地址
    Node next;

    public Node() {
    }

    public Node(Integer data) {
        this.data = data;
    }
}
public class DoubleLinked {

    // 维护一个头结点,头结点不要动,不存放具体的数据
    private Node head = new Node(0);

    // 返回头结点
    public Node getHead() {
        return head;
    }

    // 显示链表(遍历)
    public void list() {
        if(head.next == null){
            System.out.println("链表为空...");
            return;
        }
        // 因为头结点,不能动,我们需要一个辅助变量来帮我们遍历
        Node temp = head.next;
        while(true) {
            // 判断是否走到最后
            if(temp == null){
                break;
            }
            System.out.println(temp.data);
            // 将指针后移
            temp = temp.next;
        }
    }

    // 添加结点到链表最后
    // 默认添加的是到链表的最后一个位置
    // 找到链表的最后一个结点
    // 把这个结点的下一个指向当前结点
    // 当前结点的上一个结点指向之前的最后一个结点
    public void add(Node node) {
        // 因为我们头结点不能动,我们
        Node temp = head;
        while(true) {
            // 找到链表的表尾结点
            if(temp.next == null){
                break;
            }
            // 如果没有找到最后,将temp后移
            temp = temp.next;
        }
        // 当退出while循环时,temp指针就指向了最后
        temp.next = node;
        node.prev = temp;
    }

    // 在指定位置新增
    public void add(Node node,int index){

    }
    // 查询指定位置的结点
    public Node getNode(int index) {

//        for (int i = 0; i < index; i++) {
//
//        }

        return null;
    }


    // 修改一个结点的内容
    public void update(Node node,Node newNode) {
        // 判断是否为空
        if(head.next == null){
            System.out.println("链表为空...");
            return;
        }
        // 找到要修改的结点,根据data找
        // 定义一个辅助变量
        Node temp = head.next;
        boolean flag = false;
        while(true) {
            if(temp == null) {
                break; // 已经找完一遍了,没找到
            }
            if(temp.data == node.data){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        // 根据flag判断是否找到要修改的结点
        if(flag) {
            // 改变这个结点的内容
            temp.data = newNode.data;
        }else {
            System.out.println("没有找到" + node.data + "结点...");
        }
    }

    // 从双向链表中删除一个结点
    // 1.对于双向链表,我们先要找到要删除的这个结点
    // 2.找到后,直接删除
    public void del(Integer data){
        // 判断是否为空
        if(head.next == null){
            System.out.println("链表为空...");
            return;
        }
        // 找到要修改的结点,根据data找
        // 定义一个辅助变量
        Node temp = head.next;
        boolean flag = false;
        while(true) {
            if(temp == null) {
                break; // 已经找完一遍了,没找到
            }
            if(temp.data == data){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag) { //找到了
            // 删除
//            temp.next = temp.next.next;
            temp.prev.next = temp.next;
            // 这里我们写的有点问题?
            // 如果是最后一个结点,
            if(temp.next != null){
                temp.next.prev = temp.prev;
            }
        }else {
            System.out.println("没有找到" + data + "结点...");
        }
    }
    public static void main(String[] args) {
        DoubleLinked doubleLinked = new DoubleLinked();
        doubleLinked.add(new Node(1));
        doubleLinked.add(new Node(2));
        doubleLinked.add(new Node(3));
        doubleLinked.add(new Node(4));

//        doubleLinked.update(new Node(5),new Node(30));
        doubleLinked.del(4);

        doubleLinked.list();
//        System.out.println(doubleLinked.getHead());
    }
}

三、笔记内容

异常处理
1、下标越界
2、空指针
3、类型转换异常
4、数字格式化
5、算数异常(数学异常)

编程界:
1、除数为0
2、IO流,没有关闭
3、停电
当一个程序抛异常,抛异常后面的语句不再执行,类似于return的功能,终止方法的执行
public static void main(String[] args)  {
        int num1 = 10;
        int num2 = 0;
//        double num3 = 0;
        System.out.println(num1/num2);// by zero
//        System.out.println(num1/num3);//Infinity 无穷大
        System.out.println("我很重要");
    }
异常的继承体系结构
最顶级的Throwable:错误,异常
Error:正常情况下,不太可能出现的。绝大多数Error都会导致程序处于非正常状态下,很难恢复
外力的作用下,不考虑。
Error是Throwable的子类。它是在Java程序处理范围之外的
Exception:Java语言中,将程序执行中发生的不正常的情况称之为异常
编译期异常:写代码的时候,抛异常。如果编译期不解决,会编译不通过
运行期异常:RunTimeException,运行时会抛异常,平时没事
自定义异常:Java中的异常机制,结合实际业务。
怎么自定义异常?
1、所有的异常必须是Throwable的子类(大材小用,没必要)
2、如果要定义一个编译期异常,需要继承Exception类
3、如果要定义一个运行期异常,需要继承RunTimeException类
public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        //处理异常
        try {
            //有可能抛出异常的代码放到try语句块里
            System.out.println(num1/num2);// by zero
        } catch (Exception e){
            System.out.println("除数不能为零");
            e.printStackTrace();
        }
        System.out.println("我很重要");
    }

编译期异常

public class MyException extends Exception {
    public MyException(String message) {
        super(message);
    }
}

运行期异常

public class MyRuntimeException extends RuntimeException {
    public MyRuntimeException(String message) {
        super(message);
    }
}
错误码和异常信息
public class ServiceException extends RuntimeException {

    //错误码
    private Integer code;

    //异常信息
    private String message;

    public ServiceException() {
    }

    public ServiceException(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
try...catch
在一个语句块中,如果使用throw抛出一个编译期异常,就必须在方法的声明处使用throws关键字来标记异常
还有一种处理方式,就是try...catch

我们为什么要手动抛异常
因为要配合全局异常处理机制来解决
public static void fun(int i, int j) throws MyException {
        if (j==0){
            throw new  MyException("除数不能为0");
        }
        System.out.println(i/j);
    }

    public static void main(String[] args)  {
        try {
            fun(1,0);
        } catch (MyException e) {
            e.printStackTrace();
        }

    }
throw语句时可以当作方法的返回值的

在一个有返回值的方法中,如果有条件分支,一定要保证每种条件下都有条件异常

开发中大部分情况下,使用的都是运行期异常!!!
public static String show(String str){
        if (!Objects.isNull(str)){
            return str.concat("hello");
        }
//        throw new RuntimeException("参数不能为空");
        throw new ServiceException(101,"账号不能为空");
    }

    public static void main(String[] args) {
        show(null);
//        show("null");
    }
异常链
一个异常被抛出去之后会继续被调用这个方法的方法捕获被抛出,异常会扩散

只要说解决异常,处理异常,捕获 就是try...catch
class A{
    public void a(){
        throw new ServiceException(201,"业务异常...");
    }
}
class B{
    public void b(){
        A aa= new A();
        try {
            aa.a();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        System.out.println("B方法的语句");

    }
}
class C{
    public void c(){
        B bb= new B();
        bb.b();
    }
}

public class Ch05 {
    public static void main(String[] args) {
        C c = new C();
        c.c();
    }
}
如果一个方法没有捕获一个编译期异常,该方法必须使用throws异常
throws并不是真正的解决了异常,只是把异常抛给了下一级调用者
service层,干脏活和累活的

面试题:
throws和throw区别

throws出现在方法的声明处,抛出多个异常,用逗号隔开
public void show() throws MyException,RuntimeException,NullPointerException{

    }

    public void info() throws MyException {
        show();
    }

    public static void main(String[] args) {
        try {
            new Ch06().info();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
finally:关键字
finally用来创建在try代码块后面执行的代码块
无论是否方法异常,finally代码块中的代码一定会执行,一般finally中的finally

try...catch...finally
try...finally
public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        String str = null;
        //处理异常
        try {
            //有可能抛出异常的代码放到try语句块里
            System.out.println(num1/num2);
            System.out.println(str.length());
        } catch (ArithmeticException e){
            e.printStackTrace();
        }finally {
            System.out.println("finally...");
        }
    }
catch可以写多个,有顺序问题。
先写小的,再写大的
int num1 = 10;
        int num2 = 0;
        try {
            System.out.println(num1 / num2);
            // 开发角度来说,应该写指定的。
        } catch (ArithmeticException e) {
//            e.printStackTrace();
            System.out.println("除数不能为0");
        } catch (Exception e){
            System.out.println("未知错误");
        }
    }
方法的重写
4.重写的方法不能抛出比被重写方法更大的异常类型
interface Inter01 {

    void show() throws Exception;
}

public class Ch09 implements Inter01  {

    @Override
    public void show() throws NullPointerException {

    }
}

 

posted @ 2022-07-29 22:32  LJMMJL  阅读(27)  评论(0)    收藏  举报