news 2026/5/8 4:46:20

第10篇 异常处理——程序的容错机制 仓颉原生中文编程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第10篇 异常处理——程序的容错机制 仓颉原生中文编程

第10篇 异常处理——程序的容错机制

**作者:**中文编程倡导者—— 李金雨
联系方式:wbtm2718@qq.com
**目标读者:**编程入门(零基础)
核心理念:使用华为仓颉原生中文编程,体验真正的国产编程语言


一、什么是异常?

想象一下这些场景:

  • 你打开一个文件,但文件不存在
  • 你输入"abc",但程序期待一个数字
  • 你访问数组的第100个元素,但数组只有10个元素
  • 你做除法时,除数是0

这些情况都会导致程序"出错",专业术语叫做抛出异常(Throw Exception)。如果不处理,程序就会崩溃退出。

异常处理就是让程序在遇到错误时,能够优雅地处理,而不是直接"死掉"。

二、生活中的异常处理

例子1:餐厅点餐

  • 正常情况:点了一份炒饭,厨师做好了端上来
  • 异常情况:厨师发现米饭用完了
  • 处理方式:服务员告诉你"抱歉,米饭用完了,要不要试试面条?"

例子2:ATM取钱

  • 正常情况:输入密码正确,取出现金
  • 异常情况:密码错误、余额不足、机器故障
  • 处理方式:显示友好的提示信息,而不是让机器死机

三、仓颉语言中的异常处理

仓颉使用try-catch机制来处理异常。

基础语法

import std.console.* import std.convert.* func 安全地除法(被除数: Int64, 除数: Int64): Int64 { try { return 被除数 / 除数 } catch (异常: Exception) { println("发生错误:${异常.message}") return 0 // 出错时返回默认值 } } main() { var 结果1 = 安全地除法(10, 2) // 正常:5 var 结果2 = 安全地除法(10, 0) // 异常:除数为0 println("结果1:${结果1}") println("结果2:${结果2}") }

运行结果

发生错误:division by zero 结果1:5 结果2:0

四、常见的异常类型

import std.console.* func 演示各种异常(): Unit { // 1. 数组越界异常 try { var 数字列表 = [1, 2, 3] var 值 = 数字列表[10] // 越界了! } catch (异常: IndexOutOfBoundsException) { println("数组越界:${异常.message}") } // 2. 数字转换异常 try { var 文本 = "abc" var 数字 = Int64.parse(文本) // 无法转换! } catch (异常: NumberFormatException) { println("数字格式错误:${异常.message}") } // 3. 空指针异常 try { var 空名字: String? = null var 长度 = 空名字!.length // 空值解引用! } catch (异常: NullPointerException) { println("空指针异常:${异常.message}") } }

五、抛出异常

有时候我们需要自己抛出异常来提示调用者。

// 定义一个检查年龄的函数 func 设置年龄(年龄: Int64): Unit { if (年龄 < 0) { throw Exception("年龄不能为负数!") } if (年龄 > 150) { throw Exception("年龄不能超过150岁!") } println("年龄设置成功:${年龄}岁") } main() { try { 设置年龄(25) // 正常 设置年龄(-5) // 抛出异常 } catch (异常: Exception) { println("错误:${异常.message}") } }

运行结果

年龄设置成功:25岁 错误:年龄不能为负数!

六、语法设计讨论:异常处理中的类型声明

同学们,在学习异常处理时,我们再次遇到了仓颉的类型后置语法问题。

看看异常处理的代码:

try { // 可能出错的代码 } catch (异常: Exception) { // 类型后置! // 处理异常 } func 安全地除法(被除数: Int64, 除数: Int64): Int64 { // 参数和返回值类型都后置 try { return 被除数 / 除数 } catch (异常: Exception) { // 又是类型后置 return 0 } }

按照中国人的语言习惯:

  • 我们习惯说"异常类型的变量"、“整数类型的参数”
  • 我们习惯说"字符串类型的返回值"

但仓颉的写法:

  • catch (异常: Exception)→ 读作"捕获异常,异常类型的"(定语后置)
  • func 函数名(): 返回类型→ 读作"函数名,返回某某类型的"(定语后置)

如果仓颉能改进成C#风格:

// 假设的改进语法 try { // 可能出错的代码 } catch (Exception 异常) { // "异常类型的异常变量"——定语前置! // 处理异常 } Int64 安全地除法(Int64 被除数, Int64 除数) { // "整数类型的安全地除法函数" try { return 被除数 / 除数 } catch (Exception 异常) { return 0 } }

这样读起来多么自然:“定义一个整数类型的函数安全地除法,它有两个整数类型的参数…”

华为在设计仓颉语言时,采用了类似Rust的类型后置语法,这就像是在说"异常异常类型的"而不是"异常类型的异常"。现代汉语都是定语前置的,我们希望中文编程语言能真正符合中国人的语言习惯!

七、finally块

finally块中的代码无论是否发生异常都会执行,常用于清理资源。

func 读取文件(文件名: String): String { var 文件内容 = "" var 文件: File? = null try { 文件 = File.open(文件名, "r") 文件内容 = 文件.readAll() return 文件内容 } catch (异常: Exception) { println("读取文件失败:${异常.message}") return "" } finally { // 无论成功与否,都要关闭文件 if (文件 != null) { 文件.close() println("文件已关闭") } } }

八、自定义异常

我们可以创建自己的异常类型来表示特定的错误。

// 自定义异常类 class 年龄异常 : Exception { init(消息: String) { super(消息) } } class 成绩异常 : Exception { init(消息: String) { super(消息) } } // 使用自定义异常 func 设置学生成绩(成绩: Float64): Unit { if (成绩 < 0) { throw 成绩异常("成绩不能为负数!") } if (成绩 > 100) { throw 成绩异常("成绩不能超过100分!") } println("成绩设置成功:${成绩}分") } main() { try { 设置学生成绩(85.5) 设置学生成绩(105) // 抛出成绩异常 } catch (异常: 成绩异常) { println("成绩错误:${异常.message}") } catch (异常: Exception) { println("其他错误:${异常.message}") } }

九、练习时间

练习1:安全的计算器

创建一个计算器类,包含加、减、乘、除四个方法。除法要处理除数为0的情况,所有方法都要处理可能的溢出异常。

练习2:用户注册验证

创建一个用户注册函数,验证以下内容:

  • 用户名不能为空,长度3-20个字符
  • 密码不能为空,长度6-30个字符
  • 年龄必须在1-150之间
  • 邮箱格式要正确

如果验证失败,抛出相应的异常。

练习3:银行转账系统

创建一个转账函数,需要处理以下异常情况:

  • 转出账户余额不足
  • 转账金额必须大于0
  • 转账金额不能超过单笔限额(比如5万元)
  • 收款账户不存在

十、本课小结

今天我们学习了:

  1. 异常:程序运行时的错误情况
  2. try-catch:捕获并处理异常
  3. throw:主动抛出异常
  4. finally:无论是否异常都会执行的代码块
  5. 自定义异常:创建特定的异常类型

类型语法思考:在异常处理中,我们频繁地声明异常变量类型、函数参数类型、返回值类型,每一次都要面对类型后置的语法。希望未来的中文编程语言能让类型声明更符合中国人的说话习惯,真正做到"说人话"!

十一、课后作业

  1. 完善"学生管理系统"的异常处理:

    • 添加成绩输入验证(0-100分)
    • 添加年龄输入验证(5-30岁)
    • 添加学号格式验证(不能为空,长度固定)
  2. 编写一个文件复制程序,要求:

    • 检查源文件是否存在
    • 检查目标目录是否有写入权限
    • 使用try-catch-finally确保资源正确释放
  3. 思考:在你的日常生活中,还有哪些场景可以用"异常处理"的思路来解决?


下篇预告:第11篇《文件操作——数据的持久化存储》,学习如何将数据保存到文件中,让数据不会随程序关闭而丢失!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 4:46:15

如何快速上手gitsh:10个实用技巧提升Git工作效率

如何快速上手gitsh&#xff1a;10个实用技巧提升Git工作效率 【免费下载链接】gitsh An interactive shell for git 项目地址: https://gitcode.com/gh_mirrors/gi/gitsh gitsh是一款专为Git设计的交互式shell工具&#xff0c;它通过提供命令自动补全、历史记录管理和上…

作者头像 李华
网站建设 2026/5/8 4:45:50

金融工程入门:10个必学的Python量化金融技巧

金融工程入门&#xff1a;10个必学的Python量化金融技巧 【免费下载链接】py4fi2nd Jupyter Notebooks and code for Python for Finance (2nd ed., OReilly) by Yves Hilpisch. 项目地址: https://gitcode.com/gh_mirrors/py/py4fi2nd Python量化金融是现代金融工程的核…

作者头像 李华
网站建设 2026/5/8 4:45:38

技术经理的终极管理指南:如何高效领导技术团队

技术经理的终极管理指南&#xff1a;如何高效领导技术团队 【免费下载链接】interview Everything you need to prepare for your technical interview 项目地址: https://gitcode.com/gh_mirrors/int/interview 作为技术团队的核心领导者&#xff0c;技术经理需要兼具技…

作者头像 李华
网站建设 2026/5/8 4:45:33

Passwordless核心组件详解:TokenStore与Delivery机制深度解析

Passwordless核心组件详解&#xff1a;TokenStore与Delivery机制深度解析 【免费下载链接】passwordless node.js/express module to authenticate users without password 项目地址: https://gitcode.com/gh_mirrors/pa/passwordless Passwordless是一款基于Node.js/Ex…

作者头像 李华
网站建设 2026/5/8 4:45:24

RAG-Challenge-2错误处理与调试:常见问题解决方案

RAG-Challenge-2错误处理与调试&#xff1a;常见问题解决方案 【免费下载链接】RAG-Challenge-2 Implementation of my RAG system that won all categories in Enterprise RAG Challenge 2 项目地址: https://gitcode.com/gh_mirrors/ra/RAG-Challenge-2 RAG-Challenge…

作者头像 李华