Cantin's blog

......

Ruby Raise Exception

| Comments

Exception

Exception是ruby中代表异常的对象。它的实例方法有:

1
2
1.9.3p429 :002 > Exception.instance_methods(false)
 => [:exception, :==, :to_s, :message, :inspect, :backtrace, :set_backtrace]

其中:

message方法会调用to_s方法,用以返回exception的信息。

backtrace返回exception的调用栈,显示形式如下: `Filename: linenumber in methodname`

exception方法比较有趣,当没有参数或者是参数就是exception本身时,它会返回exception本身这个对象, 否则它会调用参数的to_str方法并创建一个新的exception对象。

1
2
3
4
5
6
7
8
9
10
11
12
  1.9.3p429 :003 > a = ArgumentError.new
   => #<ArgumentError: ArgumentError>
  1.9.3p429 :004 > a.object_id
   => 70171868342380
  1.9.3p429 :005 > a.exception.object_id
   => 70171868342380
  1.9.3p429 :006 > a.exception(a).object_id
   => 70171868342380
  1.9.3p429 :007 > b = a.exception('test')
   => #<ArgumentError: test>
  1.9.3p429 :008 > b.object_id
   => 70171868160920

exception方法是ruby与其他语言的异常处理不同之处。下文将会介绍。

Raise

Raise是Kernel的一个方法,用于抛出Exception。

raise有几种调用方式:

1.无参数调用

raise会产生一个新的RuntimeError对象抛出

1
2
3
4
1.9.3p429 :013 > raise
RuntimeError:
  from (irb):13
  from /Users/can/.rvm/rubies/ruby-1.9.3-p429/bin/irb:16:in `<main>'

2.传入一个参数

2.1参数为String

raise会将创建一个新的RuntimeError,并将string参数作为这个对象的message。

1
2
3
4
1.9.3p429 :017 > raise 'test'
RuntimeError: test
  from (irb):17
  from /Users/can/.rvm/rubies/ruby-1.9.3-p429/bin/irb:16:in `<main>'

2.2 参数为Exception Class

raise会调用其new方法,创建一个新的Exception对象

1
2
3
4
1.9.3p429 :018 > raise ArgumentError
ArgumentError: ArgumentError
  from (irb):18
  from /Users/can/.rvm/rubies/ruby-1.9.3-p429/bin/irb:16:in `<main>'

2.3 参数为Exception Object

raise会调用这个object的exception方法,返回exceptin方法生成的exception对象

1
2
3
4
5
6
7
8
9
10
11
12
13
class ArgumentError
  def exception(string = self)
    puts 'exception happen'

    super string
  end
end

raise ArgumentError.new

#output
exception happen
exception.rb:57:in `<main>': ArgumentError (ArgumentError)

3.传入2-3个参数

3.1 2个参数

在2.2-2.3中介绍了,如果第一个参数为Class的话会调用new,为Object的话会调用到exception

而第二个参数会被作为exception的message传入exception的new/exception方法中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class ArgumentError
  def initialize(string = '')
    puts 'Initialize happen'

    super string
  end
  def exception(string = self)
    puts 'exception happen'

    super string
  end
end

begin
  raise ArgumentError, 'test'
rescue => e
  puts e
end

begin
  raise ArgumentError.new, 'test'
rescue => e
  puts e
end

#output
Initialize happen
test
Initialize happen
exception happen
test

3.2 3个参数

第三个参数是指定backtrace, 也就是上面所说的调用栈

Rescue StandardError rather than Exception

rescue默认是处理StandardError。

StandardError是Exception的子类,表示的是在ruby程序中可预见的,比较普通的exception, 如ArgumentError之类的应该被ruby程序处理的异常。

Exception下面还有了其他错误类,如SystemExit, SystemStackError,这些代表了一些更底层,更严重的,恢复可能性更小的exception。 一般来说,ruby程序不应该试图处理这些错误。

当我们自定义Exception时,最好也是继承于StandardError。

而且,rescue时最好不要rescue Exception,因为它会捕捉到其他的如SystemExit这样的错误。

Comments