Skip to content

第 9 章 异 常

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

9.1 Java 异常处理

public class ExceptionDemo {public static void main(String[] args) { try {int a = 10; int b = 0;int c = a / b;}catch (ArithmeticException e){// catch 时,需要将范围小的写到前面e.printStackTrace();}catch (Exception e){ e.printStackTrace();}finally {System.out.println("finally");}}}

注意事项

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

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

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

9.2 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 表达式可

以用在需要类型的地方

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

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

第 10 章 隐式转换

当编译器第一次编译失败的时候,会在当前的环境中查找能让代码编译通过的方法,用

于将类型进行转换,实现二次编译

10.1 隐式函数

1) 说明

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

2) 案例实操

需求:通过隐式转化为 Int 类型增加方法。

class MyRichInt(val self: Int) { def myMax(i: Int): Int = {if (self < i) i else self} def myMin(i: Int): Int = { if (self < i) self else i}} object TestImplicitFunction {// 使用 implicit 关键字声明的函数称之为隐式函数

implicit def convert(arg: Int): MyRichInt = { new MyRichInt(arg)} def main(args: Array[String]): Unit = {// 当想调用对象功能时,如果编译错误,那么编译器会尝试在当前作用域范围内查找能调用对应功能的转换规则,这个调用过程是由编译器完成的,所以称之为隐式转换。也称之为自动转换println(2.myMax(6))}}

10.2 隐式参数

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

1) 说明

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

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

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

2) 案例实操

object TestImplicitParameter { implicit val str: String = "hello world!" def hello(implicit arg: String="good bey world!"): Unit = { println(arg)} def main(args: Array[String]): Unit = { hello}}

10.3 隐式类

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

1) 隐式类说明

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

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

2) 案例实操

object TestImplicitClass {implicit class MyRichInt(arg: Int) { def myMax(i: Int): Int = {if (arg < i) i else arg} def myMin(i: Int) = {if (arg < i) arg else i}} def main(args: Array[String]): Unit = { println(1.myMax(3))}}

10.4 隐式解析机制

1) 说明

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

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

2) 案例实操

package com.neuedu.chapter10 import com.neuedu.chapter10.Scala05_Transform4.Teacher //(2)如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找。类型的作用域是指与该类型相关联的全部伴生模块,object TestTransform extends PersonTrait { def main(args: Array[String]): Unit = {

//(1)首先会在当前代码作用域下查找隐式实体val teacher = new Teacher() teacher.eat()teacher.say()} class Teacher {def eat(): Unit = { println("eat...")}}} trait PersonTrait { } object PersonTrait {// 隐式类 : 类型 1 => 类型 2implicit class Person5(user:Teacher) { def say(): Unit = { println("say...")}}}

Released under the MIT License.