【Day05-异常、Lambda、常见算法】

1. 异常

        1.1 什么是异常

        1.2 异常的体系

                Error:代表的系统级别错误(属于严重问题),也就是说系统一旦出现问题,sun公司会把这些问题封装成Error对象给出来,说白了,Error是给sun公司自己用的,不是给我们程序员用的,因此我们开发人员不用管它。

                Exception:叫异常,它代表的才是我们程序可能出现的问题,所以,我们程序员通常会用Exception以及它的孩子来封装程序出现的问题。

                运行时异常:RuntimeException及其子类,编译阶段不会出现错误提醒,运行时出现的异常(如:数组索引越界异常)

                编译时异常:编译阶段就会出现错误提醒的。(如:日期解析异常)

/*
异常
    代表程序出现的问题

异常体系
    Throwable
        Error 代表的系统级别错误 (属于严重问题),Error是给sun公司自己用的,我们了解即可
        Exception 代表异常,程序可能出现的问题,我们通常会用Exception以及它的子类来封装程序出现的问题
            RuntimeException 运行时异常(非受检异常),例如数组索引越界、空指针、数学运算异常等
            其他Exception    编译时异常(受检异常),例如解析异常

JVM默认处理是常的方式
    1. 打印异常信息
    2. 立即结束程序(异常出现后,如果不处理,程序是无法继续向下运行的)
*/
public class Demo1 {
    public static void main(String[] args){
        //1. 运行时异常(非受检异常),例如数组索引越界、空指针、数学运算异常等
        //1-1 数组索引越界
//        int[] arr = new int[3];
//        System.out.println(arr[3]);//ArrayIndexOutOfBoundsException
        //1-2 空指针
//		int[] arr1 = null;
//        System.out.println(arr1[1]);//NullPointerException
        //1-3 数学运算
//        int a = 10 / 0;//ArithmeticException

        //2. 编译时异常(受检异常),例如解析异常
        //日期格式解析异常
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("2024-08-30 12:02:51");
        Date parse = simpleDateFormat.parse("2024-08-30 12:02:51");//这就是受检异常,需要在上边抛出异常
    }
}

        1.3抛出异常

                1.3.1 throws

                抛出异常(throws)

  • Java 的方法调用中,如果一个方法中出现了异常,本方法自己不处理,默认是会抛给调用方法去处理的
  • 此时要注意的是,如果发生的是非运行时异常,需要在方法上明确使用 throws 关键字声明抛出

/*
异常处理的方案1--抛异常
    在Java的方法调用中,如果一个方法中出现了异常,本方法自己不处理,默认是会抛给调用方法去处理的
    此时要注意的是,如果发生的是非运行时异常,需要在方法上明确使用throws关键字声明抛出

格式
    public void 方法名 throws 异常1 ,异常2 ,异常3 ..{
        方法体
        throw new Exception()
    }
*/
public class Demo2 {

    public static void main(String[] args) throws Exception {
        printLength();
    }

    //如果出现多种异常,直接写最大的 throws Exception
    public static void printLength() throws Exception {
//        String str = null;//NullPointerException
//        System.out.println(str.length());
        System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse("2002-02-02"));

        new File("").createNewFile();//IOException
    }
}

                1.3.2 try...catch

                捕获异常(try…catch)

  • 直接在当前方法,发生异常的代码外使用try--catch--结构捕获并处理异常
  • 异常处理后,后续的代码是可以继续执行的

/*
异常处理的方案2--捕获异常
    直接在当前方法,发生异常的代码外使用try--catch--结构捕获并处理异常
    异常处理后,后续的代码是可以继续执行的

格式
    public void 方法名{
        try{
            // 方法体
        }catch(异常类型1 变量){
            // 处理异常
        }catch(异常类型2 变量){
            // 处理异常
        }
    }
*/
public class Demo3 {
    public static void main(String[] args) {
        print();
    }

    private static void print() {
        try {
            String str = null;
            System.out.println(str.length());
            System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse("2002-02-02"));
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("sys大帅b");
        }

    }

}

         1.4 自定义异常

        自定义异常

        Java无法为这个世界上全部的问题都提供异常类来代表, 如果以后我们自己写的代码中的某种问题,想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了。

/*
自定义异常
    Java无法为这个世界上全部的问题都提供异常类来代表,如果以后我们自己写的代码中的某种问题,
    想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了。

自定义运行时异常
    1、定义一个异常类,继承RuntimeException
    2、在类中提供构造函数
    3、在需要抛出异常的地方使用throw关键字 抛出异常类的对象
*/
public class Demo4 {
     public static void main(String[] args) {
        //模拟用户登录,用户名:admin,密码123456
         System.out.println(login("admin", "12345"));
     }

    //设置登录的方法

    public static String login(String name, String password) {
         if (!name.equals("admin")) {
             //1.用户登录失败,用户名错误
            throw new LoginException("用户登录失败,用户名错误");//LoginException: 用户登录失败,用户名错误
         } else if (!password.equals("12345")) {
             //2.用户登录失败,密码错误
            throw new LoginException("用户登录失败,密码错误");//LoginException: 用户登录失败,密码错误
         } else {
             //3.登录成功
             return "用户登录成功,用户名:" + name;//用户登录成功,用户名:admin
         }
    }
}

//自定义运行时异常
class LoginException extends RuntimeException {
    public LoginException(String message) {
        super(message);
    }
}
/*
自定义异常
    Java无法为这个世界上全部的问题都提供异常类来代表, 如果以后我们自己写的代码中的某种问题,
    想通过异常来表示,以便用异常来管理该问题,那就需要自己来定义异常类了。

自定义编译时异常
    1、定义一个异常类,继承Exception
    2、在类中提供构造函数
    3、在需要抛出异常的地方使用throw关键字 抛出异常类的对象

注意
    编译时异常,在编写代码的过程中必须手动处理

异常的作用
    1、异常是用来查找系统bug 的关键参考信息
    2、异常可以作为方法内部一种特殊的返回值,以便通知上层调用者,代码底层的执行情况
*/
public class Demo5 {
    public static void main(String[] args) throws LoginException1 {
        //模拟用户登录,用户名:admin,密码123456
        try {
            System.out.println(login("admin", "12345"));
        } catch (LoginException1 loginException1) {
            loginException1.printStackTrace();
        }
    }

    //设置登录的方法
    public static String login(String name, String password) throws LoginException1 {
        if (!name.equals("admin")) {
            //1.用户登录失败,用户名错误
            throw new LoginException1("用户登录失败,用户名错误");//LoginException: 用户登录失败,用户名错误
//            LoginException1 le = new LoginException1("用户名错了");
//            throw le;
        } else if (!password.equals("12345")) {
            //2.用户登录失败,密码错误
            throw new LoginException1("用户登录失败,密码错误");//LoginException: 用户登录失败,密码错误
        } else {
            //3.登录成功
            return "用户登录成功,用户名:" + name;//用户登录成功,用户名:admin
        }
    }
}

//自定义编译时异常
class LoginException1 extends Exception {
    public LoginException1(String message) {
        super(message);
    }
}

2.Lambda 

        2.1 Lambda简述

        Lambda表达式

        Lambda表达式是JDK 8开始新增的一种语法形式; 作用:用于简化匿名内部类的代码写法。

/*
Lambda表达式
    是JDK8开始新增的一种语法形式,主要用来简化匿名内部类代码的书写

Lambda格式
    (被重写方法的参数列表)->{
        被重写方法的方法体;
    }

Lambda使用前提
    Lambda只能操作函数式接口(有且仅有一个抽象方法的接口,被FunctionalInterface注解修饰)

练习
    1. 使用Lambda优化前天Arrays中的Demo1和Demo3案例
    2. 完成Demo2~Demo4
*/
public class Demo1 {
    public static void main(String[] args) {
        //匿名内部类操作接口
        Person person = new Person() {
            @Override
            public void eat() {
                System.out.println("人吃饭");
            }
        };
        person.eat();
        //Lambda简化
        Person person1 = ()->  System.out.println("人吃牛波一饭");
        person1.eat();
        System.out.println("===========================================");

        //匿名内部类操作抽象类
        Animal animal = new Animal() {
            @Override
            void eat() {
                System.out.println("狗吃大刀肉");
            }
        };
        animal.eat();
        //Lambda简化
        //匿名内部类不是函数式接口
    }

}


//接口
interface Person {
    void eat();
}

//Lambda只能操作函数式接口(有且仅有一个抽象方法的接口,被FunctionalInterface注解修饰)
//抽象类
abstract class Animal {
    abstract void eat();
}

        2.2 Lambda表达式省略写法

        Lambda表达式的省略写法(进一步简化Lambda表达式的写法)

  • 参数类型可以省略不写
  • 如果只有一个参数,小括号()也可以省略。
  • 如果Lambda表达式方法体代码只有一行代码可以省略花括号{}不写同时要省略分号!此时,如果这行代码是return语句,必须去掉return不写
public class Demo4 {

    public static void main(String[] args) {
        //调用test完成 a+b  的计算
        test(((a, b) -> a + b));

        new Calculator(){
            @Override
            public double add(double a, double b) {
                return Math.pow(a,b);
            }
        };

    }

    public static void test(Calculator calculator) {
        System.out.println("运算结果:" + calculator.add(10, 20));
    }
}


interface Calculator {
    double add(double a, double b);
}

3. 算法 

        3.1 排序算法

/*
冒泡排序
    相邻的两个元素进行比较,小的放左边大的放右边,完成升序排列

实现步骤
    确定总共需要做几轮: 数组长度-1
    每轮比较几次: 轮数从0计数的话, 就是数组长度-1-当前轮数
    比较规则: 相邻两个元素比较,大的放在右边
*/
public class Demo1 {
    public static void main(String[] args) {
        int[] arr = {5, 2, 3, 1};
        bubbleSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

 

/*
选择排序
    每轮选择当前位置,开始找后面的最小值,与当前位置交换

关键点分析
    确定总共需要做几轮: 数组长度-1
    每次的基准位:轮数从0计数的话, 就是基准位索引敲好就是轮数
    比较规则: 以每次的第一个为基准做比较,谁小谁来基准位
*/
public class Demo2 {
    public static void main(String[] args) {
        int[] arr = {5, 2, 3, 1};
        selectionSort(arr);
        System.out.println(Arrays.toString(arr));
    }


    private static void selectionSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = i + 1; j < arr.length ; j++) {
                if (arr[i] > arr[j]) {
                    int temp = arr[j];
                    arr[j] = arr[i];
                    arr[i] = temp;
                }
            }
        }
    }
}

        3.2 二分查找

/*
二分查找/折半查找
    前提是数组有序
    特点是每一次查找完成,会舍去一半元素

思路分析
    1、定义两个指针,指向数组第一个和最后一个索引位置
    2、循环查找,min小于等max则继续(三个指针可能重叠的)
    3、每次循环进来,重新计算中间指针
    4、判断情况1:如果mid指向的元素就是num,则返回mid
    5、判断情况2:如果要查找的元素,在左半边,舍弃max重新计算
    6、判断情况3:如果要查找的元素,在右半边,舍弃min重新计算
    7、循环结束没有找到,则代表不存在,返回-1
 */
public class Demo1 {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};

        System.out.println(binarySearch(arr, 1));
        System.out.println(binarySearch(arr, 2));
        System.out.println(binarySearch(arr, 3));
        System.out.println(binarySearch(arr, 4));
        System.out.println(binarySearch(arr, 5));
        System.out.println(binarySearch(arr, 6));
        System.out.println(binarySearch(arr, 7));
        System.out.println(binarySearch(arr, 8));
        System.out.println(binarySearch(arr, 9));
        System.out.println(binarySearch(arr, 10));
    }

    //二分查找
    private static int binarySearch(int[] arr, int num) {
        //1.设置开始和结束索引
        int left = 0;
        int right = arr.length - 1;
        //2.计算中间索引
        int mid = (left + right) / 2;
        //3.使用while循环,条件:左侧开始索引 <= 结束索引
        while (left <= right) {
            //4.使用中间索引的数据和需要查询的num比较
            if (arr[mid] == num) {
                return mid;
            };
            if (arr[mid] >= num) {
                right = mid - 1;
                mid = (left + right) / 2;
            } else {
                left = mid + 1;
                mid = (left + right) / 2;
            }
        }
        return -1;
    }
}

 

  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值