Scala-异常处理、隐式转换以及泛型简单了解

异常处理

语法处理上和 Java 类似,但是又不尽相同。

(1)Java 语言按照 try—catch—finally 的方式来处理异常

(2)不管有没有异常捕获,都会执行 finally,因此通常可以在 finally 代码块中释放资
源。

(3)可以有多个 catch,分别捕获对应的异常,这时需要把范围小的异常类写在前面,
把范围大的异常类写在后面,否则编译错误。

scala的异常处理:

def main(args: Array[String]): Unit = {
    try {
    	var n= 10 / 0
    } catch {
        case ex: ArithmeticException=>{
            // 发生算术异常
            println("发生算术异常")
        }
        case ex: Exception=>{
            // 对异常处理
            println("发生了异常 1")
            println("发生了异常 2")
        }
    } finally {
   		println("finally")
    }
}

1)我们将可疑代码封装在 try 块中。在 try 块之后使用了一个 catch 处理程序来捕获异常。如果发生任何异常,catch 处理程序将处理它,程序将不会异常终止。

2)Scala 的异常的工作机制和 Java 一样,但是 Scala 没有“checked(编译期)”异常,即 Scala 没有编译异常这个概念,异常都是在运行的时候捕获处理。

3)异常捕捉的机制与其他语言中一样,如果有异常发生,catch 子句是按次序捕捉的。因此,在 catch 子句中,越具体的异常越要靠前,越普遍的异常越靠后,如果把越普遍的异常写在前,把具体的异常写在后,在 Scala 中也不会报错,但这样是非常不好的编程风格。

4)finally 子句用于执行不管是正常处理还是有异常发生时都需要执行的步骤,一般用于对象的清理工作,这点和 Java 一样。

5)用 throw 关键字,抛出一个异常对象。所有异常都是 Throwable 的子类型throw 表达式是有类型的,就是 Nothing,因为 Nothing 是所有类型的子类型,所以 throw 表达式可以用在需要类型的地方

def test():Nothing = {
	throw new Exception("不对")
}

6)java 提供了 throws 关键字来声明异常。可以使用方法定义声明异常。它向调用者函数提供了此方法可能引发此异常的信息。它有助于调用函数处理并将该代码包含在 try-catch块中,以避免程序异常终止。在 Scala 中,可以使用 throws 注解来声明异常

def main(args: Array[String]): Unit = {
	f11()
}
@throws(classOf[NumberFormatException])
def f11()={
	"abc".toInt
}

隐式转换

当编译器第一次编译失败的时候,会在当前的环境中查找能让代码编译通过的方法,用于将类型进行转换,实现二次编译,即在二次编译的时候做隐式转换,当想调用对象功能时,如果编译错误,那么编译器会尝试在当前作用域范围内查找能调用对应功能的转换规则,这个调用过程是由编译器完成的,所以称之为隐式转换。也称之为自动转换

隐式函数

隐式转换可以在不需改任何代码的情况下,扩展某个类的功能。

使用 implicit 关键字声明的函数称之为隐式函数

隐式参数

普通方法或者函数中的参数可以通过 implicit 关键字声明为隐式参数,调用该方法时,就可以传入该参数,编译器会在相应的作用域寻找符合条件的隐式值。

(1)同一个作用域中,相同类型的隐式值只能有一个

(2)编译器按照隐式参数的类型去寻找对应类型的隐式值,与隐式值的名称无关。

(3)隐式参数优先于默认参数

隐式类

在 Scala2.10 后提供了隐式类,可以使用 implicit 声明类,隐式类的非常强大,同样可以扩展类的功能,在集合中隐式类会发挥重要的作用。

(1)其所带的构造参数有且只能有一个

(2)隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是顶级的。

隐式解析机制

(1)首先会在当前代码作用域下查找隐式实体(隐式方法、隐式类、隐式对象)。(一般是这种情况)

(2)如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。类型的作用域是指与该类型相关联的全部伴生对象以及该类型所在包的包对象

object TestImplicit {

    def main(args: Array[String]): Unit = {
        val new12 = new MyRichInt(12)
        println(new12.myMax(15)) // 15

        // 1. 隐式函数
        implicit def convert(num: Int): MyRichInt = new MyRichInt(num)
        println(12.myMax(15))    // 15

        println("=======================")

        // 2. 隐式类
        implicit class MyRichInt2(val self: Int) {
            // 自定义比较大小的方法
            def myMax2(n: Int): Int = if (n < self) self else n
            def myMin2(n: Int): Int = if (n > self) self else n
        }

        println(12.myMax2(15))    // 15
        println(12.myMin2(15))    // 12

        println("=======================")

        // 3.隐式参数
        implicit val str: String = "alice"
        implicit val age: Int = 18

        def sayHello()(implicit name: String): Unit ={
            println("hello, " + name)
        }
        def sayHi(implicit name: String = "bobo"): Unit ={
            println("hi, " + name)
        }
        sayHello() // hello, alice
        sayHi      // hi, alice

        // 简便的写法
        def hiAge(): Unit = {
            println("hi, " + implicitly[Int])
        }
        hiAge()    // hi, 18
    }
}

// 自定义一个类
class MyRichInt(val self: Int) {
    // 自定义比较大小的方法
    def myMax(n: Int): Int = if (n < self) self else n
    def myMin(n: Int): Int = if (n > self) self else n
}

泛型

协变和逆变

class MyList[+T]{ //协变
    
}
class MyList[-T]{ //逆变
    
}
class MyList[T] //不变

协变:Son 是 Father 的子类,则 MyList[Son] 也作为 MyList[Father]的“子类”。
逆变:Son 是 Father 的子类,则 MyList[Son]作为 MyList[Father]的“父类”。
不变:Son 是 Father 的子类,则 MyList[Father]与 MyList[Son]“无父子关系”。

泛型上下限

Class PersonList[T <: Person]{ //泛型上限
    
}
Class PersonList[T >: Person]{ //泛型下限
    
}

泛型的上下限的作用是对传入的泛型进行限定。

上下文限定

def f[A : B](a: A) = println(a) //等同于 def f[A](a:A)(implicit arg:B[A])=println(a)

上下文限定是将泛型和隐式转换的结合产物,以下两者功能相同,使用上下文限定[A :Ordering]之后,方法内无法使用隐式参数名调用隐式参数,需要通过 **implicitly[Ordering[A]]**获取隐式变量,如果此时无法查找到对应类型的隐式变量,会发生出错误。

object TestGenerics {

    def main(args: Array[String]): Unit = {
        // 1、协变和逆变
        val child: Parent = new Child
        val childList: MyCollection1[Parent] = new MyCollection1[Child]
        val childList2: MyCollection2[SubChild] = new MyCollection2[Child]

        // 2.上下限
        def test[A <: Child](a: A): Unit ={
            println(a.getClass.getName)
        }

//        test[Parent](new Child) // error
        test[Child](new Child) // com.starnet.scala.other.Child
        test[SubChild](new SubChild) // com.starnet.scala.other.SubChild
    }
}

// 定义继承关系
class Parent {}
class Child extends Parent {}
class SubChild extends Child {}

// 定义带泛型的集合类型
class MyCollection1[+E] {}
class MyCollection2[-E] {}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值