栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【scala函数式编程】函数式编程中的异常处理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【scala函数式编程】函数式编程中的异常处理

1. 常见异常处理方式 a. 概念回顾

引用透明:表达式可以被引用的值替代,表达式不依赖上下文

类型安全:在编译时检测到类型异常,而不是在运行时检测到类型异常

异常检测:
1. scala高阶函数高度泛化,传入参数(函数或数值)的类型需要通过推断获得,类型推断必需根据上下文依赖中的显示标记类型推断得出,换句话讲,scala需要高度信任显示标记类型,因此,不能感知由参数类型推断错误以外的特定异常;
2. java强制要求对异常进行处理或抛出,每次编译都会检查上下文依赖中抛出的异常,因此在函数式编程时传入函数如果存在异常,则必需进行相应处理或抛出,会对签名模板进行改变(签名模板包含:名称、类型、次序、异常),会对代码模板进行改变(代码模板包含各种if-else逻辑,用于处理各种可能抛出的常见异常)

b. 处理异常的其他方式
  1. 预前处理:改变参数列表:增加默认参数,在代码中出现以外情况时,使用默认值继续运行(关键词:默认值,目的:防止运行报错)
  2. 预后处理:if-else判断:通过if-else判断,找到代码中可能出现的意外情况,处理或抛出异常(关键词:异常,目的:停止运行)
  3. 预前延迟处理:Option数据类型,定义默认值与正常值
  4. 预后延迟处理:Either数据类型,定义异常与正常值
2. Option类型 a. 定义Option类型

定义顺序类型的基本过程:

  1. 定义基本类型;
  2. 定义用于表示0的对象;
  3. 定义用于表示1-N的类型
// 从trait开始,定义原始类型Option,
sealed trait Option[+A]{
// 为演示函数提升,需要有map函数,this代表任意一个继承了Option的类型的对象,相当于下文optLift函数中的那个(a:Option[A])
    def map[B](f: A => B):Option[B] = this match{
    case None => None // 如果对象类型为None,则直接返回None
    case Some(a) => Some(f(a)) // 如果对象类型为Some(a)类型,则分三步:1.解析出a;2. 计算f(a);3. 用Some封装f(a)
    }
}
// 从0开始,定义空对象None, case object表示静态对象,数量唯一
case object None extends Option[Nothing]
// 从1开始,定义非空类型Some[+A],case class表示静态类,可直接调用
case class Some[+A](get: A) extends Option[A]
b. Option类型的使用
  1. 对值进行检验后封装,有错误正常执行并返回None结果:将A转换为Option[A],若A求值时报错,则返回None,否则返回Some[A]
// 通过修改Try参数a为a: => A和 a: A两种情形,使用Try(1 / 0)来验证catch部分是否生效
// 这里对a惰性求值,按需计算,以便在运行过程中,代码运行至try中时对a进行求值来捕获错误,否则将直接返回Some[Exception]对象,进而绕过catch部分
def Try[A](a: => A):Option[A]={   
    try{Some(a)}catch{case e: Exception => None}
}
  1. 对函数进行提升:A => B 转换为 Option[A] => Optioin[B]
def test(a: Int): String = a.toString
// 构造提升函数对函数A => B进行提升,返回类型为Option[A] => Option[B],因此等号右侧函数实现为(a: Option[A]) => a.map(f): Option[B]
def optLift[A, B](f: A => B): Option[A] => Option[B] = (a: Option[A]) => a.map(f)
// 等价为以下形式,由于返回函数只有一种类型的入参,等号右侧的参数列表可以省略,入参由_代替,返回参数也可以省略
def optLift[A, B](f: A => B): Option[A] => Option[B] = _.map(f)
// 对test函数进行提升
val testOpt = optLift(test)
3. Either类型 a. 定义Either类型

定义树状类型的基本过程:

  1. 定义基本类型;
  2. 定义用于表示左子树的类型,左子树为错误信息;
  3. 定义用于表示右子树的类型,右子树为正常值;
// 从trait开始,定义原始类型Either,此例特殊之处在于左右子树互斥
sealed trait Either[+E, +A]{
// 为演示函数提升,需要有map函数,this代表了任意一个继承了Either的类型的对象,相当于下文eitLift函数中的那个(a: Either[E,A])
    def map[B](f: A => B):Either[E, B] = this match{
    case  Left(e) => Left(e) // 当对象类型为Left时,保持不变
    case Right(a) => Right(f(a)) // 当对象类型为Right时,则分三步:1.解析出a;2.计算f(a);3. 用Right封装f(a)
    }
}
// 定义左子树,只存在左叶子结点,右叶子结点为空
case class Left[+E](value: E) extends Either[E, Nothing]
// 定义右子树,只存在右叶子结点,左叶子结点为空
case class Right[+A](value: A) extends Either[Nothing, A]
b. Either类型的使用
  1. 对值进行检验后封装,报错时返回错误信息:将A封装为Either[E, A],A不能通过校验时显示报错信息,而不是None
sealed class Name(val value: String)
case class Person(name :Name)
def checkName(name:String):Either[String, Name] = {
    if(name == "" || name == null) Left("Name is empty.")
    else Right(new Name(name))
}
  1. 对函数进行提升,报错时返回错误信息:A => B 转换为 Either[E, A] => Either[E, B]
def test(name: Name):Person= Person(name)
// 构造提升函数对函数A => B进行提升,返回类型为Either[E, A] => Either[E, B],因此等号右侧函数实现为(a: Either[E, A]) => a.map(f): Either[E, B]
def eitLift[E,A,B](f: A => B): Either[E, A] => Either[E, B] = (a: Either[E,A]) => a.map(f)
// 等价为以下形式,由于返回函数只有一种类型的入参,等号右侧的参数列表可以省略,入参由_代替,返回参数可以省略
def eitLift[E,A,B](f: A => B): Either[E,A] => Either[E, B] = _.map(f)
// 对test函数进行提升
val testEit = eitLift(test)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/937143.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号