【Java学习笔记】异常处理

生活中我们在使用一些产品的时候,经常会碰到一些异常情况。例如,使用ATM机取钱的时,机器会突然出现故障导致无法完成正常的取钱业务,甚至吞卡;在乘坐地铁时,地铁出现异常无法按时启动和运行;使用手机时,手机突然自动关机,等等。这些产品的异常情况,有些是系统硬件的问题,但更多的情况是软件出现了问题。
使用Java开发软件时,无论程序员多么小心谨慎,产品反复测试,还是会出现程序错误的现象。所以,优秀的编程语言可以为程序员提供高效、可靠的错误处理机制,便于开发高质量的软件产品。
Java语言提供了一种面向对象异常处理机制来报告和处理错误,这种异常处理机制对异常的处理都封装在异常类中完成。程序在运行过程中,如果出现异常,则会抛出一个异常类对象。

1.异常的概念

  • 在程序的设计过程中通常会遇到两种不可避免的错误:编译错误和运行错误。
  • 编译错误是由于编写的程序不符合程序的语法规定而导致的语法问题。大部分的编译错误,是由于对编程语言的语法不熟悉或拼写错误引起的。如果违反了编程语言规则,就会导致程序编译错误。
  • 运行错误是指能够顺利的编译通过,在程序运行过程中产生的错误。例如:操作文件时文件无法找到,没有给对象开辟内存空间等。如果出现这样的错误,程序会停止运行,但是这样的错误,不容易被发现和排除。
  • java中的异常处理机制,为程序提供了清晰的异常终止和处理错误的接口。当异常发生时,发生异常的方法抛出一个封装了错误信息的异常对象。此时,程序不会继续运行,发生错误的方法也不会返回正常运行的值。异常处理机制开始搜索异常处理器来处理这种错误。
  • 异常(Exception)是一个在程序运行期间发生的事件。它会终端正在运行中的程序。Java中常见的异常包括 数组下标越界(ArrayIndexOfBoundsException)、空指针异常类(NullPointerException)、算术异常(ArithmeticException)、字符串转换为数字异常(NumberFormatException)、类型不存在异常(TypeNotPresentException)等。

2.异常的基本样式

与java异常处理的相关关键字包括try、catch、throw和finally等,异常的基本样式也使用这些关键字。

  • 基本样式:
methodname(){
	try{
		......				//可能产生异常的语句或方法程序块
	}
	catch(ExceptionType1 e){
			......		//对异常类型ExceptionType1对象的处理
	}
	catch(ExceptionType2 e){
			...... //对异常类型ExceptionType2对象的处理
		throw(e) //再抛出这个异常
	}
	finally {
	......//无论是否抛出异常,都需要执行的代码块
}
}

在方法内:

  • try语句内是用户监视的可能出现异常的程序语句和方法。
  • catch语句快内是用户对抛出异常对象的处理语句。
  • throw语句块内是手动抛出一个异常给函数method()的上级执行者,
  • finally语句块内,是必须在函数method()返回之前执行的代码。
    【例】异常处理简单示例
    在这里插入图片描述

3.java异常类

java异常类都是由Throwable类派生而来的。派生出的两个分支分别是Error类和Exception类。

3.1异常的层次结构

异常类是一种特殊类,表示的是一种特殊的运行错误,用于处理异常。在Java程序设计中,异常对象都是从Throwable类派生的实例。
在这里插入图片描述

  • error用于处理在运行过程中发生的系统内部错误和资源耗尽错误。
    应该尽量不出现Error类的错误。因为一旦出现了这样的错误,除了通知用户并使线程安全终止,用户也无能为力。
    通常Java程序不对Error类异常进行处理。并且这类错误也很少出现。
  • Exception类又分为多个分支,这些分支可以分为两类,一类是派生于RunTimeException的异常。一类是派生于IOException的异常,
    RunTimeException异常是由于程序错误导致的异常,IOException异常是本来可以正常运行的程序,在操作文件删除或者文件名修改等特殊情况下发生异常而导致程序不能正常运行。

派生于Throwable类的常用异常

被终止异常(InterruptedException)某个线程处于长时间的等待、休眠或其他暂停状态,其他线程通过Thread类的interrupt()方法终止该线程时抛出的异常
方法不存在异常(NoSuchMethodException)访问某个类的不存在方法时抛出的异常
找不到类异常(ClassNotFoundException)ClassNotFoundException 表示在尝试加载类时找不到该类。这可能发生在运行时,通常是由于类路径不正确或缺少相应的类文件
不支持克隆异常(CloneNotSupportedException)当没有实现Cloneable接口或者不支持克隆方法时调用其clone方法抛出该异常

派生于RuntimeException类的常用异常

算术运算异常(ArithmeticException)整数除0时抛出这个异常
类造型异常(ClassCstException)
数组越界异常(ArrayIndexOutofBoundsofException)
数组存储异常(ArrayStoreException)
访问空指针(NullPointException)

由IOException类派生的异常

文件已结束异常(EOFException)
文件未找到异常(FileNotFoundException)

3.2异常处理方法

【例】
在这里插入图片描述

4.异常捕获

企业针对产品的异常,会使用一些关键字进行描述和处理。如:产品平均无故障时间、产品故障率、召回等。java的异常处理是通过5个关键词来实现的。分别是try catch throw throws finally 。

其中,try用来存放可能发生一个或多个异常的Java语句,catch语句块用来捕获try语句块抛出的异常。finally语句块用来存放释放的资源和句柄等。

4.1 异常捕获处理语块

为了捕获异常,需要使用catch语句块来配合try语句块。
try语句块用来指定可能发生异常的程序块,配合使用的catch语句块用来处理try语句块抛出的异常。
try语句块内部如果出现异常,那么程序将跳过try语句块中出现的异常语句之后的其它代码,直接进入catch语句块内执行代码
【例】
在这里插入图片描述

try-catch 语句块可以嵌套使用。当try语句块遇到异常时,Java会检查与try异常程序块相配合的catch捕获处理中是否存在能处理该异常的catch语句块。如果存在,则该异常将被改catch语句块捕获并处理,否则,该异常将被上一级的try-catch语句块捕获。

【例】

package example;

public class TrynestdealException {

	public static void main(String[] args) {
		tryCatch();						//调用静态try-catch函数
		
	}
	//静态tryCatch()函数
	static void tryCatch() {
		try {							//外层try块
			try {						//内层try块
				System.out.println("执行里层try块\n");
				int inte = Integer.parseInt("pencil");//字符串转化为整数
				System.out.println(inte);//输出整数
			}
			catch(ArrayIndexOutOfBoundsException e) {	//捕获异常
				System.out.println("执行里层catch块\n");
				System.out.println("捕获ArrayIndexOutOfBoundsException异常" + e.getMessage());
			}
			catch(ArithmeticException e) {	//捕获异常 ArithmeticException
				//捕获异常后输出异常信息
				System.out.println("执行里层catch2块\n");
				System.out.println("捕获ArithmeticException异常" + e.getMessage());
				
			}
		}
		catch(ClassCastException ie) {	//捕获异常ClassCastException
			System.out.println("捕获外层异常ClassCastException" + ie.getMessage());
		}
		catch(NumberFormatException ie) {
			System.out.println("捕获外层异常NumberFormatException" + ie.getMessage());
		}
	}

}

在这里插入图片描述

4.2 必须执行语句块

有时候我们要去某地,有多条交通路线,其中有一条是必须走的,也就是通常所说的交通要道。在try-catch-finally结构中,finally语句块就是交通要道。
在try-catch语句块中定义了finally语句块。这时无论try-catch语句块是否抛出和捕获异常,程序都将执行finally语句块。
【例】

package example;

public class ExceptionFinally {

	public static void main(String[] args) {
		
		int num[] = new int[5];
		try {
			for(int i = 0;i<5;i++) {
				num[i]= i+1;
				for(int j = 0;i<=i;j++) {
					num[i]+= num[j];
				}
			}
		for(int i = 0;i<6;i++) {
			System.out.println(num[i]);
		}
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			System.out.println("finally块是必经之路");
		}

	}

}

在这里插入图片描述
在操作文件的时候,无论操作是否成功,必须要在程序运行后关闭文件。同样,如果将释放内存的工作放到finally语句块内,那么程序不会由于未释放资源而导致内存泄漏

4.3 必须执行语句块的意外

finally语句块通常情况下总是会被执行,但在下面这几种情况下finally语句块不会被执行

  • 电脑断电关机
  • 在finally语句块之前的语句中含有SYSTEM.EXIT(0)语句
  • 在finally语句块执行过程中抛出异常
  • 程序所属线程死亡,程序在未执行finally语句块之前就退出

在这里插入图片描述

5.异常抛出

异常捕获语句块都存在于产生异常的方法中,异常抛出可以将产生的异常抛给调用它的方法。
如果某方法的try语句块中抛出的异常没有与之匹配的catch块,或者catch语句块已经不活了异常但不想立即处理,就可以将异常抛给调用它的上一级方法。

5.1 异常抛出的概念

  • 在方法声明的时候,必须指定方法中可能产生的异常,使这个方法的调用者必须处理这些可能的异常。调用者可以自己处理这种异常,也可以将这种异常派送给它的调用者,因此异常可以逐级上溯。直到找到可以处理他的代码为止。
  • 抛出异常必须做的两部分工作是在方法的声明中使用throws语句指定它所抛出的异常和使用throw语句抛出异常。
  • 在方法中声明可能出现的异常是为了告诉编译器该方法可能产生的异常,因而要求该方法的使用者必须考虑处理方法抛出的异常,以增强程序的健壮性。
  • 任何有异常抛出的方法都有可能导致程序的崩溃,如果使用者没有对方法抛出的异常进行处理,则会导致程序运行结束。
  • 通过throw可语句可以明确的抛出一个异常,而在方法中使用throws声明次方法将抛出某种类型的异常。

5.2 throw

使用throw语句时必须声明一个异常对象,这个对象时Throwable派生类的对象
ThrowableInstance一定是Throwable类或Throwable子类的一个对象。简单类型(int、char)以及非Throwable类(String或Object)不能用作异常
【例】

package example;

public class UseThrowExample {
	static void demoproc(String v1) {
		try {
			if(v1 == null) {
				//抛出NullPointerException异常
				throw new NullPointerException("Throw Example");
			}
		}catch(NullPointerException e){
				System.out.println("输入的参数为空");
				throw e;
		}
	}
	public static void main(String[] args) {
		try {
			String string = null;
			demoproc(string);		//调用方法
		}catch(NullPointerException e) {
			System.out.println("异常情况为"+ e);
		}
	}

}

在这里插入图片描述

5.3 throws

如果一个方法可以导致一个异常但不处理它,那么他必须在方法声明时包含一个throws子句,以使方法的调用者库保护他们自己而不发生异常。
throws子句列举了一个方法可能引发的所有异常类型,一个方法引发的所有其他类型的异常必须在throws子句中生明。如果不这样做,会导致编译错误。

package example;

import java.io.IOException;

public class ThrowsUsingExample {
	public static void main(String[] args) {
		try {
			System.out.println("请输入字符");
			String s = getInput();
			System.out.println("输入字符为:");
			System.out.println(s);
		}catch(IOException e) {
			System.out.println("产生异常"+e.getMessage());
		}
		
	}

	private static String getInput() throws IOException{
		
		char[] buffer = new char[10];
		int count = 0;
		boolean flag = true;
		while(flag) {
			buffer[count] = (char)System.in.read();
			if(buffer[count]=='\n') {
				flag = false;
			}else {
				count++;
			}
			if(count >=10) {
				IOException aException = new IOException("buffer is null");
				throw aException;
				
			}
		}
		return new String(buffer);
	
		
	}

}

在这里插入图片描述

5.4 抛出异常的步骤

我们在使用手机软件时,经常会遇到出现异常、卡顿或者异常退出的情况,这主要和开发软件异常处理或者手机内存不足等情况有关。程序抛出异常,一般分为以下三个步骤:

  • 确异常类
  • 创建异常类的实例
  • 抛出异常
package example;

import java.sql.SQLException;

public class ExceptionThreestep {
	
	//可能会抛出异常的方法
	public static void throwException() throws SQLException{
		try {
			throw new SQLException("SQLException1");
		}catch(SQLException e) {
			System.out.println("throwException:()抛出异常"+e.getMessage());
		//捕获异常暂不处理,抛出异常
			throw new SQLException("SQLException1");//抛出异常SQLException
		}
	}
	

	public static void main(String[] args) {
		
		try {
			throwException();
		}
		catch(SQLException e) {
			System.out.println("main()捕获SQLException:"+e.getMessage());
		}
	}

}

在这里插入图片描述

6.自定义异常

除了Java中提供的一些异常类,还可以根据自己的需求定义异常类。

6.1 创建用户自定义异常

package example;


class UserOwnException {
	//声明UserOwnException无参数构造方法
	public UserOwnException() {
		
	}
	
	//声明UserOwnException带有String类型参数的构造方法
	public UserOwnException(String smg) {
		super();//调用父类的构造方法
	}

}

public class UsingUserException {

	public static void main(String[] args) {
		
		try {
			execute();   //调用execute()方法
		}catch(UserOwnException e) {
			System.out.println(e.getMessage());
		}

	}
	
	static void execute() throws UserOwnException{
		try {
			throw new Exception();//抛出异常
		}
		//捕获Exception类
		catch(Exception e) {
			//捕获后,直接抛出用户自定义异常类
			throw new UserOwnException("自定义异常抛出"+e.getMessage());
		}
	}



}



6.2 捕获运行时异常

创建自己的异常类,可以方便的处理和捕获某些运行时的异常,并重新抛出一个新的异常提供给它的调用者捕获。
运行时异常属于未检查异常,如果在方法的throws子句中声明了此异常,那么方法的调用者就可以不处理此异常。

package example;

class MyArithException extends Exception{
	MyArithException(){
	}
	MyArithException(String msg){
		super(msg);	//调用父类的构造方法
	}
}


public class CatchRunException {

	public static void main(String[] args) {
		
		try {
			executeRuntime();		//调用executeRuntime()方法
		}catch(MyArithException e){
			System.out.println("捕获运行时异常"+e.getMessage());
		}

	}
	
	static void executeRuntime() throws MyArithException{
		try {
			int i = 1/0;		//抛出运行时异常 ArithmeticException
		}
		catch(ArithmeticException e) { //捕获异常ArithmeticException
			
			/*
			 * 在这里捕获运行时异常ArithmeticException 不处理,
			 * 而是抛出一个新的MyArithException 异常
			 * 因为运行时异常不在方法声明的throws子句中声明
			 * 
			 * */
			throw new MyArithException(e.getMessage());
		}
	}
	

}


在这里插入图片描述

7.拓展训练

7.1 训练一:强制类型转换异常

【拓展要点:ClassCastException异常】
当程序运行时,有时需要对不同的类型进行类型转换。在进行类型转换的过程中,当java虚拟机发现这两个类型不兼容而无法完成转换时,就会出现ClassCastException异常

7.2 训练二:找不到类型时的异常

【拓展要点:ClassNotFoundException异常】
当应用试图根据字符串形式的类名构造类,而在遍历CLASSPATH之后做不到对应名称的.class文件时,将抛出ClassNotFoundException异常。

8.技术解惑

8.1 如何优雅地处理异常

异常是一种强大的调试手段,是因为回答了以下三个问题:

  • 为什么出了错 -------- 异常类型回答了“什么”被抛出
  • 在哪里出了错 ------- 异常堆栈回答了“在哪里”被抛出
  • 为什么出错 ------- 异常信息回答了“为什么”被抛出

三个原则可以帮助我们在调试过程中最大限度的使用好异常:

-具体明确 - 提早抛出 -延迟捕获

8.2 throw与throws的区别

(1)throw表示语句抛出一个异常。
一般用于程序出现某种逻辑时,程序员主动抛出某种特定类型的异常。
(2)throws是方法可能抛出异常的声明(在声明方法时,表示该方法可能要抛出异常)
当某个方法可能会抛出某种异常时,用throws声明可能抛出的异常,然后交给上层调用它的方法程序处理。

throw与throws关键字的比较

  • throws 出现在函数头部,throws出现在函数体中
  • throws表示出现异常的一种可能性,并不一定会发生异常;而throw表示抛出异常,执行throw一定会抛出某种异常对象
  • 两者都是消极处理异常的方式,而是抛出或者可能抛出异常。但是不会由函数去处理异常,而是由函数的上层调用进行处理

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电脑怎么卸载软件?多个方法合集(2024年新版)

在电脑的日常使用中&#xff0c;我们经常需要安装各种软件来满足不同的需求&#xff0c;但随着时间的推移&#xff0c;可能会出现一些软件不再需要或需要更换的情况。此时&#xff0c;及时从电脑上卸载这些不必要的软件是非常重要的。它不仅可以释放硬盘空间&#xff0c;还可以…

第二证券股市资讯:股票中什么叫龙头?

龙头&#xff0c;也就是龙头股&#xff0c;指的是某一职业中有必定影响力和号召力的股票&#xff0c;龙头股的涨跌通常对其他同职业板块股票的涨跌有必定演示和引导作用&#xff0c;是一种风向标一般的存在。龙头股的技能面表现和成交量都会比同时刻的大盘和地块要强。 具体分…

【尚庭公寓SpringBoot + Vue 项目实战】移动端项目初始化(十九)

【尚庭公寓SpringBoot Vue 项目实战】移动端项目初始化&#xff08;十九&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】移动端项目初始化&#xff08;十九&#xff09;1、 SpringBoot配置2、Mybatis-Plus配置3、Knife4j配置4、导入基础代码5、导入接口定义代码6…

Python语言修改控制台输出文字的颜色和背景颜色

Python语言修改控制台输出文字的颜色和背景颜色 格式显示模式字体颜色背景颜色文字加效果显示类 格式 \033[显示模式;字体颜色;背景颜色m 显示模式 显示模式格式将文本颜色和背景颜色重置为默认值&#xff0c;取消所有其他文本属性\033[0m高亮&#xff08;加粗&#xff09;\03…

华为OD机试 - 部门人力分配 - 二分查找(Java 2024 D卷 200分)

华为OD机试 2024D卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;D卷C卷A卷B卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测…

redis-实战篇(8)达人探店

8、达人探店 8.1、达人探店-发布探店笔记 发布探店笔记 探店笔记类似点评网站的评价&#xff0c;往往是图文结合。对应的表有两个&#xff1a; tb_blog&#xff1a;探店笔记表&#xff0c;包含笔记中的标题、文字、图片等 tb_blog_comments&#xff1a;其他用户对探店笔记的…

最新PHP仿猪八戒任务威客网整站源码/在线接任务网站源码

资源介绍 老规矩&#xff0c;截图为亲测&#xff0c;前后台显示正常&#xff0c;细节功能未测&#xff0c;有兴趣的自己下载。 PHP仿猪八戒整站源码下载&#xff0c;phpmysql环境。威客开源建站系统&#xff0c;其主要交易对象是以用户为主的技能、经验、时间和智慧型商品。经…

上海亚商投顾:创业板指低开低走 先进封装概念午后走强

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日缩量震荡调整&#xff0c;深成指、创业板指跌超1%。车路云概念延续强势&#xff0c;长江通信4连板&am…

LVGL开发教程-FreeRTOS中的LVGL

系列文章目录 知不足而奋进 望远山而前行 目录 系列文章目录 文章目录 前言 重要步骤 lv_tick_inc(x) lv_timer_handler() 1. 声明一把锁 2. 初始化这把锁 3. 创建一个任务 4. 编写任务的内容 完整示例代码 总结 前言 在嵌入式系统开发中&#xff0c;使用LVGL&…

Docker定位具体占用大量存储的容器

监控告警生产环境的服务器磁盘分区使用率大于90%&#xff0c;进入服务器查看Docker 的 overlay2 存储驱动目录中占用很大&#xff0c;很可能是某个容器一直在打印日志&#xff0c;所以需要定位到是哪个容器&#xff0c;然后进行进一步排查。 然后进入到overlay2中查看是哪个目录…

优化改进YOLOv5算法之Shift-ConvNets,具有大核效应的小卷积核,效果提升明显

目录 1 Shift-ConvNets模块原理 1.1 Decomposition and Combination of Convolution 1.2 Sparse Dependencies of Large Convolution Kernels 1.3 Intermodule Feature Manipulation 2 YOLOv5中加入Shift-ConvNets模块 2.1 common.py文件配置 2.2 yolo.py配置 2.3 创建…

【Spine学习13】之 制作受击动画思路总结(叠加颜色特效发光效果)

绑定IK腿部骨骼容易出错的一种方式&#xff0c; 要记住 如果按照错误方式绑定骨骼&#xff0c;可能移动IK约束的时候会另腿部的弯曲方向相反了 &#xff1a; 上节分享了攻击动作的制作思路总结&#xff0c; 这节总结受击思路。 第一步&#xff1a; 创建一个新的动画&#xff1…

专业140+总分400+武汉理工大学855信号与系统考研经验电子信息与通信工程,真题,大纲,参考书

专业855信号与系统140&#xff0c;总分400&#xff0c;今年顺利上岸武汉理工大学&#xff0c;总结一下自己的复习经历&#xff0c;希望对报考武理工的同学有所帮助。专业课&#xff1a;855信号与系统 首先教材&#xff1a; 《信号与系统》高等教育出版社 作者&#xff1a;刘泉…

Vue65-vue-resource:ajax请求

vue-resource是vue的插件库&#xff0c;用vue.use(xxxx)使用插件。 1、安装 2、引入和使用 这个库&#xff0c;维护的频率不高了。还是建议使用&#xff1a;axios&#xff0c;vue-resource只是了解即可。

1969python房屋租赁管理系统mysql数据库Flask结构BootStrap布局计算机软件工程网页

一、源码特点 python Flask房屋租赁管理系统是一套完善的web设计系统mysql数据库 &#xff0c;对理解python编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 python flask 房屋租赁管理系统 开发环境pycharm mysql …

大模型的下一站:AI Agent!

前言 现在各家基本上都有自己的大模型产品&#xff0c;现在的重点都是在找商业模式&#xff0c;以及扩展大模型的应用场景上。所以大家做APP、做Copilot也就不足为奇&#xff0c;都是为自己找出路的做法。但从作者的角度&#xff0c;Copilot只是传统互联网应用到大模型应用的过…

汇凯金业:现货黄金技术分析及其应用

现货黄金技术分析是一种通过市场价、量、时、空间四个元素的研究&#xff0c;利用图表表达数据&#xff0c;从而预测未来价格走向的方法。虽然技术分析并非完美无缺&#xff0c;但它在投资决策中起到了重要作用。以下是现货黄金技术分析的详细介绍及其应用方法。 技术分析的基…

1分钟告诉你电脑微信文件夹储存在什么位置!

在日常生活中&#xff0c;微信已经成为我们不可或缺的社交工具之一&#xff0c;我们使用它来与亲朋好友保持联系&#xff0c;分享生活中的点滴。然而&#xff0c;随着我们在微信中发送和接收越来越多的信息、图片、视频等内容&#xff0c;微信所占用的存储空间也逐渐增加。 因…

做一个架构师需要什么能力?

作为一个架构师&#xff0c;需要具备多方面的能力来确保项目的顺利进行和系统的成功设计。以下是架构师所需的主要能力&#xff0c;按照不同的类别进行归纳和分点表示&#xff1a; 技术能力 编程能力&#xff1a;架构师通常是一个开发团队中技术较为出色的人员之一&#xff0…

转型技术管理:九大步骤解锁高效管理新境界

文章目录 引言一、寻求反馈二、从员工的角度看待问题三、总览全局四、管理自己的情绪五、赞赏员工的出色工作六、在人前支持员工七、管理自己的职业生涯八、认识到自己也许存在偏见&#xff0c;与不同于自己的人交流九、在工作中建立信任和沟通总结 引言 在快速变化的科技浪潮…