异常处理
在Ruby中,抛出异常的信息格式如下:
文件名:行号:in 方法名:错误信息 (异常类名)
from 文件名:行号:in 方法名
以from开头的行表示发生错位的位置。
在Ruby中,使用begin ~ rescue ~ end语句来做异常处理,其语法如下:
begin
可能会发生异常的处理
rescue
发生异常时的处理
end
1 | begin |
通过在rescue后指定变量名,可以获得异常对象。异常对象有两个方法,方法名为class、message、backtrace。
class方法可以获取到异常的种类
message方法获取异常信息。
backtrace方法获取异常发生的位置信息
begin
可能会发生的异常的处理
rescue => 引用异常对象的变量
发生异常时的处理
end
1 | begin |
Note:此处是将代码直接写在ruby文件里,然后直接运行的,没有写在方法里面。所以看到的信息是文件名和发生错误的行号
如果不指定变量名,Ruby将会把异常对象赋值给**$!、$2**变量
- $! 引用到最后发生的异常对象
- $@ 引用到发生的异常的位置信息
1 | begin |
从上面的运行示例可以看出,其实**$!.backtrace与$@**是等价的,都表示异常发生的位置。
在Ruby中可以通过ensure来确保无论是否引发异常都将执行处理,类似于Java和C#中得finally。
begin
可能发生的异常
rescue => 变量
发生异常时的处理
ensure
无论是否有异常,都会处理
end
1 | def copy(from to) |
在rescue中使用retry后,begin以下的处理会再重做一遍。所以需要注意陷入死循环的情况。
1 | count = 0 |
使用rescue做为修饰符
使用rescue作为修饰符可以简化很多代码
表达式1 rescue 表达式2
与下面的写法等价
begin
表达式1
rescue
表达式2
end
其意义为如果表达式1中发生异常,表达式2的值就会成为整体表达式的值。
1 | def parseInt(param) |
在判断字符串是否为数值形式时,可以使用这种方法。
异常处理的其他语法
方法内
如果异常处理的范围是整个方法体,这时可以省略begin以及end关键字,直接使用rescue和ensure。
def 方法名
方法体
rescue => 异常对象
异常处理
ensure
后处理
end
类定义中
在类定义中也可以使用rescue以及ensure。但是,如果类定义途中发生异常,那么异常发生部分后的方法定义就不会再执行了。所以一般很少在类定义中使用。
class 类名
类定义
rescue => 异常对象
异常处理
ensure
后处理
end
指定需要捕捉的异常
当然,Ruby也提供了针对特定异常的捕捉处理,可以使用多个rescue来分开处理
begin
可能发生异常的地方
rescue Exception1, Exception2 =>变量
对Exception1或Exception2的处理
rescue Exception3 => 变量
对Exception3的处理
rescue
对上述异常以外的异常的处理
end
1 | def multi_rescue |
以上代码定义了一个带块的方法,通过此方法可以插入任何你想要得代码执行块。
异常类
注意:ruby中所有异常都是Exception类的子类。
当rescue中不指定异常类时,程序会默认捕捉StandardError类及其子类的异常. 所以在定义自己的异常时,可以先定义继承StandardError类的新类,然后再继承这个新类。
1 | MyError = Class.new(StandardError) |
上面两种写法是等效的,都是表示定义一个继承StandardError类的新类。第一种方式是一种简洁的写法。
1 | MyError = Class.new(StandardError) #自定义MyError异常 |
抛出异常
使用raise方法,可以使程序主动抛出异常。
raise方法有一下4中调用方式:
raise message
抛出RuntimeError异常,并把字符串作为message设置给新生成的异常对象raise 异常类
抛出指定的异常raise 异常类,message
抛出指定的异常,并把message信息设置给新生成的异常对象raise
在rescue外抛出RuntimeError。 在rescue中调用时,会再次抛出最后一次发生的异常。
1 | #自定义MyError3异常 |