初识Java 13-2 异常

目录

标准Java异常

新特性:更好的NullPointerException报告机制

使用finally执行清理

finally有什么用

在return时使用finally

缺陷:异常丢失

异常的约束

构造器


本笔记参考自: 《On Java 中文版》


标准Java异常

        Throwable类描述了任何可能抛出异常的事物,它有两个常用的子类:

  • Error:表示编译时错误和系统错误。
  • Exception:是一个基本类型,可从任何标准的Java库方法、自定义方法及运行事故中抛出。

        很显然,作为Java程序员,我们会更加关心Exception

        对异常的理解和处理是较为重要的部分(与了解各种异常相比)。基本的思路是,异常的名字代表着所发生的问题。因此,异常的名字应该是浅显易懂的。

    异常并不全部来自java.lang。有些异常是为不同的库设计的,这一点可以从他们的全限定类名或基类看出。

特例:RuntimeException(非检查型异常)

        有这么一组异常,它们总是会被Java自动抛出,而不需要程序员将它们包含在任何异常说明之中。这种异常都被放在了RuntimeException这一基类之下。

    这就是一个继承的完美示例。

||| RuntimeException:表示编程错误,它包括:

  • 无法预料的错误,比如在我们控制之外的null引用。
  • 作为程序员,应该在代码中检查的错误(例如ArrayIndexOutOfBoundsException,这表示我们的数组大小可能出现问题)。

        注意:在一个地方发现的异常,往往也可能成为另一个地方的问题。

        正如之前所说,RuntimeException及其子类不需要异常说明,这类异常也被称为“非检查型异常(它们指出的是bug。若必须检查,代码会变得十分复杂)。不过,尽管我们一般不会捕捉RuntimeException,但我们可以有选择地抛出一个RuntimeException

        若不捕捉这类异常,RuntimeException就可能逐层返回,知道到达main()方法:

【例子:若不捕捉RuntimeException

public class NeverCaught {static void f() {throw new RuntimeException("来自f()");}static void g() {f();}public static void main(String[] args) {g();}
}

        程序执行的结果是:

        若一个RuntimeException没有被捕获,关于这个异常的printStackTrace()会在程序结束时被调用。这就体现出了RuntimeException(及其子类)的特殊性,这类异常不会被要求写入异常说明,它们的输出将被报告给System.err

    只有RuntimeException(及其子类)类型的异常可被忽略,编译器会强制实施对所有检查型异常的处理。

新特性:更好的NullPointerException报告机制

        在JDK 15之前,NullPointerException能够报告的信息并不多。

【例子:NullPointerException的报错】

package exceptions;class A {String s;A(String s) {this.s = s;}
}class B {A a;B(A a) {this.a = a;}
}class C {B b;C(B b) {this.b = b;}
}public class BetterNullPointerReports {public static void main(String[] args) {C[] ca = {new C(new B(new A(null))),new C(new B(null)),new C(null),};for (C c : ca) {try {System.out.println(c.b.a.s);} catch (NullPointerException npe) {System.out.println(npe);}}}
}

        若是在JDK 11的环境中运行,会得到如下的结果:

        但若是在JDK 15或更高版本中运行,则会显示:

更多的信息有助于我们理解和处理这些异常。

使用finally执行清理

        我们可能会需要手动进行一些清理操作,这种操作通常是内存恢复之外的动作,因为内存会由垃圾收集器处理。在这种情况下,我们可能会希望:无论try块是否抛出异常,都会有一段代码必须执行。

        为此,可以在所有的异常处理程序的末尾添加一个finally子句:

try {// 被守护区域
} catch(A a1) {// 情况A的处理程序
} catch(B b1) {// 情况B的处理程序
} finally {// 不管哪种情况都会执行的活动
}

【例子:添加了finally的异常处理】

class ThreeException extends Exception {
}public class FinallyWorks {static int count = 0;public static void main(String[] args) {while (true) {try {if (count++ == 0) // 使用后缀++,第一次的结果就是0throw new ThreeException();System.out.println("没有异常");} catch (ThreeException e) {System.out.println("ThreeException");} finally {System.out.println("在finally子句中");if (count == 2) // 跳出循环break;}}}
}

        程序执行的结果是:

        有输出可知,无论是否抛出异常,finally子句都会执行。并且,Java中的异常不会允许我们回退到异常抛出的地方。

finally有什么用

        若语言没有垃圾收集,并且不会自动调用析构函数,那么finally就需要确保内存的释放。但Java并不需要这一功能。对Java而言,finally主要用于清理内存之外的某些东西。

        为了演示finally的作用,首先创建一个需要使用的组件:

public class PnOffSwitch {private static Switch sw = new Switch();public static void f()throws OnOffException1, OnOffException2 {}public static void main(String[] args) {try {sw.on();// 可能抛出异常的代码...f();sw.off();} catch (OnOffException1 e) {System.out.println("OnOffException1");sw.off();} catch (OnOffException2 e) {System.out.println("OnOffException1");sw.off();}}
}

        两个需要使用的异常:

        若不使用finally,一般情况下我们会这样进行异常处理:

public class OnOffSwitch {private static Switch sw = new Switch();public static void f()throws OnOffException1, OnOffException2 {}public static void main(String[] args) {try {sw.on();// 可能抛出异常的代码...f();sw.off();} catch (OnOffException1 e) {System.out.println("OnOffException1");sw.off();} catch (OnOffException2 e) {System.out.println("OnOffException1");sw.off();}}
}

        当程序结束时,我们要求sw处于关闭状态。因此每个catch子句的末尾都添加了sw.off()。但程序还有可能抛出某个没有在这里被捕获的异常,这种情况会导致sw.off()被忽略。因此finally就有了用武之地,可以把try块中的清理工作都放在这里:

【例子:finally的清理】

public class WithFinally {static Switch sw = new Switch();public static void main(String[] args) {try {sw.on();// 可能抛出异常的代码...OnOffSwitch.f();} catch (OnOffException1 e) {System.out.println("OnOffException1");} catch (OnOffException2 e) {System.out.println("OnOffException2");} finally {sw.off(); // 无论何种情况都会执行}}
}

        即使抛出的异常没有在当前这组catch子句中捕获,在异常处理机制向更高一层进行搜索之前,finally也会执行。

【例子:总是执行的finally

class FourException extends Exception {
}public class AlwaysFinally {public static void main(String[] args) {System.out.println("进入第一个try块");try {System.out.println("进入第二个try块");try {throw new FourException();} finally {System.out.println("finally在第二个try块中执行");}} catch (FourException e) {System.out.println("在第一个try块的处理程序中捕获异常FourException");} finally {System.out.println("finally在第一个try块中执行");}}
}

        程序执行的结果是:

    涉及breakcontinue语句时,finally也会执行。


return时使用finally

        利用finally子句总会执行的特性,我们可以在一个多返回的方法中保证重要的清理工作能够完成:

【例子:在多返回的方法中使用finally

public class MultipleReturns {public static void f(int i) {System.out.println("初始化后执行清理");try {System.out.println("Point 1");if (i == 1)return;System.out.println("Point 2");if (i == 2)return;System.out.println("Point 3");if (i == 3)return;System.out.println("结束");return;} finally {System.out.println("执行清理");}}public static void main(String[] args) {for (int i = 1; i <= 4; i++){f(i);System.out.println();}}
}

        程序执行的结果是:


缺陷:异常丢失

        在一些特殊的finally子句的使用中,可能发生异常丢失的情况:

【例子:特殊子句中的异常丢失】

class VeryImportantException extends Exception {@Overridepublic String toString() {return "这是一个很重要的异常,它不应该被忽略";}
}class HoHumException extends Exception {@Overridepublic String toString() {return "一个不重要的异常";}
}public class LostMessage {void f() throws VeryImportantException {throw new VeryImportantException();}void dispose() throws HoHumException {throw new HoHumException();}public static void main(String[] args) {try {LostMessage lm = new LostMessage();try {lm.f();} finally {lm.dispose();}} catch (VeryImportantException |HoHumException e) {System.out.println(e);}}
}

        程序执行的结果是:

        原本应该被捕获的VeryImportantExceptionfinally子句中的HoHumException取代了。这是十分严重的问题,因为它意味着一个异常可能会完全丢失(并且难以察觉)。

    C++会将在第一个异常处理前抛出第二个异常视为严重的编程错误。

        目前Java还未修复这一问题。为了处理这一麻烦,我们需要将任何可能抛出异常的方法(就是上面的dispose)包在另一个try-catch子句中。

        还有一种会丢失异常的方式,就是在finally子句中执行return

【例子:另一种异常丢失】

public class ExceptionSilencer {public static void main(String[] args) {try {throw new RuntimeException();}finally {return; // 在finally中使用return,会阻止任何的异常报错}}
}

        若运行程序,会发现并无任何报错

异常的约束

        存在着这样一个约束:在重写一个方法时,只能抛出 ①该方法的基类版本中说明的异常,或者是 ②以原有异常为基类派生而出的异常。

    这一约束指向一个概念:能够配合基类工作的代码,可以自动配合从这个基类派生出的其他类的对象进行工作,异常也不会例外。

【例子:异常的各种约束】

class BaseballException extends Exception {
}class Foul extends BaseballException {
}class Strike extends BaseballException {
}abstract class Inning {Inning() throws BaseballException {}public void event() throws BaseballException {}public abstract void atBat() throws Strike, Foul;public void walk() { // 该方法没有抛出检查型异常}
}class StormException extends Exception {
}class RainedOut extends StormException {
}class PopFoul extends Foul {
}interface Storm {void event() throws RainedOut;void rainHard() throws RainedOut;
}public class StormyInning extends Inning implements Storm {// 子类构造器可以有新的异常,但在处理这些异常时还需要考虑基类的异常public StormyInning()throws RainedOut, BaseballException {}public StormyInning(String s)throws BaseballException {}// 普通的方法在重写时,必须遵守基类方法的约定// 1. 访问权限// 2. 不能擅自添加异常// void walk() throws PopFoul{}// event()方法已经存在于基类当中,接口无法增加其的异常// public void event() throws RainedOut {}// 若是基类中不存在的方法,则可以自行添加声明:@Overridepublic void rainHard() throws RainedOut {}// 即使基类版本会抛出异常,其子类版本也可以选择不进行异常抛出:@Overridepublic void event() {}// 若是重写的方法,可以抛出其基类版本所说明的异常的子类:@Overridepublic void atBat() throws PopFoul { // PopFoul是Foul的子类}public static void main(String[] args) {try {StormyInning si = new StormyInning();si.atBat();} catch (PopFoul e) {System.out.println("Pop Foul(一次违规的挥棒)");} catch (RainedOut e) {System.out.println("Rained out(下雨了)");} catch (BaseballException e) { // 这里,派生的si.atBat()不会抛出Strike异常System.out.println("通用的baseball(棒球)异常");}try {// 若向上转型,情况会有所不同Inning i = new StormyInning();i.atBat();// 此时,就必须捕获来自基类版本的异常} catch (Strike e) {System.out.println("Strike(发生碰撞)");} catch (Foul e) {System.out.println("Foul(犯规)");} catch (RainedOut e) {System.out.println("Rained out(下雨了)");} catch (BaseballException e) {System.out.println("通用的baseball(棒球)异常");}}
}

        先观察Inning类:

        该类的构造器和event()方法都有异常列表,这就向编译器说明它们会抛出异常,但实际上并没有。这种做法是合法的,因为编译器会要求用户捕获任何可能在event()的重写版本中添加的异常(这也适用于抽象方法)。

        StormyInning继承了Inning类和Storm接口,其中event()方法即存在于Inning中,也存在于Storm中。注意,这个event()方法不能改变Inning中的event()方法的异常说明:

假设这种语法能够成立,那么在我们使用基类的时候,就难以判断是否捕获了正确的异常。

    构造器由于其多样的调用形式,在异常的约束方面也不同于一般的方法。有上述例子可以发现,构造器可以抛出任何异常。也因此,子类构造器必须在其异常说明中声明基类构造器提到的异常

        子类构造器不能捕获基类构造器抛出的异常。

        再看StormyInning类中的walk()方法:

这个方法之所以无法编译,就是因为其抛出了一个Inning.walk()没有抛出的异常。

        而从StormyInning类中的event()方法中可以发现:

即使基类方法抛出异常,其子类也可以选择不进行异常抛出。因为这不会破坏基类版本会抛出异常的情况。

        最后需要提一点,在main()中,我们首先定义了一个StormInning对象:

StormyInning si = new StormyInning();

此时,编译器会强制要求我们处理StormInning类声明会抛出的异常。但是,若我们将其向上转型为Inning

Inning i = new StormyInning();

则编译器会强制我们捕获基类声明会抛出的异常。

    异常说明不是方法类型的一部分,因此不能依赖方法说明作为重载方法的依据。

        注意:在继承和重写的过程中,“异常说明”可以缩小,但是不能扩大——这就和继承过程中的规则恰恰相反。

构造器

        我们需要常常怀疑:当发生异常时,程序是否正确地进行了清理。

        构造器的存在会使得对象有一个安全的起始状态。但是,构造器可能会执行某些操作,比如打开文件,这种操作需要通过特殊的清理方法处理。若构造器内抛出了异常,这些清理行为可能就不会正确执行了。

        finally可能是一个办法。但是,由于finally每次都会执行清理代码,若构造器半途而废,finally就可能会把构造器还未成功构建的部分也一并清理。

【例子:文件的打开与清理】

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;public class InputFile {private BufferedReader in;public InputFile(String fname) throws Exception {try {in = new BufferedReader(new FileReader(fname));// 剩下的部分也可能抛出异常} catch (FileNotFoundException e) {System.out.println("无法打开[" + fname + "]");// 因为没有打开,所以不用关闭文件throw e;} catch (Exception e) {// 除上述异常,其他异常情况都需要关闭文件try {in.close(); // 对于可能抛出异常的close()方法,也需要使用try进行处理} catch (IOException e2) {System.out.println("in.close() 执行失败");}throw e; // 重新抛出异常} finally {// 不应该在这里进行文件关闭}}public String getLine() {String s;try {s = in.readLine();} catch (IOException e) { // 在方法内部直接处理异常throw new RuntimeException("readline() 失败");}return s;}public void dispose() {try {in.close();System.out.println("dispose() 执行成功");} catch (IOException e) {throw new RuntimeException("in.close() 失败");}}
}

        除了捕获FileNotFoundException(文件未发现)的catch子句外,其他catch子句都应该关闭文件(此时文件已经被打开)。

        比较好的做法是,在执行完异常处理后再次抛出异常。因为构造器的调用已经失败,那么我们当然不会希望构造器的调用者认为构造器顺利完成了任务。

        就像之前所说,在构造器中,finally绝对不适合调用close()来进行文件关闭。因为这种做法会导致文件在构造器调用完毕后就被关闭,这很明显与我们的期望相违背。

    上述的代码中,有些方法会抛出异常,而有的方法会在内部直接处理异常。这种对异常处理的设计需要仔细考虑。

        现在必须提醒一点,Java存在着一个缺点:除了内存的清理,其他清理都不会自动发生。这就导致Java必须告诉客户程序员,那些要让他们自己处理。

        下面的例子演示了如何清理可能抛出异常的类:

【例子:嵌套的try块】

public class Cleanup {public static void main(String[] args) {try {InputFile in = new InputFile("Cleanup.java");try {String s;int i = 1;while ((s = in.getLine()) != null); // 一行一行进行数据处理} catch (Exception e) {System.out.println("在main()中捕获异常");e.printStackTrace(System.out);} finally {in.dispose();}} catch (Exception e) {System.out.println("InputFile对象构造失败");}}
}

        程序执行的结果是:

        InputFile对象的构造存在于外层的try块之中。若构造器执行失败,程序不会向下进入下一个try块中,而是直接来到外层的try块对应的catch子句内。

    这里体现了一种清理惯用法:在创建了一个需要清理的对象后,直接跟一个try-finally块。

【例子:清理惯用法】

class NeedsCleanup {// 该构造不会失败private static long counter = 1;private final long id = counter++;public void dispose() {System.out.println("需要清理 id:" + id);}
}class ConstructionException extends Exception {
}class NeedsCleanup2 extends NeedsCleanup {// 该构造可能失败NeedsCleanup2() throws ConstructionException {}
}public class CleanupIdiom {public static void main(String[] args) {// 直接的处理方式:在需要清理的对象后紧跟一个try-finally块NeedsCleanup nc1 = new NeedsCleanup();try {// ...} finally {nc1.dispose();}// 可以将不会失败的构造对象组织在一起:NeedsCleanup nc2 = new NeedsCleanup();NeedsCleanup nc3 = new NeedsCleanup();try {// ...} finally {// 释放顺序与构造顺序相反nc3.dispose();nc2.dispose();}// 若构造可能失败,就需要确保每个对象的清理try {NeedsCleanup2 nc4 = new NeedsCleanup2();try {NeedsCleanup2 nc5 = new NeedsCleanup2();try {// ...} finally {nc5.dispose();}} catch (ConstructionException e) {// 处理nc5可能报出的异常System.out.println(e);} finally {nc4.dispose();}} catch (ConstructionException e) {// 处理nc4System.out.println(e);}}
}

        程序执行的结果是:

        在nc4nc5的构造处理的过程中,可以发现try-catch导致的麻烦:为了处理每一个对象,我们需要为它们分别设定try-catch的处理。

    为了处理异常,我们需要尽可能考虑所有可能性,并确保它们能被处理。

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

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

相关文章

面试经典 150 题 2 —(滑动窗口)— 3. 无重复字符的最长子串

3. 无重复字符的最长子串 方法 class Solution { public:int lengthOfLongestSubstring(string s) {int result 0, length s.length();int start 0, end 0;while(end < length){// 发现有重复字符时&#xff0c;可以直接把左指针移动到第一个重复字符的下一个位置for(i…

【Windows】RPC调用过程实例详解

概述&#xff1a;windows 创建 RPC调用过程实例详解 参考文章&#xff1a;Remote procedure call (RPC)&#xff08;远程过程调用 (RPC)&#xff09; - Win32 apps | Microsoft Learn 文章目录 0x01、生成 UUID 和模版(IDL)文件0x02、添加 acf 文件0x03、编译 idl 文件0x04、客…

基于java+vue+springboot的家庭理财记账信息网站

运行环境 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven 项目介绍 在这科技…

TensorFlow学习:使用官方模型进行图像分类、使用自己的数据对模型进行微调

前言 上一篇文章 TensorFlow案例学习&#xff1a;对服装图像进行分类 中我们跟随官方文档学习了如何进行预处理数据、构建模型、训练模型等。但是对于像我这样的业余玩家来说训练一个模型是非常困难的。所以为什么我们不站在巨人的肩膀上&#xff0c;使用已经训练好了的成熟模…

AQS内部的体系架构

AQS本质上是一个双向队列&#xff0c;加一个状态位state。内部靠Node节点形成队列。 AQS由state和CLH变体的虚拟双端队列组成。 AQS的内部类Node类 属性说明&#xff1a; 内部结构&#xff1a;

Python 入门

目录 1 Python介绍1.1 特点1.2 什么时候不应该用Python1.3 Python解释器 2 IDLE开发环境使用入门2.1 IDLE 两种模式2.2 IDLE常用快捷键 3 程序基本格式4 图形化程序设计5 绘制奥运五环 声明&#xff1a;本文作为自己的学习笔记&#xff0c;欢迎大家于本人学习交流&#xff0c;转…

【深度学习】Chinese-CLIP 使用教程,图文检索,跨模态检索,零样本图片分类

代码&#xff1a;https://github.com/OFA-Sys/Chinese-CLIP/blob/master/deployment.md 文章目录 安装环境和onnx推理转换所有模型为onnx测试所有onnx模型的脚本onnx cpu方式执行docker镜像 安装环境和onnx推理 安装环境&#xff0c;下载权重放置到指定目录&#xff0c;进行on…

联邦学习中的攻击手段和防御机制

联邦学习产生的背景&#xff1a; 海量数据的生成和这些数据的后续处理往往需要一个数据仓库并在仓库内汇总数据。然而&#xff0c;随着数据泄漏事件层出不穷&#xff0c;数据安全性得不到保障&#xff0c;人们开始怀疑集中收集数据是否可靠&#xff0c;数据的隐私性的也得到了更…

创建一个基本的win32窗口

1.建立一个窗口的基本步骤 &#xff08;1&#xff09;向系统注册一个窗体类 &#xff08;2&#xff09;根据窗体类创建窗口 &#xff08;3&#xff09;进入消息循环 2.程序结构 (1)主函数的输入参数 int WINAPI WinMain( HISTANCE hInstance,//当前窗口的句柄 HINSTANCE hPr…

项目管理过程组

项目管理有2条主线&#xff0c;一条是技术&#xff0c;一条是管理。项目过程由项目团队实施。一般术语以下两大类之一&#xff1a;一类是项目管理过程。另一类是面向产品的过程。在大多数情况下&#xff0c;大多数项目都有共同的项目管理过程。它们通过有目的的实施而互相联系起…

计算机网络 | 体系结构

计算机网络 | 体系结构 计算机网络 | 体系结构概念及功能计算机网络简介计算机网络的功能因特网发展阶段小结 组成与分类计算机网络的组成计算机网络的分类小结 标准化工作及相关组织速率相关性能指标速率带宽吞吐量小结 时延相关性能指标时延时延带宽积往返时延RTT利用率小结 …

点云模板匹配

点云模板匹配是一种在点云数据中寻找特定形状或模式的方法。它通常用于计算机视觉和三维图像处理中&#xff0c;可以应用于物体识别、姿态估计、场景分析等任务。点云模板匹配的基本思想是将一个称为模板的小点云形状与输入的大点云进行匹配&#xff0c;以找到最佳的对应关系。…

OCR让点读笔如虎添翼

点读笔是一种智能学习工具&#xff0c;它可以通过识别文字来提供相应的语音或图像反馈。在实现文字识别功能时&#xff0c;点读笔通常会借助OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;技术。下面将详细介绍点读笔如何利用OCR技术实现文…

SMOS数据处理,投影变换,‘EPSG:6933‘转为‘EPSG:4326‘

在处理SMOS数据时&#xff0c;遇到了读取nc数据并存为tif后&#xff0c;影像投影无法改变&#xff0c;因此全球数据无法重叠。源数据的投影为EPSG:6933&#xff0c;希望转为EPSG:4326。 解决代码。 python import os import netCDF4 as nc import numpy as np from osgeo impo…

水库大坝除险加固安全监测系统解决方案

一、系统背景 为贯彻落实《办公厅关于切实加强水库除险加固和运行管护工作的通知》&#xff08;〔2021〕8号&#xff09;要求&#xff0c;完成“十四五”小型病险水库除险加固、雨水情测报和大坝安全监测设施建设任务&#xff0c;规范项目管理&#xff0c;消除安全隐患&#xf…

【通信系列 5 -- HTTPS 介绍】

文章目录 1.1 HTTPS链接网址1.1.1 HTTPS 产生背景1.1.2 HTTPS工作内容1.1.3 SSL/TLS1.1.4 TLS 的命名规范1.1.5 TLS 加密算法1.1.6 分组模式1.1.7 摘要算法1.1.8 非对称加密1.1.9 CA认证 1.2 openssl1.2.1 RSA 签名验签 1.1 HTTPS链接网址 HTTP 是一种 超文本传输协议(Hyperte…

c#设计模式-行为型模式 之 中介者模式

&#x1f680;简介 又叫调停模式&#xff0c;定义一个中介角色来封装一系列对象之间的交互&#xff0c;使原有对象之间的耦合松散&#xff0c;且可以独立地改变它们之间的交互。 从下右图中可以看到&#xff0c;任何一个类的变 动&#xff0c;只会影响的类本身&#xff0c;以及…

198、RabbitMQ 的核心概念 及 工作机制概述; Exchange 类型 及 该类型对应的路由规则

JMS 也是一种消息机制 AMQP ( Advanced Message Queuing Protocol ) 高级消息队列协议 ★ RabbitMQ的核心概念 Connection&#xff1a; 代表客户端&#xff08;包括消息生产者和消费者&#xff09;与RabbitMQ之间的连接。 Channel&#xff1a; 连接内部的Channel。 Exch…

Git基础使用

Git基础使用 1、git的本质2 Gitlab账号申请、免密设置2.1 申请Gitlab账号2.2 免密设置2.2.1 公钥及私钥路径2.2.2 免密设置 3、常用命令3.1 git全局配置信息3.2 初始化项目3.3 拉取项目 将日常笔记记录上传&#xff0c;方便日常使用翻阅。 1、git的本质 git对待数据更像是一个快…

k8s修改集群IP--重置集群

原来IP地址 192.168.10.138 k8s-master 192.168.10.139 k8s-node1 192.168.10.140 k8s-node2 新IP地址 192.168.10.148 k8s-master 192.168.10.149 k8s-node1 192.168.10.150 k8s-node2 cp -Rf /etc/kubernetes/ /etc/kubernetes-bak pki 证书目录保留下来&#xff1a; rm -rf …