第10章——处理异常

Java 的受检异常(checked exception)会强制开发人员捕获错误,包括那些开发人员并不关 心的,因此 Java 程序员经常会写一个空的 catch 代码块来抑制相关的异常,而不是将其引渡至 合理的位置上进行处理。Scala 不这样做。它让开发人员只处理自己关心的异常,并忽略其他异 常。这些没有处理的异常将会自动地传播。在本章中,我们将学到如何在 Scala 中处理异常。

10.1 Scala 中的异常

ExceptionHandling/Throw.scala

throw new IllegalArgumentException

ExceptionHandling/JavaThreadSleep.java

  // Java code
try {
  Thread.sleep(1000);
}                    
catch(InterruptedException ex) {
  // Losing sleep over what to do here?
}

ExceptionHandling/ThreadSleep.scala

Thread.sleep(1000)

ExceptionHandling/Tax.scala

object Tax {
  def taxFor(amount: Double): Double = {
    if (amount < 0)
      throw new IllegalArgumentException("Amount must be greater than zero")

    if (amount < 0.01)
      throw new RuntimeException("Amount too small to be taxed")

    if (amount > 1000000) throw new Exception("Amount too large...")

    amount * 0.08
  }
}

ExceptionHandling/ExceptionHandling.scala

for (amount <- List(100.0, 0.009, -2.0, 1000001.0)) {
  try {
    print(s"Amount: $$$amount ")
    println(s"Tax: $$${Tax.taxFor(amount)}")
  } catch {
    case ex: IllegalArgumentException => println(ex.getMessage)
    case ex: RuntimeException =>
      // if you need a block of code to handle exception
      println(s"Don't bother reporting...${ex.getMessage}")
  }
}

运行结果

Amount: $100.0 Tax: $8.0
Amount: $0.009 Don't bother reporting...Amount too small to be taxed
Amount: $-2.0 Amount must be greater than zero
Amount: $1000001.0 java.lang.Exception: Amount too large...
	at Tax$.taxFor(Tax.scala:9)
...

ExceptionHandling/CatchAll.scala

for (amount <- List(100.0, 0.009, -2.0, 1000001.0)) {
  try {
    print(s"Amount: $$$amount ")
    println(s"Tax: $$${Tax.taxFor(amount)}")
  } catch {
    case ex: IllegalArgumentException => println(ex.getMessage)
    case _: Throwable => println("Something went wrong")
  }
}

运行结果

Amount: $100.0 Tax: $8.0
Amount: $0.009 Something went wrong
Amount: $-2.0 Amount must be greater than zero
Amount: $1000001.0 Something went wrong

10.2 注意 catch 的顺序

ExceptionHandling/JavaCatchOrder.java

// Java code—will not compile due to incorrect catch order
public class JavaCatchOrder {
  public void catchOrderExample() {
    try {
      String str = "hello";
      System.out.println(str.charAt(31));
    } catch (Exception ex) {
      System.out.println("Exception caught");
    } catch (StringIndexOutOfBoundsException ex) { // ERROR
      System.out.println("Invalid Index");
    }
  }
}

运行结果

JavaCatchOrder.java:10: error: exception StringIndexOutOfBoundsException
has already been caught
    catch(StringIndexOutOfBoundsException ex) { //ERROR
    ^
1 error

ExceptionHandling/CatchOrder.scala

val amount = -2
try {
  print(s"Amount: $$$amount ")
  println(s"Tax: $$${Tax.taxFor(amount)}")
} catch {
  case _: Exception => println("Something went wrong")
  case ex: IllegalArgumentException => println(ex.getMessage)
}

运行结果

Amount: $-2 Something went wrong