Scala入门到放弃——异常处理和隐式转换(九)

十二、异常处理

异常

  • Scala 的异常处理和其它语言比如 Java 类似。
  • Scala 的方法可以通过抛出异常的方法的方式来终止相关代码的运行,不必通过返回值。
package exception

import java.io.IOException


/**
  * scala异常分类和java一样的
  * Throwable
  *    |- Error
  *    |- Exception
  *    |- 未检查异常
  *    |- 已检查异常
  *
  * 异常处理的方式:
  *    - 消极处理: throw 异常类 没有throws
  *    - 积极处理: try{...}catch(){...}finally{...}
  */
object ExceptionDemo {
  def main(args: Array[String]): Unit = {
    try {
      println("start")
      // throw new RuntimeException("程序终止!!") // Exception in thread "main" java.lang.RuntimeException: 程序终止!!
      throw new IOException
      println("end")
    } catch {
      // 模式匹配
      case e1: RuntimeException => println("runtime exception")
      case e2: Exception => println("exception")
      case _ => println("xxxx") // 如果以上声明的两种异常不匹配,则进入最后一个
    } finally {
      println("释放资源")
    }
  }
}

十三、隐式转换

隐式转换函数(implicit conversion function)指的是以implicit关键字声明的带有单个参数的函数。这样的函数将被自动应用,将值从一种类型转换为另一种类型。隐式转换函数叫什么名字是无所谓的,因为通常不会由用户手动调用,而是由Scala进行调用。但是如果要使用隐式转换,则需要对隐式转换函数进行导入(import)。因此通常建议将隐式转换函数的名称命名为“one2one”的形式。

常用使用方式:

  • 隐式值
  • 隐式参数
  • 参数的隐式转换
  • 隐式类

Scala会考虑如下位置的隐式转换函数:

  • 位于源或目标类型的伴生对象中的隐式函数
  • 位于当前作用域可以以单个标识符指代的隐式函数

隐式转换在如下三种不同情况下会被考虑:

  • 当表达式类型与预期类型不同时
  • 当对象访问一个不存在成员时
  • 当对象调用某个方法,而这个方法的参数声明与传入参数不匹配时

有三种情况编译器不会尝试使用隐式转换

  • 如果代码能够在不使用隐式转换的前提下通过编译,则不会使用隐式转换
  • 编译器不会尝试同时执行多个转换
  • 存在二义性的转换是错误

隐式值

/**
  * implicit 隐式值
  */
object ImplicitValue {

  // 隐式值声明 对象内部或者作用域
  implicit val name: String = "Hello"

  // implicit val address:String = "bj"  // error

  implicit val sex: Boolean = false // ok


  def main(args: Array[String]): Unit = {
    // 使用隐式值
    val newValue = implicitly[String]
    val newValue2 = implicitly[Boolean]
    println(newValue)
    println(newValue2)
  }
}

隐式参数(传值)

方法或者函数的参数,在声明时有implicit。要求参数之中只能有一个implicit类型匹配。

package implicits

/**
  * 隐式参数
  *
  */
object ImplicitParams {
  // 声明隐式值 缺省值
  implicit var num: Int = 10

  def main(args: Array[String]): Unit = {
    println(sum(10))
    println(sum(10)(20))
  }

  def sum(x: Int)(implicit y: Int): Int = { // y是隐式参数 适用于柯里化函数
    x + y
  }

  //  def sum2(x: Int,implicit y: Int): Int = { // 不可以 普通函数是无法使用隐式参数
  //    x + y
  //  }

  implicit val str: String = "Hello"

  //  def sum3(x: Int)(implicit y: Int)(implicit z: String): Int = { // 不可以 隐式参数只能在柯里化函数中出现一次
  //
  //  }
}

参数隐式转换

class Student(var name: String)

object Implicit1 {
  def main(args: Array[String]): Unit = {
    sayHi("zs")  // 传入的类型和方法的参数类型 不匹配,触发隐式转换 str--->student
  }

  implicit def strToStudent(str: String): Student = {  
    new Student(str)
  }

  def sayHi(student: Student): Unit = {
    println("Hello:" + student.name)
  }
}

隐式转换增强现有类型

object Implicit2 {
  implicit def manToSuperMan(man: Man): SuperMan = new SuperMan(man.name)
  
  def main(args: Array[String]): Unit = {
    val man = new Man("小张")
    man.fly()
  }
}

class Man(val name: String)

class SuperMan(val name: String) {

  def fly(): Unit = {
    println("超人会飞...")
  }
}
隐式类

在上面的例子中为了让人也能够飞,需要在SuperMan中定义fly方法,再写一个隐式转换函数,将Man隐式转换为SuperMan。这种写法过于啰嗦,可以使用隐式类实现等价功能

class Man2(val name: String)

object Implicit5 {
  def main(args: Array[String]): Unit = {
    implicit class SuperMan2(man: Man2) {
      var name: String = _
      def fly = {
        this.name = man.name
        println(s"$name ---> 超人会飞")
      }
    }
    val man = new Man2("zs")
    man.fly
  }
}

隐式类就是在类定义前加一个implicit关键字,这表示它的构造函数是一个隐式转换函数,能够将参数的类型转换成自己的类型,在这里就是构造函数SuperMan2(man: Man2)定义了Man2SuperMan2的隐式转换。

注意:使用隐式类时需要注意以下限制条件

  • 只能在别的trait/类/对象内部定义
  • 构造函数只能携带一个非隐式参数
  • implict关键字不能用于case类

引入隐式转换

隐式值
  • 定义在伴生对象或者作用域
  • 引用其它对象的 import 对象._
package implicits

object Implicit3 {
  // 伴生类的类体
  implicit var x: Int = 0

  def main(args: Array[String]): Unit = {
    // 伴生类的函数体
    implicit var str: String = "Hi"

    import AA._ // 类似于java的静态导入

    var ll: Long = implicitly[Long]
    println(ll)
  }
}

object AA {
  // 其它对象中定义了一个隐式值
  implicit var l: Long = 1000L
}

隐式参数

  • 定义在伴生对象或者作用域或import
package implicits
object Implicit4 {

  def main(args: Array[String]): Unit = {
    implicit var x: Int = 10

    //    def sum(x: Int)(implicit y: Int): Int = {
    //      x + y
    //    }
    import BB._
    println(sum(10))
  }

  // 类体
  //  def sum(x: Int)(implicit y: Int): Int = {
  //    x + y
  //  }
}

object BB {
  def sum(x: Int)(implicit y: Int): Int = {
    x + y
  }
}
参数隐式转换
  • 定义在伴生对象或者作用域
  • 其它类,需要import
package implicits

import CC._

object Implicit5 {
  def main(args: Array[String]): Unit = {
    sayHi("ls")

    //    implicit def str2Student(str: String): Student2 = {
    //      new Student2(str)
    //    }
  }

  def sayHi(student: Student2): Unit = {
    println(student.name)
  }

  //  implicit def str2Student(str: String): Student2 = {
  //    new Student2(str)
  //  }
}

class Student2(var name: String)

object CC {
  implicit def str2Student(str: String): Student2 = {
    new Student2(str)
  }
}
隐式类
package implicits

import DD._

/**
  *
  * 隐式类
  */
object Implicit2 {
  def main(args: Array[String]): Unit = {
    val man2 = new Man2("zs")
    man2.fly
    println(man2.name)

    // 隐式类 接受Man2对象  构建SuperMan2独享
    //    implicit class SuperMan2(man2: Man2) {
    //      var name: String = _
    //
    //      def fly = {
    //        // this.name = man2.name
    //        println("飞翔...")
    //      }
    //    }
  }
}

class Man2(var name: String)

//implicit class SuperMan2(man2: Man2) {  //error
//  var name: String = _
//
//  def fly = {
//    // this.name = man2.name
//    println("飞翔...")
//  }
//}

object DD {

  implicit class SuperMan2(man2: Man2) { //error
    var name: String = _
    def fly = {
      // this.name = man2.name
      println("飞翔...")
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值