【JavaSE】异常的初步认识

news2024/11/19 15:13:10

目录

1、初步认识异常

1、算数异常

 2、空指针异常

 3、数组越界异常

2、异常的结构体系

3、异常的分类

1、编译时异常/受查异常 

2、运行时异常/非受查异常 

4、异常的处理 

1、处理异常的编程方式(防御式编程)

1、事前防御性(LBYL)

2、事后认错行 (EAFP)

2、异常的抛出 

3、异常的捕获

1、异常声明(关键字throws)

2、try和catch关键字(捕获并处理异常)  

3、finally关键字 

4、异常的处理流程 

 5、自定义异常类


1、初步认识异常

在Java中,将程序执行过程中发生的不正常行为成为异常,比如下面常见的例子:

1、算数异常

public class Test {
    public static void main(String[] args) {
        System.out.println(10/0);
    }
}

 来看上面的提示的异常:java.lang.ArithmeticException.他表示的是包当中的类,所以这里我们可以认为ArithmeticException(算数异常)是一个类。

 2、空指针异常

public class Test{ 
    public static void main(String[] args) {
        int[] array = null;
        System.out.println(array.length);
    }
}

 NullPointerException(空指针异常)表示的也是一个类存在于java.lang包当中。

 3、数组越界异常

public class Test{
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};
        System.out.println(array[10]);
    }
}

 像上述两个异常一样,ArrayIndexOutOfBoundsException(数组越界异常)也属于java.lang包当中。

 从上述过程中可以看到,Java中不同类型的异常,都有与其对应的类来进行描述。

❗❗❗【注意事项】

1、当发生异常之后,没有人为处理异常的时候,那么后面的内容不会被执行。

2、在以后的学习当中,我们会遇到各种各样的异常,当我们不知道某种异常产生的原因或者不知道什么错误可以导致这种异常产生的时候

🔆第一种方式:我们可以看这个异常的注释

第二种方式:可以查看这个技术网站:stackoverflow,但是这个网站是国外的网站,查询的时候会非常的慢。

2、异常的结构体系

异常种类繁多,为了对不同异常或者错误进行很好的分类管理,Java内部维护了一个异常的体系结构:

从上图可以看到:

  1. Throwable:是异常体系的顶层,其派生两个重要的子类Error (错误)和 Exception(异常)。
  2. Error:指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误、资源耗尽等。
  3. Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行。我们平时所说的一场就是Exception。

3、异常的分类

异常可能在编译时发生,也可能在程序运行时发生根据发生的时机不同,可以将异常分为:编译时异常运行时异常

1、编译时异常/受查异常 

在程序编译期间发生的异常,称为编译时异常,也称为受查异常(Checked Exception)。

此时这种异常要处理掉,不然编译不会通过。

举例:当我们创建一个student类,让他实现Cloneable接口,并在Student类当中重写clone()方法,在Test类当中创建Student类的对象,并调用clone方法。

像上述的算数异常、空指针异常、数组越界异常,他们在编译时并没有报出异常,都正常编译通过,但上图在编译时,就出现了红色波浪线,表示出现异常,那为什么会出现这种情况呢?

像算数异常、空指针异常、数组越界异常,都是运行时异常(非受查异常) ;像上图出现的克隆异常,被称为编译时异常(受查异常)

【注意事项】

下面的这种情况不属于编译时异常:编译时出现的语法错误不能称之为异常  

 以上这两种都不属于编译时异常,这只是语法错误。所以在写代码的时候,一定要分辨清楚是语法错误还是编译时异常。

2、运行时异常/非受查异常 

  • 在程序执行期间发生的异常,称为运行时异常,也成为非受查异常(Unchecked Exception)
  • RuntimeException以及其子类对应的异常,都称为运行时异常,比如:之前的算数异常(ArithmeticException)、空指针异常(NullPointerException)、数组越界异常(ArrayIndexOutOfBoundsException)

 

 注意:运行时异常指的是程序已经编译通过得到class文件了,再由JVM执行过程中出现的错误。

4、异常的处理 

1、处理异常的编程方式(防御式编程)

1、事前防御性(LBYL)

在操作之前做充分的检查。每一步操作都进行检查。

boolean ret = false;
ret = 登陆游戏();
if (!ret) {
    处理登陆游戏错误;
    return;
}
ret = 开始匹配();
if (!ret) {
    处理匹配错误;
    return;
}
ret = 游戏确认();
if (!ret) {
    处理游戏确认错误;
    return;
}
ret = 选择英雄();
if (!ret) {
    处理选择英雄错误;
    return;
}
ret = 载入游戏画面();
if (!ret) {
    处理载入游戏错误;
    return;
}

缺陷:正常流程和错误处理流程代码混在一起,代码整体显得比较混乱。 

2、事后认错行 (EAFP)

先操作,遇到问题再处理,在Java当中异常处理选择使用这种方式

try {
    登陆游戏();
    开始匹配();
    游戏确认();
    选择英雄();
    载入游戏画面();
    ...
} catch (登陆游戏异常) {
    处理登陆游戏异常;
} catch (开始匹配异常) {
    处理开始匹配异常;
} catch (游戏确认异常) {
    处理游戏确认异常;
} catch (选择英雄异常) {
    处理选择英雄异常;
} catch (载入游戏画面异常) {
    处理载入游戏画面异常;
}
    ......

 优势:正常流程和错误是分离开的,程序员更关注正常流程,代码更清晰,容易理解代码。

 在Java当中,异常处理主要的5个关键字:throw、try、catch、final、throws。

关键字功能
throw抛出异常
try将可能出现的异常代码放在try里
catch捕获异常
finallyfinally中的代码一定会被执行
throws声明异常

要处理异常首先得有异常,怎样才能有异常?代码在编译或者运行的时候,触发异常或者抛出异常 。

2、异常的抛出 

我们在编写程序的时候,大多数是编译器抛出异常,但是我们可不可以自己抛出异常。

答案是可以,在Java当中,我们可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知给调用者。

语法格式throw  new  XXXException("异常产生的原因"); 

1、这里抛出的是运行时异常的子类空指针异常 ,所以可以不用处理。

public class Test{
    public static void test1(int[] a){
        if(a == null){
            throw new NullPointerException("空指针异常");
            //根据自己的需求,抛出自己想要的异常
            //这个语法一般用在自己自定义的异常
        }
    }

    public static void main(String[] args) {
        test1(null);
    }
}

2、这里抛出的是编译时异常,用户必须自己处理,不然编译无法通过。

 

 如何解决,在下面的内容中。

❗❗❗【注意事项】

  • throw必须写在方法体内部
  • 抛出的对象必须是Exception或者Exception的子类对象
  • 如果抛出的是RunTimeException或者RunTimeException的子类,则可以不用处理,直接交给JVM来处理
  • 如果抛出的是编译时异常,用户必须处理,否则编译无法通过
  • 异常一旦出现,其后的代码就不会继续执行。

3、异常的捕获

异常的捕获,也就是异常的具体处理方式,只要有两种

异常声明throws
try - catch捕获处理

1、异常声明(关键字throws)

语法格式:

修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2....{
}
public static void test1(int[] a) throws CloneNotSupportedException{
}

如上述的编译时异常,CloneNotSupportedException异常如何解决,这里就说明第一种解决方式

声明过后的意思:大概就是站在test1方法的角度来说,我没有责任了 ,这个方法内部会抛出什么异常我已经告诉你了,就需要方法的调用者自己来解决了

 声明的作用:当方法中抛出编译时异常,编写该方法的用户不想处理该异常,此时就可以借助throws借助throws将异常抛给方法的调用者来处理,即当前方不处理异常,提醒方法的调用者处理异常。

那么,给main方法也进行声明

 可以看见,编译器没有报错,那么没有报错,就说明这个异常被解决了吗?在运行时就不会报错了吗?

可以看见,异常依旧存在 ,这里的处理异常,只不过是让代码在编译的时候不报错,但是代码的逻辑问题还是没有解决,这时候这个异常被交给了JVM进行处理,异常交给JVM处理,代码运行就会直接终止。

【注意事项】

  • throws必须跟在方法的参数列表之后
  • 声明的异常必须是Exception或者Exception的子类
  • 方法内部如果抛出多个异常,throws之后必须跟多个异常类型,之间用逗号隔开。
public class Test{
    public static void test1(int[] a) throws CloneNotSupportedException,
            NullPointerException,ArrayIndexOutOfBoundsException {
        if(a == null){
            throw new CloneNotSupportedException("");
        }
    }

当然,如果觉得上述的方法太麻烦,可以直接声明多个异常的父类异常,这样的写法虽然写的时候方便的,但是这样的代码可读性非常低,Exception异常有很多的子类,这样让方法的调用者,不知道调用的方法会抛出什么异常。

    public static void test1(int[] a) throws Exception{}
  • 调用声明会抛出异常的方法的时候,调用者必须对该异常进行处理,或者继续使用throws抛出。

【面试题】

throw和throws的区别
throw:用来抛出一个异常
throws:用来声明一个异常

2、try和catch关键字(捕获并处理异常)  

上面说到的throws,并没有对异常进行真正的处理,而是将异常声明了,方法的调用者需要对异常进行处理,这里就需要try - catch。

语法格式

try{
   //将可能出现异常的代码放在这里
}catch(要捕获的异常类型  e){
   //如果try中的代码抛出异常了,此时catch捕获时异常类型于try 中抛出的异常类型一致时,
   //或者时try中抛出异常的基类时,就会被捕获到
   //对异常就可以处理,处理完成之后,跳出try-catch结构,继续执行后序代码
}catch(要捕获的异常类型  e){
    //第一个catch没有捕获到异常,下一个catch捕获异常,捕获到了,对异常进行处理,
    //处理完成之后,跳出try-catch结构继续执行后序代码


   //后序代码
   // 当异常被捕获到时,异常就被处理了,这里的后序代码一定会执行
   // 如果捕获了,由于捕获时类型不对,那就没有捕获到,这里的代码就不会被执行

举例:

public class Test{
    public static void main(String[] args) {
        try{
            test1(null);
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
            System.out.println("捕捉到了 CloneNotSupperException 异常,进行处理异常的逻辑");
        }catch(NullPointerException e){
            e.printStackTrace();
            System.out.println("捕捉到了 NullPointerException 异常");
        }
        System.out.println("正常的逻辑......");
    }

}

 可以看出,当使用了try-catch 结构处理异常,可以将异常解决。

【注意事项】

  • 对于受查异常来说,当try当中没有抛出catch这个受查异常的时候,catch检测不到就会报错。

  •  运行异常(非受查异常)检测没有那么严格:try当中的代码抛出异常和catch检测的异常不相同,编译器在编译阶段并不会报错

  • 有的人想到将catch要检测的异常写成Exception,这样就可以一劳永逸了,什么异常都可以捕Exception放在第一个catch中,那么后续的catch都就没有作用了这样写没有错但是不推荐,这样写的代码可读性不高

  •  但是可以用Exception来兜底。将Exception放在最后的catch中。
  public static void main(String[] args) {
        try {
            //test1(null);
            int[] array = null;
            System.out.println(array.length);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
            System.out.println("捕捉到了 Exception 异常,进行处理异常的逻辑");
        } catch (NullPointerException e) {
            e.printStackTrace();
            System.out.println("捕捉到了 ArithmeticException 异常,进行处理异常的逻辑");
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("捕捉到了 ArithmeticException 异常,进行处理异常的逻辑");
        }
        System.out.println("正常的逻辑......");
    }
}
  • 当try当中存在多个异常的时候,从上往下执行,谁先抛出异常就捕获那个异常;catch当中程序的书写顺序,不影响异常的捕获。

  • 当try当中有多个异常时,在同一时间只会抛出一个异常,就上面图片中显示的一样。
  • 当try块内抛出异常的位置之后的代码不会被执行
  • 如果try当中抛出的异常,catch没有捕获到,那么就会交给JVM,将异常交给JVM之后就会被中端程序

❗❗补充:printStackTrace ()方法的意思是:在命令行打印异常信息在程序中出错的位置及原因。 

3、finally关键字 

在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库 连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能 导致有些语句执行不到finally就是用来解决这个问题的

语法格式:

try{
    // 可能会发生异常的代码
}catch(异常类型 e){
    // 对捕获到的异常进行处理
}finally{
    // 此处的语句无论是否发生异常,都会被执行到
}

//正常代码
// 如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行

finally当中的代码一定会被执行

 public static void main(String[] args) {
        try {
            int[] array = null;
            System.out.println(array.length);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
            System.out.println("捕捉到了 ArrayIndexOutOfBoundsException 异常,进行处理异常的逻辑");
        }catch(ArithmeticException e) {
            e.printStackTrace();
            System.out.println("捕捉到了 ArithmeticException 异常,进行处理异常的逻辑");
        }finally{
            System.out.println("finally 一般被用于资源的释放....");
        }
        System.out.println("正常的逻辑......");
    }
}

即使try当中抛出的异常没有被捕获处理,但是finally块内的代码还是会被运行

  • 当然你也可以尝试当try中抛出的异常被捕获并解决了之后,finally块内的代码会不会被执行。
  • 也可以尝试,当try当中的代码没有异常抛出,finally块内的代码会不会执行。

 finally被用来进行资源的释放

第一种写法

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try {
            int a = scanner.nextInt();
            int[] array ={1,2,3};
            System.out.println(array[1]);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
            System.out.println("捕捉到了 ArrayIndexOutOfBoundsException 异常,进行处理异常的逻辑");
        }finally{
            scanner.close();//关闭Scanner资源
            System.out.println("finally 一般被用于资源的释放....");
        }
        System.out.println("正常的逻辑......");
    }

第二种写法

public static void main(String[] args) {
       //写成这种格式,在finally中,就可以不用写scanner.close();
        try (Scanner scanner = new Scanner(System.in)) {
            int a = scanner.nextInt();
            int[] array ={1,2,3};
            System.out.println(array[1]);
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
            System.out.println("捕捉到了 ArrayIndexOutOfBoundsException 异常,进行处理异常的逻辑");
        }finally{
            System.out.println("finally 一般被用于资源的释放....");
        }
        System.out.println("正常的逻辑......");
    }

注意:finally中的代码一定会执行的,一般在finally中进行一些资源清理的扫尾工作。 

下面我们来看一道题

 这个代码你觉得输出的结果会是几?

  •  finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally). 但是如果 finally 中也存在 return 语句, 那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的 return.
  • 所以我们一般不建议finally中写return

4、异常的处理流程 

我们先来了解一个知识点:调用栈

方法之间是存在相互调用关系的,这种调用关系我们可以应用"调用栈"来描述,在JVM中有一块内存空间称为"虚拟机栈"专门存储方法之间的调用关系。

 

当func方法中存在异常的时候,没有解决,这个异常会随着调用栈的顺序,进入main方法,main方法中没有解决这个异常,那么这个异常就会交给JVM,那么程序就会直接终止掉。 

 

​​​​​​​【异常处理的流程】

  • 程序先执行 try 中的代码
  • 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配
  • 如果找到匹配的异常类型, 就会执行 catch 中的代码
  • 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者
  • 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
  • 如果上层调用者也没有处理的了异常, 就继续向上传递.
  • 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.

 5、自定义异常类

Java当中虽然已经内置了丰富的异常类,但是并没有完全包含实际开发中所遇到的一些异常,此时就需要我们自己定义一些异常类来供我们自己使用。

来看一个登录程序:

public class Test {
    public String name = "abcde";
    public String password = "12345678";
    public void login(String name,String password){
        if(!this.name.equals(name)){
            System.out.println("用户名错误");
            return;
        }
        if(!this.password.equals(password)){
            System.out.println("密码错误");
            return;
        }
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.login("wertd","23455");
    }
}

可以看到,当按上述代码格式来运行,当输入的密码于写死的密码不相同时,程序就会结束,但是在一个程序中,我们不能因为某个验证错误,让整个程序结束运行,我们是要程序是跑起来的,当遇到异常时,将异常抛出,但是程序还在运行。 

这里我们来写一个自定义的异常类,来解决这个问题

定义自定义的异常类

UserNameException类继承Exception类,表示受查异常/编译时异常 

 UserNameException类继承RuntimeException类,表示非受查异常/运行时异常

 下面通过自定义好的异常类,来修改上述的代码

来看两个自定义的异常类

public class UserNameException extends RuntimeException {
    public UserNameException(){
        super();
    }
    //写一个有参构造方法,可以在抛出异常的时候,编辑出现异常的原因
    public UserNameException(String s){
        super(s);
    }
}
public class PasswordException extends RuntimeException{
    public PasswordException(){
        super();
    }
    public PasswordException(String s){
        super(s);
    }
}

用户登录功能的代码

public class Test {
    public String name = "abcde";
    public String password = "12345678";
    public void login(String name,String password) throws UserNameException,PasswordException{
        if(!this.name.equals(name)){
            System.out.println("用户名错误");
            throw new UserNameException("你的用户名错了");//这里“”内的内容,是在运行期间编译器抛出异常后,用作提醒错误的原因
        }
        if(!this.password.equals(password)){
            System.out.println("密码错误");
            throw new PasswordException("你的密码错了");
        }
    }

    public static void main(String[] args) {
        Test test = new Test();
        try{
            test.login("wertd","23455");
        }catch(UserNameException e){
            e.printStackTrace();
            System.out.println("用户名异常");
        }catch(PasswordException e){
            e.printStackTrace();
            System.out.println("密码异常");
        }finally{

        }
    }
}

💥总结:

  • 自定义异常类,然后继承自Exception或者RuntimeException
  • 实现一个带有String类型参数的构造方法,参数含义:出现异常的原因
  • 自定义的异常类继承自Exception的异常默认是受查异常 / 编译时异常
  • 继承自RuntimeException的异常默认是非受查异常 / 运行时异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/163312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件测试】软件测试基础知识

1. 什么是软件测试 软件测试就是验证软件产品特性是否满足用户的需求 2. 调试与测试的区别 目的不同 调试:发现并解决软件中的缺陷测试:发现软件中的缺陷 参与角色不同 调试:开发人员测试:测试人员,开发人员等&a…

软件测试复习04:动态测试——黑盒测试

作者:非妃是公主 专栏:《软件测试》 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录等价划分法边值分析法错误推测法因果图法示例习题等价划分法 等价类:一个几何&#xf…

如何快速搭建自己的阿里云服务器(宝塔)并且部署springboot+vue项目(全网最全)

📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正! 文章目录📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!一、前言二、准备工作1、新手申请2、安全组设置3、修改实例4.这里可以 直接用阿里云…

【图像处理OpenCV(C++版)】——4.2 对比度增强之线性变换

前言: 😊😊😊欢迎来到本博客😊😊😊 🌟🌟🌟 本专栏主要结合OpenCV和C来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快…

【数据结构】5.7 哈夫曼树及其应用

文章目录前言5.7.1 哈夫曼树的基本概念哈夫曼树的特点5.7.2 哈夫曼树的构造算法哈夫曼树的构造过程哈夫曼算法的实现算法思路算法实现5.7.3 哈夫曼编码哈夫曼编码思想前缀编码哈夫曼编码哈夫曼编码的性质哈夫曼编码的算法实现文件的编码和解码前言 编程:将学生的百…

【精品】k8s(Kubernetes)由基础到实战学法指南

轻松快速学会k8s四招 图1 k8s四招 学完本篇,您会获得什么惊喜? 从初学k8s,到帮助别人学会的过程中,发现朋友们和我,并非不努力,而是没有掌握更好的方法。有方法可让我们学的更快更轻松,这篇文章,以一个networkpolicy的题目,来逐步讲解,帮助大家建立一种,自己可以根…

深入了解延迟队列 DelayQueue

1. 前言 前面我们了解了基于数组,链表实现的阻塞队列,以及优先级队列。今天我们来了解下基于优先级队列的延迟队列,而且今天的内容很核心哦。 大家快搬好小板凳做好,听我慢慢分析 2. 简单实例 Task 类 public class Task implem…

数据结构(字符串)

字符串简称串,由零个或多个字符组成的有限序列,一般记为s=“a0 a1a2…an-1”,(n≥0)。其中s称作串名,用双引号括起来的字符序列是串的值。字符ai(0≤i≤n-1)可以是字母、数字或其它字…

开发第三天(Day 03)

首先对ipl.nas进行修改: ; haribote-ipl ; TAB4ORG 0x7c00 ; 这个程序被读入哪里; 以下是标准FAT12格式软盘的描述JMP entryDB 0x90DB "HARIBOTE" ; 可以自由地写引导扇区的名字 (8字节)DW 512 ; 1扇区…

【动态内存管理】-关于动态内存你只知道四个函数是不够的,这里还有题目教你怎么正确使用函数,还不进来看看??

🎇作者:小树苗渴望变成参天大树 💦作者宣言:认真写好每一篇博客 💢 作者gitee:link 如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧! 🎊动态内存管理&…

adrp 命令为何能获取符号的地址

疑问所在 在linux 启动时,在如下位置会将bootloader 传入的x0 - x3 参数保存到boot_args[] 变量中。代码如下: /* …

神经网络基础部件-损失函数详解

一,损失函数概述 大多数深度学习算法都会涉及某种形式的优化,所谓优化指的是改变 xxx 以最小化或最大化某个函数 f(x)f(x)f(x) 的任务,我们通常以最小化 f(x)f(x)f(x) 指代大多数最优化问题。 在机器学习中,损失函数是代价函数的…

Spring Security 多过滤链的使用

一、背景 在我们实际的开发过程中,有些时候可能存在这么一些情况,某些api 比如: /api/** 这些是给App端使用的,数据的返回都是以JSON的格式返回,且这些API的认证方式都是使用的TOKEN进行认证。而除了 /api/** 这些API…

Qt扫盲-QTextEdit理论总结

QTextEdit理论总结一、概述二、用途一:富文本阅读器1. 用法2. 快捷键绑定三、用途二:编辑器1. 用法2. 拖拽3. 快捷键绑定四、常用功能五、信号一、概述 QTextEdit是一个先进的所见即所得的 富文本 查看器/编辑器,支持使用 html 风格的标签或…

【QT】.pro 文件

🌿作者:阿润菜菜 📖专栏:QT开发 .pro 文件是什么 .pro就是工程文件(project),它是qmake自动生成的用于生产makefile的配置文件。类似于VS中的.sln 和vsproj文件 默认情况下,每个 Qt 项目都包含一个后缀名为…

Huffman编码实现文件的压缩和解压缩

一个项目,不过处理起来也比较麻烦,配套可以和文件传输放一起 前提知识: 哈夫曼树和哈夫曼编码的概念和构建 1:n个数构成的哈夫曼树一共有2*n-1个结点>8 -> 15 2:数字越大的数离根节点越近,越小的数离…

无线耳机跑步会不会掉、最适合跑步用的耳机排名

现在,喜欢运动的人越来越多了。大家都有体会,多数运动是相对枯燥的,在运动时听听音乐,那是多么惬意的事情啊。为此,体验过多款耳机,但令我很满意的甚少。相信不少喜欢运动的朋友都有着跟我一样的烦恼吧&…

【Java基础知识3】Java注释:单行、多行、文档注释(如何通过 javadoc 命令生成代码文档、如何在IEDA配置自动为所有的类都添加创建者和创建日期)

本文已收录专栏 🌲《Java进阶之路》🌲 目录 本文已收录专栏 🌲《Java进阶之路》🌲 🍐01、单行注释 🍐02、多行注释 🍐03、文档注释 🍐04、文档注释的注意事项 🍐05、注释…

ceres学习笔记(二)

继续关于ceres官方doc里教程的学习,对于powells function的学习。 一、powells function 鲍威尔法,严格来说是鲍威尔共轭方向法,是迈克尔J.D.鲍威尔提出的一种求解函数局部最小值的算法。该函数不能是可微分的,并且不会导出衍生函…

spring用注解读取与获取对象

前言 上一篇博客简单的介绍了spring的功能与使用&#xff0c;可以看到我们创建一个对象&#xff0c;就需要在xml中存储一个bean对象&#xff0c;这种操作非常的繁琐&#xff0c;因此spring发明了使用注解来快捷存储bean对象 配置工作 我们在xml文件中写下面的代码片段 <…