Java基础(三):Java异常机制以及底层实现原理

🌷一、异常

☘️1.1 什么是异常

Java异常是程序发生错误的一种处理机制,异常的顶级类是ThrowableThrowable字面意思就是可抛出的,该类是所有的错误和异常的超类,只有Throwable类或者Throwable子类的实例对象才可以被Java虚拟机抛出,或者被Java语句抛出。

🍇Throwable有两个子类ErrorException

  • Error:表示错误,比如内存溢出。

  • Exception:表示异常,比如IO异常。

🍈Exception又分为运行时异常和非运行时异常

  • 运行时异常:也叫做非检查异常,在代码中抛出运行时异常时,Java编译器在编译时不会报错,只有在运行的时候才可能会抛出该异常,RuntimeException类和该类的子类都是运行时异常。

  • 非运行时异常:也叫做检查异常或者编译时异常,Java编译器在编译的时候如果发现程序抛出了检查异常,那么编译器就会报错,需要我们在代码中处理,要么捕获,要么继续抛出。没有继承RuntimeException的异常都是非运行时异常。

Error类及其子类,都是运行时异常

🌱1.2 代码示例

1.2.1 运行时异常

运行时异常,比如ArrayIndexOutOfBoundsExceptionNullPointerExceptionRuntimeException,当程序抛出运行时异常时,即使我们没有处理,编译器也不会报错,这种抛出不一定是显示的抛出,更多的是在运行时出现异常之后JVM自动的抛出。

public void runException () {throw new RuntimeException();
}

1.2.2 非运行时异常

非运行时异常,比如RuntimeExceptionNoSuchMethodException,当程序抛出了非运行时异常时,我们必须处理,否则编译器编译时就会报错。非运行时异常更多是提供给开发者用于对可能出现的异常情况进行处理。

public void nonRunException () {try {throw new FileNotFoundException();} catch (FileNotFoundException e) {e.printStackTrace();}
}

🌲1.3 异常处理方法

Java中异常处理方法有两种:继续抛出、捕获处理。

1.3.1 继续抛出

抛出异常有一个关键字:throwsthrows可以抛出多个异常,多个异常类用逗号分隔即可。

当方法中抛出异常之后,如果我们不对异常处理,可以在方法上使用throws抛出异常,这样就不需要方法处理异常,但是抛出异常的方法,需要调用者来处理异常。

1.3.2 捕获处理

异常的另外一种处理办法就是捕获处理,把异常在方法内部就处理掉,这样调用者调用方法时,不需要再处理异常。

捕获异常有几个关键字trycatchfinally

  • try:用于包裹异常的代码

  • catch:用于捕获异常之后的处理,可以有多个catch来捕获不同的异常,也可以用一个catch,不同的异常用符号|来分割

  • finally:无论如何都会执行的代码块

捕获异常有三种格式:

  • 第一种,用try捕获异常,然后在catch中处理。
try {
} catch () {
}
// 也可以有多个catch
try {
} catch () {
} catch () {
}
// 也可以在catch中直接捕获多个异常
try {
} catch (Exception1 | Exception2) { 
}
  • 第二种,用try捕获异常,在catch中处理异常,并且在finally中执行需要执行的代码
try {
} catch () {
} finally {
}
  • 第三种,捕获异常之后不处理,但是要在finally中执行需要执行的代码
try {
} finally {
}

🥬1.4 try-with-resources

try-with-reourcesJDK1.7出来的新语法,这个语法有两个目的:主要是自动关闭资源,为了减少对finally的依赖,同时使得代码变得简洁一些、同时还可以传递被抑制的异常。

1.4.1 自动关闭资源

我们先说第一个,我们先看一下如果用传统的try-catch是怎么使用的。

如果我们用try-catch-finally来关闭异常,可以发现关闭资源的代码比业务代码还要多,看起来也不是很简洁。

public static void main(String[] args) {FileInputStream fileInputStream = null;try {fileInputStream = new FileInputStream("");} catch (FileNotFoundException e) {e.printStackTrace();} finally {try {if (fileInputStream != null) {fileInputStream.close();}} catch (IOException e) {e.printStackTrace();}}
}

现在我们用try-with-resource来改写这个,把需要关闭资源的放到try的括号里面,这样发生了异常会自动关闭。

public static void main(String[] args)  {try(FileInputStream fileInputStream = new FileInputStream("")) {int result = fileInputStream.read();} catch (IOException e) {e.printStackTrace();}
}

那么try-with-resource是怎么实现自动关闭,我们反编译一下字节码,可以看到本质上还是用的try-catch来实现的,只不过是在try里面调用了close

public static void main(String[] args) {
try {FileInputStream fileInputStream = new FileInputStream("file.txt");Object var2 = null;if (fileInputStream != null) {if (var2 != null) {try {fileInputStream.close();} catch (Throwable var4) {((Throwable)var2).addSuppressed(var4);}} else {fileInputStream.close();}}
} catch (IOException var5) {IOException e = var5;e.printStackTrace();
}

1.4.2 传递抑制的异常

如果tryfinally都发生了异常,并且抛出那么finally中的异常就会覆盖try中的异常。

我们在一个方法里面先抛出一个FileNotFoundException异常,然后再finally里面关闭这个流的时候又会出现NullPointerException异常,在main方法进行捕获之后可以发现最后只打印了NullPointerException异常,而FileNotFoundException并没有打印出来。

public static void main(String[] args) {try {c();} catch (Exception e) {e.printStackTrace();}
}public static void c () throws IOException {FileInputStream fileInputStream = null;try {fileInputStream = new FileInputStream("");} catch (FileNotFoundException e) {throw e;} finally {try {fileInputStream.close();} catch (IOException e) {throw e;}}
}

打印出来的异常信息

java.lang.NullPointerExceptionat com.lee.study.exception.Demo.c(Demo.java:26)at com.lee.study.exception.Demo.main(Demo.java:12)

我们再用try-with-resources改写一下,这里我们需要构造一个自定义的类,实现在关闭的时候也抛出异常。

public static void main(String[] args) {try (MyAutoCloseable myAutoCloseable = new MyAutoCloseable();) {myAutoCloseable.read();}catch (Exception e) {e.printStackTrace();}}
}
// 实现了AutoCloseable接口可以自动的调用close方法
class MyAutoCloseable implements AutoCloseable {public void read() throws Exception {throw new Exception("read");
}@Override
public void close() throws Exception {throw new Exception("close");
}

打印出来的异常信息

java.lang.Exception: readat com.lee.study.exception.MyAutoCloseable.read(Demo.java:22)at com.lee.study.exception.Demo.main(Demo.java:12)Suppressed: java.lang.Exception: closeat com.lee.study.exception.MyAutoCloseable.close(Demo.java:27)at com.lee.study.exception.Demo.main(Demo.java:13)

我们看下反编译代码,可以看到在finally中关闭的时候调用了一个方法addSuppressed,这个方法就是用来把这些抑制的异常都记录下来。

public static void main(String[] args) {try {MyAutoCloseable myAutoCloseable = new MyAutoCloseable();Throwable var2 = null;try {myAutoCloseable.read();} catch (Throwable var12) {var2 = var12;throw var12;} finally {if (myAutoCloseable != null) {if (var2 != null) {try {myAutoCloseable.close();} catch (Throwable var11) {var2.addSuppressed(var11);}} else {myAutoCloseable.close();}}}} catch (Exception var14) {Exception e = var14;e.printStackTrace();}}

🌳1.5 自定义异常

除了Java中提供的异常之外,我们也可以自定义一些异常,自定义异常可以自定义运行时异常和非运行时异常两种方式。

1.5.1 自定义运行时异常

自定义运行时异常之需要继承RuntimeException这个方法即可,这里我们加了一个构造方法,这样可以创建异常对象时加一些描述异常信息。

public class DemoRuntimeException extends RuntimeException{public DemoRuntimeException (String message) {super(message);}
}

1.5.2 自定义非运行时异常

自定义非运行时异常只需要继承Exception,这里也是加了一个构造方法,描述异常信息。

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

🌸二、源码分析

🌴2.1 变量

// 用来保存栈信息的轨迹
private transient Object backtrace;// 记录描述异常信息
private String detailMessage;// 描述这个异常是哪个Throwable导致的,默认是当前Throwable
private Throwable cause = this;// 记录异常抛出位置的栈信息,每个StackTraceElement代表一个栈
private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];
private StackTraceElement[] stackTrace = UNASSIGNED_STACK;//用来保存被屏蔽的异常对象,如果在finally中抛出了异常,就会覆盖try中的异常,这个是JDK 1.7引入的新特性
private static final List<Throwable> SUPPRESSED_SENTINEL =Collections.unmodifiableList(new ArrayList<Throwable>(0));
private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;

🌵2.2 构造方法

/*** 无参构造方法,只调用了fillInStackTrace方法*/
public Throwable() {fillInStackTrace();
}/*** @param message 描述异常的信息,打印异常信息会一并打印*/
public Throwable(String message) {fillInStackTrace();detailMessage = message;
}/*** @param message 描述异常的信息,打印异常信息会一并打印* @param cause 当前异常是哪个Throwable导致的*/
public Throwable(String message, Throwable cause) {fillInStackTrace();detailMessage = message;this.cause = cause;
}/*** @param cause 当前异常是哪个Throwable导致的*/
public Throwable(Throwable cause) {fillInStackTrace();detailMessage = (cause==null ? null : cause.toString());this.cause = cause;
}/*** @param message 描述异常的信息,打印异常信息会一并打印* @param cause 当前异常是哪个Throwable导致的* @param enableSuppression 是否开启记录被屏蔽的对象* @param writableStackTrace 是否开启记录异常栈信息*/
protected Throwable(String message, Throwable cause,boolean enableSuppression,boolean writableStackTrace) {if (writableStackTrace) {fillInStackTrace();} else {stackTrace = null;}detailMessage = message;this.cause = cause;if (!enableSuppression)suppressedExceptions = null;
}

🌾2.3 fillInStackTrace

2.3.1 方法描述

在构造方法中都会先调用一下这个fillInStackTrace方法,这个方法主要是获取栈信息,并且对保存栈信息数组进行清空。

首先会判断当前保存栈信息数组stackTrace和栈信息轨迹backtrace是否为空,如果不为空的话调用nativefillInStackTrace获取栈信息,然后把保存栈信息数组stackTrace清空。

当创建Throwable传入的参数writableStackTracefalsestackTrace就会为空,这样就不会开启异常栈信息的记录。如果你不需要记录栈信息,在自定义异常时可以重新这个方法,直接返回this

public synchronized Throwable fillInStackTrace() {if (stackTrace != null || backtrace != null) {fillInStackTrace(0);stackTrace = UNASSIGNED_STACK;}return this;
}private native Throwable fillInStackTrace(int dummy);

2.3.2 代码示例

先看一个例子,在main方法中调用a,并且捕获异常,打印异常信息,在a调用b,并捕获异常,打印异常信息。

public class Demo {public static void main(String[] args) {try {a ();} catch (Exception e) {e.printStackTrace();}}public static void a () throws Exception {try {c();} catch (Exception e) {e.printStackTrace();throw e;}}public static void c () throws Exception {throw new Exception("报错了");}
}

把异常信息打印出来,发现两次打印的是一样的,也就是捕获到异常又抛出,异常的栈轨迹是一样的。

java.lang.Exception: 报错了at com.lee.study.exception.Demo.c(Demo.java:25)at com.lee.study.exception.Demo.a(Demo.java:17)at com.lee.study.exception.Demo.main(Demo.java:9)
java.lang.Exception: 报错了at com.lee.study.exception.Demo.c(Demo.java:25)at com.lee.study.exception.Demo.a(Demo.java:17)at com.lee.study.exception.Demo.main(Demo.java:9)

我们将代码修改一下,在catch里面调用一下fillInStackTrace方法

public class Demo {public static void main(String[] args) {try {a ();} catch (Exception e) {e.printStackTrace();}}public static void a () throws Exception {try {c();} catch (Exception e) {e.printStackTrace();// 调用一下fillInStackTracee.fillInStackTrace();throw e;}}public static void c () throws Exception {throw new Exception("报错了");}
}

再看一下打印的栈轨迹信息,第二次打印的时候已经没有调用b的轨迹了。其实调用这个方法,相当于是把异常栈的数组给清空了。

java.lang.Exception: 报错了at com.lee.study.exception.Demo.c(Demo.java:27)at com.lee.study.exception.Demo.a(Demo.java:17)at com.lee.study.exception.Demo.main(Demo.java:9)
java.lang.Exception: 报错了at com.lee.study.exception.Demo.a(Demo.java:21)at com.lee.study.exception.Demo.main(Demo.java:9)

2.3.3 爬栈

有时候我们不需要记录异常栈轨迹信息,有两种方法实现,第一个是在创建ThrowablewritableStackTrace设置为false,第二个是我们可以重写fillInStackTrace方法,直接返回this

定义一个异常,并且调用打印异常信息

public class DemoNonRuntimeException extends Exception{public DemoNonRuntimeException (String message) {super(message);}
}
public class Demo {public static void main(String[] args) {try {c ();} catch (DemoNonRuntimeException e) {e.printStackTrace();}}public static void c () throws DemoNonRuntimeException {throw new DemoNonRuntimeException("报错了");}
}

打印的异常信息

com.lee.study.exception.DemoNonRuntimeException: 报错了at com.lee.study.exception.Demo.c(Demo.java:17)at com.lee.study.exception.Demo.main(Demo.java:9)

如果我们重写fillInStackTrace方法

public class DemoNonRuntimeException extends Exception{public DemoNonRuntimeException (String message) {super(message);}public Throwable fillInStackTrace () {return this;}
}public class Demo {public static void main(String[] args) {try {c ();} catch (DemoNonRuntimeException e) {e.printStackTrace();}}public static void c () throws DemoNonRuntimeException {throw new DemoNonRuntimeException("报错了");}
}

再打印异常信息,就会发现已经没有栈轨迹信息了。

com.lee.study.exception.DemoNonRuntimeException: 报错了

🌿2.4 printStackTrace

这个方法是用来打印异常栈信息的方法,我们对这个方法应该是最熟悉的。

private void printStackTrace(PrintStreamOrWriter s) {Set<Throwable> dejaVu =Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());dejaVu.add(this);synchronized (s.lock()) {s.println(this);StackTraceElement[] trace = getOurStackTrace();for (StackTraceElement traceElement : trace)s.println("\tat " + traceElement);for (Throwable se : getSuppressed())se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);Throwable ourCause = getCause();if (ourCause != null)ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);}
}

🍀2.5 getMessage

用于获取异常描述信息

public String getMessage() {return detailMessage;
}

🌹三、JVM处理异常原理

这里我们从字节码的角度来分析一下异常的实现原理,主要是try-catch的实现原理,因为throws时不处理异常的,只是继续抛出。

这里我们以三个例子来说明异常处理的原理:

🥇try-catch

🥈try-catch-finally

🥉try-catch-finally,并在finallyreturn

🍁3.1 分析前准备

3.1.1 安装字节码分析工具

因为需要字节码分析异常处理的原理,首先我们需要在idea中安装字节码工具:jclasslib插件。

安装好之后,我们找到需要分析的编译后的class文件,然后选择导航栏的View-Show Bytecode With Jclasslib查看字节码文件。

在这里插入图片描述

3.1.2 异常表

Java中,如果一个方法有try-catch处理,在被编译成字节码都会生成一个异常表,异常表是一个表格,每一个都代表一个异常处理。

在这里插入图片描述

🥇起始PC:代表这个异常处理器监控的字节码开始位置。

🥈结束PC:代表这个异常处理器监控的字节码结束位置(不包括最后一行)。

🥉跳转PC:代表监控范围内如果发生了异常,跳转到该行字节码去执行。

🍂3.2 try-catch

3.2.1 示例代码

public class Demo {public static void main(String[] args) throws Exception {invoke(0, 1);}public static void invoke (int a, int b) throws Exception {try {if (b == 0) {throw new ArithmeticException();}int c = a / b;} catch (ArithmeticException e) {throw new Exception();}}
}

3.2.2 字节码

 0 iload_11 ifne 12 (+11)4 new #3 <java/lang/ArithmeticException>7 dup8 invokespecial #4 <java/lang/ArithmeticException.<init>>
11 athrow
12 iload_0
13 iload_1
14 idiv
15 istore_2
16 goto 28 (+12)
19 astore_2
20 new #5 <java/lang/Exception>
23 dup
24 invokespecial #6 <java/lang/Exception.<init>>
27 athrow
28 return

3.2.3 异常表

在这里插入图片描述

3.2.4 分析

  1. 在字节码11行athrow抛出了异常ArithmeticException

  2. JVM会去异常表中找,是否有ArithmeticException的异常处理器。

  3. 在异常表中有ArithmeticException的处理器,跳转到19行继续执行。

  4. 在27行又抛出了一个异常Exception

  5. JVM会继续在异常表中找,是否有Exception的异常处理器。

  6. 这里没有Exception的处理器,会返回到方法的调用者继续执行上述流程,如果还是没找到就结束线程。

🍃3.3 try-catch-finally

3.3.1 示例代码

public class Demo {public static void main(String[] args) throws Exception {invoke(0, 1);}public static void invoke (int a, int b) throws Exception {try {if (b == 0) {throw new ArithmeticException();}int c = a / b;} catch (ArithmeticException e) {throw new Exception();} finally {System.out.println("执行方法");}}
}

3.3.2 字节码

 0 iload_11 ifne 12 (+11)4 new #3 <java/lang/ArithmeticException>7 dup8 invokespecial #4 <java/lang/ArithmeticException.<init>>
11 athrow
12 iload_0
13 iload_1
14 idiv
15 istore_2
16 getstatic #5 <java/lang/System.out>
19 ldc #6 <执行方法>
21 invokevirtual #7 <java/io/PrintStream.println>
24 goto 47 (+23)
27 astore_2
28 new #8 <java/lang/Exception>
31 dup
32 invokespecial #9 <java/lang/Exception.<init>>
35 athrow
36 astore_3
37 getstatic #5 <java/lang/System.out>
40 ldc #6 <执行方法>
42 invokevirtual #7 <java/io/PrintStream.println>
45 aload_3
46 athrow
47 return

3.3.3 异常表

在这里插入图片描述

3.3.4 分析

  1. 增加了finally之后,在异常表中多了两个异常处理器,并且都是any的,表示任何异常都可以捕获。

  2. 这两个异常处理器最终都跳转到36行执行

3.3.5 为什么finally一定会执行

分两种情况如果代码执行中发生了异常和没有发生异常

  • 发生了异常

    无论时在try还是在catch中,第二个和第三个异常处理器都会捕获到,都会跳转到36行继续执行也就是finally中的内容

  • 没有发生异常

    在编译的时候会把finally的字节码拷贝到try里面代码块的后面,这样也会执行,所以为什么字节码里面有两处finally的内容

🍄3.4 try-finally-return

3.4.1 示例代码

public class Demo {public static void main(String[] args) {invoke();}public static int invoke () {int a = 1;try {a = 2;return a;} finally {a = 3;return a;}}
}

3.4.2 字节码

从字节码分析中分析,当finally中有return之后,会将try里面的覆盖掉,在6-9就是return的内容,而try里面的return已经不见了。

 0 iconst_1 // 将1放入操作数栈1 istore_0 // 将1存储到局部变量表第一个位置2 iconst_2 // 将2放入操作数栈3 istore_0 // 将2存储到局部变量表第一个位置4 iload_0  // 加载局部变量表第一个位置元素放入操作数栈5 istore_1 // 将2存储到局部变量表第二个位置6 iconst_3 // 将3放入操作数栈7 istore_0 // 将3存储到局部变量表第一个位置8 iload_0 // 加载局部变量表第一个位置元素放入操作数栈9 ireturn // 返回
10 astore_2  
11 iconst_3 // 将3放入操作数栈
12 istore_0 // 将3存储到局部变量表第一个位置
13 iload_0 // 加载局部变量表第一个位置元素放入操作数栈
14 ireturn // 返回

🪴3.5 finally赋值

3.5.1 示例代码

public class Demo {public static void main(String[] args) {invoke();}public static int invoke () {int a = 1;try {a = 2;return a;} finally {a = 3;}}
}

3.5.2 字节码

 0 iconst_1 // 将1放入操作数栈1 istore_0 // 将1存储到局部变量表第一个位置2 iconst_2 // 将2放入操作数栈3 istore_0 // 将2存储到局部变量表第一个位置4 iload_0 // 从局部变量表中加载第一个位置元素放入操作数栈5 istore_1 // 将2存储到局部变量表第二个位置6 iconst_3 // 将3放入操作数栈7 istore_0 // 将3存储到局部变量表第一个位置8 iload_1 // 从局部变量表中夹在第二哥位置元素放入操作数栈,也就是29 ireturn //返回
10 astore_2
11 iconst_3
12 istore_0
13 aload_2
14 athrow

3.5.3 分析

这里在finally中对a进行赋值,但是在try中返回,最后返回的值是2还是3?

这里返回的是2,虽然finally里面的内容一定会执行,但是从字节码中可以得知,在返回的时候是将局部变量表第二个位置的元素返回的,而3是存储在局部变量表第一个位置。

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

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

相关文章

缓存菜品操作

一&#xff1a;问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大。 二&#xff1a;实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; 每个分…

ACWing-186巴士-DFS

题目 原题链接&#xff1a;186. 巴士 - AcWing题库 oj:xmuoj | 最小化蒙德城的旅行者队伍 思路 本题因为n300&#xff0c;说明搜索深度很深&#xff0c;但是测试数量小于17&#xff0c;所以答案一定在比较浅的一个搜索深度中&#xff0c;于是可以利用迭代加深的处理方法迭代…

基于Springboot+Vue的Java项目-旅游网站系统开发实战(附演示视频+源码+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &am…

OpenNJet如何做到让用户永远在线

前言 最近看到了国内开源的一个名为OpenNJet的项目&#xff0c;有一个响亮的口号&#xff1a;“下一代云原生应用引擎”。 一下子就被吸引到了。 先看下官方对OpenNJet的介绍&#xff1a; OpenNJet 应用引擎是基于 NGINX 的面向互联网和云原生应用提供的运行时组态服务程序&…

红黑树(RBTree)认识总结

一、认识红黑树 1.1 什么是红黑树&#xff1f; 红黑树是一种二叉搜索树&#xff0c;与普通搜索树不同的是&#xff0c;在每个节点上增加一个“颜色”变量 —— RED / BLACK 。 通过对各个节点颜色的限制&#xff0c;确保从 根 到 NIL &#xff0c;没有一条路径会比其他路径长出…

借势母亲节h5小游戏的作用是什么

企业商家往往喜欢借势节日开展营销&#xff0c;母亲节作为5月的重要节日自然不可错过&#xff0c;不同行业商家都有自己开展互动想要实现的效果&#xff0c;如品牌宣传曝光、引流及渠道跳转等。 基于微信社交属性&#xff0c;有利于品牌发展&#xff0c;在【雨科】平台拥有多款…

基于web的物流管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

Backpropagation反向传播算法【总结】

概念介绍 Backpropagation本质上就是一个提升Gradient Descent效率的算法&#xff0c;核心在于其可以有效率地计算出一个偏移量来update下一组未知参数。 难点在于&#xff1a;Neural Network有很多层&#xff0c;而且每层参数都非常多&#xff0c;所以不能立即算出来该组未知…

【Linux网络编程】高级IO——五种IO模型

高级IO 1.什么是IO&#xff1f;什么是高效的IO&#xff1f;2.有那些IO的方式&#xff1f;这么多的方式&#xff0c;有那些是高效的&#xff1f;3.五种IO模型4.高级IO重要概念5.非阻塞IO 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x…

C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

信息泄露中的目录遍历,phpinfo,备份文件下载

一、目录遍历漏洞 1.什么是目录遍历漏洞 指的是在没有授权的情况下读取文件&#xff0c;某些情况下还可对服务器里的文件任意写入 2.目录遍历漏洞成因 网站配置存在缺陷&#xff0c;对输入目录缺少验证&#xff0c;没过滤../之类的目录跳转符&#xff0c;可通过提交目录跳转…

超详细——集成学习——Adaboost——笔记

资料参考 1.【集成学习】boosting与bagging_哔哩哔哩_bilibili 集成学习——boosting与bagging 强学习器&#xff1a;效果好&#xff0c;模型复杂 弱学习器&#xff1a;效果不是很好&#xff0c;模型简单 优点 集成学习通过将多个学习器进行结合&#xff0c;常可获得比单一…

AI绘画ComfyUI工作流安装教程,新手入门安装部署教程

ComfyUI 是专为 Stable Diffusion 打造的图形用户界面&#xff08;GUI&#xff09;&#xff0c;采用了基于节点的操作方式。用户可以通过连接不同的模块&#xff08;即节点&#xff09;来创建复杂的图像生成流程。这些节点涵盖了多样的功能&#xff0c;包括加载检查点模型、输入…

慧天卓特干旱监测系统:2023年云南最强冬春连旱分析

2023年开春以来&#xff0c;由于高温少雨&#xff0c;土壤失墒快&#xff0c;我国西南的云贵川渝等地区出现连续快速干旱&#xff0c;云南地区的干旱尤为严重。 2023年1月下旬至6月18日&#xff0c;云南平均降水量197.7毫米&#xff0c;为1961年以来历史同期最少&#xff0c;气…

生成requirements.txt文件

前言 对于Python项目&#xff0c;生成和使用requirements.txt是十分必要的。通过requirements.txt可以一次性保存和安装项目所需要的所有库。尤其是在复现github上的实验代码时。 方法1 常用的命令 pip freeze > requirements.txt然而这种方法并不好用&#xff0c;有时会…

什么是泛域名证书?与普通SSL证书有什么区别

随着互联网的发展&#xff0c;越来越多的网站开始使用SSL证书来保护用户的隐私和安全。在SSL证书中&#xff0c;泛域名SSL证书和普通域名证书是两种常见的类型。那么&#xff0c;什么是泛域名SSL证书&#xff0c;与普通域名证书有什么区别呢&#xff1f; 首先&#xff0c;我们来…

ChatGPT变懒原因:正在给自己放寒假!已被网友测出

ChatGPT近期偷懒严重&#xff0c;有了一种听起来很离谱的解释&#xff1a; 模仿人类&#xff0c;自己给自己放寒假了&#xff5e; 有测试为证&#xff0c;网友Rob Lynch用GPT-4 turbo API设置了两个系统提示&#xff1a; 一个告诉它现在是5月&#xff0c;另一个告诉它现在是1…

基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 遗传算法&#xff08;GA&#xff09;原理 4.2 BP神经网络原理 4.3 遗传优化BP神经网络结合应用 4.4 遗传算法简要改进 5.完整程序 1.程序功能描述 基于改进遗传优化的BP神经网络金融…

什么是影响力?HR招聘测评,如何考察候选人的影响力?

什么是影响力&#xff1f; 影响力也即是说服别人同你的观点&#xff0c;或者是潜移默化的改变他人&#xff0c;从而形成自我凝聚力&#xff0c;影响力可以推动某一个事务的进行。影响力尤其在管理型岗位上具有重要作用。 在百科中有如下定义&#xff1a;影响力是用别人乐于接受…

Python类方法探秘:从单例模式到版本控制

引言&#xff1a; 在Python编程中&#xff0c;类方法作为一种特殊的实例方法&#xff0c;以其独特的魅力在众多编程范式中脱颖而出。它们不仅提供了无需实例即可调用的便捷性&#xff0c;还在设计模式、版本控制等方面发挥着重要作用。本文将通过几个生动的示例&#xff0c;带您…