热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Continuation和高级流程控制

文章标题:Continuation和高级流程控制。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

    流程控制通常非常简单:包括序列化、选择和迭代等过程。很多一直在使用这些基本控制结构的程序员都曾经经历过一段困难的时间来确定哪种流程控制是必需的。本文将简要介绍有关 continuation 的内容,并向您展示如何用最新的方法来考虑流程控制的问题。

很多程序员在首次接触编程之后,并不会太多考虑有关流程控制的问题,因为大部分编程语言都只有几个简单的流程控制结构。然而,流程控制的内容实际上比大部分主流编程语言中提供的更为丰富。有很多并不被大多数人所知的专用语言都具有高级且有用的流程控制结构。

高级流程控制的例子

我们开始了解流程控制的最好方法是查看几个使用不同语言的高级流程控制结构的例子。然后可以将这些知识归纳为一个适用于高级流程控制情况的框架。

大规模退出

第一种高级流程控制技术您可能已经听说过:大规模退出(non-local exit)。大规模退出有几种类型,每种类型都可以划分成两类:结构化的和非结构化的。非结构化大规模退出(Unstructured non-local exit) 就是计算机科学老师警告您不要这样做的一种情况,例如可怕的 goto 语句。实际上,如果得到广泛而正确地使用,非结构化的大规模退出可能会非常有用。例如,在流程控制非常复杂的程序中,它们可以提高程序的可读性。如果复杂的流程控制不能非常自然地嵌套,那么强行使用嵌套结构会使整个程序的可读性变差,而不是变好。有关使用 goto 语句的优缺点的更多信息,请参考本文后面 参考资料 部分给出的链接。

对于结构化的大规模退出(structured non-local exit),您可能熟悉最流行的一种类型:异常。如果您使用 C、Fortran 和 Cobol 的时间已经超过了 20 年,而且一直没有再使用过其他语言,那么请参阅下面对异常的一段简介。

异常 (exception) 是在代码中触发错误或对错误进行局部化的一种方法。通常当错误发生时,我们希望能够对这个错误进行处理。除非我们明确下达继续操作的指示,否则其余的工作不会继续进行。例如,我们可以看一下下面使用 Java™ 语言编写的这个简单的数据库代码:


清单 1. 简单的数据库代码的例子

//NOTE -- this code will not compile, but that's on purpose.
import java.sql.*;
  ...
  public static int testdbcode(Connection conn) {
    //Prepare the statement
    PreparedStatement s = conn.prepareStatement(
       "select id from test_table where name = ?");
    //Set the parameters
    s.setString(1, "fred");
    //Run the query
    ResultSet rs = s.executeQuery()
    //Move to the first result row
    rs.next();
    //Get the answer (first result parameter)
    int id = rs.getInt(1);
    return id;
  }
  ...
      

这段代码的问题是没有错误处理,在处理数据库或其他外部实体时,每个地方都可能产生错误。例如,如果在准备查询时产生了错误,那么设置参数、运行查询以及检索结果就都没什么用了。这个查询在碰到第一个错误之后就毫无意义了。因此在 Java 语言中,提供了一些异常,这让我们可以封装一段代码,这样在碰到第一个错误时就会跳到这段代码上来。要在 Java 语言中实现这种功能,我们可以按照下面的方式重新编写这段代码:


清单 2. 采用异常处理的简单数据库函数

import java.sql.*;
  ...
  public static int testdbcode(Connection conn) {
    try {
      //Prepare the statement
      PreparedStatement s = conn.prepareStatement(
         "select id from test_table where name = ?");
      //Set the parameters
      s.setString(1, "fred");
      //Run the query
      ResultSet rs = s.executeQuery()
      //Move to the first result row
      rs.next();
      //Get the answer (first result parameter)
      int id = rs.getInt(1);
      return id;
    } catch (Exception e) {
      //Put error handling code here
      return -1;
    }
  }
  ...
      

try 中的代码块会一直执行完,除非有一条语句出现了错误。如果触发 了某个错误,就会跳过 try 中的代码块,执行 catch 中的代码块,其中变量 e 中保存了异常的信息。在 Java 中,被触发的错误都是完整的类,因此任何信息都可以放入异常中。实际上,我们可以创建多个 catch 代码块,每个代码块分别用来处理一种特定的异常类。

在上面的代码例子中,我们处理的是系统生成的异常。不过我们也可以创建应用程序级的异常,并对其执行同样的处理。应用程序可以在任意时刻使用 throw 关键字触发异常。例如,我们可以说如果上面的代码中 ID 值为 1,那么就可以认为这是一个应用程序级的异常。我们可以使用下面的方式:


清单 3. 触发应用程序级异常的简单数据库的例子

import java.sql.*;
  ...
  public static int testdbcode(Connection conn) {
    try {
      //Prepare the statement
      PreparedStatement s = conn.prepareStatement(
         "select id from test_table where name = ?");
      //Set the parameters
      s.setString(1, "fred");
      //Run the query
      ResultSet rs = s.executeQuery()
      //Move to the first result row
      rs.next();
      //Get the answer (first result parameter)
      int id = rs.getInt(1);
      //Check for application exception
      if(id == 0) {
        //Signal the exception
        //Assume that InvalidUserIDException is defined elsewhere
        throw new InvalidUserIDException();
      }
      return id;
    } catch (InvalidUserIDException e) {
      //Specialized error handling here
      return -1;
    } catch (Exception e) {
      //Handle all other errors here
      return -1;
    }
  }
  ...
      

另外,处理异常的代码没有理由只能放在函数本身中。trycatch 语句也可以放到任何包含函数(containing function)中。异常处理机制会展开堆栈,直到它到达一个合适的异常处理程序,此时程序就会执行异常处理代码。这种执行结构化大规模退出的能力可以极大地简化代码的编写,以及对代码的维护工作,因为在某些情况下,错误处理与实际实现功能的代码是完全分隔开的。当然,这一切都非常简单。异常处理还有几个主要的功能,这已经超出了本文介绍的范围,不过 参考资料 中的部分内容可以为您提供这方面的帮助。

 

[1] [2] [3] [4] [5] 下一页


推荐阅读
  • 深入理解C++中的KMP算法:高效字符串匹配的利器
    本文详细介绍C++中实现KMP算法的方法,探讨其在字符串匹配问题上的优势。通过对比暴力匹配(BF)算法,展示KMP算法如何利用前缀表优化匹配过程,显著提升效率。 ... [详细]
  • 深入理解Java中的volatile、内存屏障与CPU指令
    本文详细探讨了Java中volatile关键字的作用机制,以及其与内存屏障和CPU指令之间的关系。通过具体示例和专业解析,帮助读者更好地理解多线程编程中的同步问题。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • MySQL缓存机制深度解析
    本文详细探讨了MySQL的缓存机制,包括主从复制、读写分离以及缓存同步策略等内容。通过理解这些概念和技术,读者可以更好地优化数据库性能。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
  • 精选30本C# ASP.NET SQL中文PDF电子书合集
    欢迎订阅我们的技术博客,获取更多关于C#、ASP.NET和SQL的最新资讯和资源。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 构建基于BERT的中文NL2SQL模型:一个简明的基准
    本文探讨了将自然语言转换为SQL语句(NL2SQL)的任务,这是人工智能领域中一项非常实用的研究方向。文章介绍了笔者在公司举办的首届中文NL2SQL挑战赛中的实践,该比赛提供了金融和通用领域的表格数据,并标注了对应的自然语言与SQL语句对,旨在训练准确的NL2SQL模型。 ... [详细]
  • 本文详细介绍了HTML中标签的使用方法和作用。通过具体示例,解释了如何利用标签为网页中的缩写和简称提供完整解释,并探讨了其在提高可读性和搜索引擎优化方面的优势。 ... [详细]
  • 数据库内核开发入门 | 搭建研发环境的初步指南
    本课程将带你从零开始,逐步掌握数据库内核开发的基础知识和实践技能,重点介绍如何搭建OceanBase的开发环境。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
author-avatar
手机用户2502932937
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有